国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開(kāi)發(fā) > Java > 正文

java圖像處理之倒角距離變換

2024-07-13 10:16:58
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

圖像處理中的倒角距離變換(Chamfer Distance Transform)在對(duì)象匹配識(shí)別中經(jīng)常用到,算法基本上是基于3x3的窗口來(lái)生成每個(gè)像素的距離值,分為兩步完成距離變換,第一步從左上角開(kāi)始,從左向右、從上到下移動(dòng)窗口掃描每個(gè)像素,檢測(cè)在中心像素x的周圍0、1、2、3四個(gè)像素,保存最小距離與位置作為結(jié)果,圖示如下:

java,倒角,距離變換,java二值圖像倒角距離變換,java倒角距離

第二步從底向上、從右向左,對(duì)每個(gè)像素,檢測(cè)相鄰像素4、5、6、7保存最小距離與位置作為結(jié)果,如圖示所:

java,倒角,距離變換,java二值圖像倒角距離變換,java倒角距離

完成這兩步以后,得到的結(jié)果輸出即為倒角距離變換的結(jié)果。完整的圖像倒角距離變換代碼實(shí)現(xiàn)可以分為如下幾步:

1.對(duì)像素?cái)?shù)組進(jìn)行初始化,所有背景顏色像素點(diǎn)初始距離為無(wú)窮大,前景像素點(diǎn)距離為0

2.開(kāi)始倒角距離變換中的第一步,并保存結(jié)果

3.基于第一步結(jié)果完成倒角距離變換中的第二步

4.根據(jù)距離變換結(jié)果顯示所有不同灰度值,形成圖像

最終結(jié)果顯示如下(左邊表示原圖、右邊表示CDT之后結(jié)果)

java,倒角,距離變換,java二值圖像倒角距離變換,java倒角距離

完整的二值圖像倒角距離變換的源代碼如下:

package com.gloomyfish.image.transform;  import java.awt.Color; import java.awt.image.BufferedImage; import java.util.Arrays;  import com.gloomyfish.filter.study.AbstractBufferedImageOp;  public class CDTFilter extends AbstractBufferedImageOp {   private float[] dis; // nn-distances   private int[] pos; // nn-positions, 32 bit index   private Color bakcgroundColor;      public CDTFilter(Color bgColor)   {     this.bakcgroundColor = bgColor;   }    @Override   public BufferedImage filter(BufferedImage src, BufferedImage dest) {     int width = src.getWidth();     int height = src.getHeight();      if (dest == null)       dest = createCompatibleDestImage(src, null);      int[] inPixels = new int[width * height];     pos = new int[width * height];     dis = new float[width * height];     src.getRGB(0, 0, width, height, inPixels, 0, width);     // 隨機(jī)生成距離變換點(diǎn)     int index = 0;     Arrays.fill(dis, Float.MAX_VALUE);     int numOfFC = 0;     for (int row = 0; row < height; row++) {       for (int col = 0; col < width; col++) {         index = row * width + col;         if (inPixels[index] != bakcgroundColor.getRGB()) {           dis[index] = 0;           pos[index] = index;           numOfFC++;         }       }     }     final float d1 = 1;     final float d2 = (float) Math.sqrt(d1 * d1 + d1 * d1);     System.out.println(numOfFC);     float nd, nd_tmp;     int i, in, cols, rows, nearestPixel;      // 1 2 3     // 0 i 4     // 7 6 5     // first pass: forward -> L->R, T-B     for (rows = 1; rows < height - 1; rows++) {       for (cols = 1; cols < width - 1; cols++) {         i = rows * width + cols;          nd = dis[i];         nearestPixel = pos[i];         if (nd != 0) { // skip background pixels           in = i;            in += -1; // 0           if ((nd_tmp = d1 + dis[in]) < nd) {             nd = nd_tmp;             nearestPixel = pos[in];           }            in += -width; // 1           if ((nd_tmp = d2 + dis[in]) < nd) {             nd = nd_tmp;             nearestPixel = pos[in];           }            in += +1; // 2           if ((nd_tmp = d1 + dis[in]) < nd) {             nd = nd_tmp;             nearestPixel = pos[in];           }            in += +1; // 3           if ((nd_tmp = d2 + dis[in]) < nd) {             nd = nd_tmp;             nearestPixel = pos[in];           }            dis[i] = nd;           pos[i] = nearestPixel;         }       }     }      // second pass: backwards -> R->L, B-T     // exactly same as first pass, just in the reverse direction     for (rows = height - 2; rows >= 1; rows--) {       for (cols = width - 2; cols >= 1; cols--) {         i = rows * width + cols;          nd = dis[i];         nearestPixel = pos[i];         if (nd != 0) {           in = i;            in += +1; // 4           if ((nd_tmp = d1 + dis[in]) < nd) {             nd = nd_tmp;             nearestPixel = pos[in];           }            in += +width; // 5           if ((nd_tmp = d2 + dis[in]) < nd) {             nd = nd_tmp;             nearestPixel = pos[in];           }            in += -1; // 6           if ((nd_tmp = d1 + dis[in]) < nd) {             nd = nd_tmp;             nearestPixel = pos[in];           }            in += -1; // 7           if ((nd_tmp = d2 + dis[in]) < nd) {             nd = nd_tmp;             nearestPixel = pos[in];           }            dis[i] = nd;           pos[i] = nearestPixel;          }       }     }      for (int row = 0; row < height; row++) {       for (int col = 0; col < width; col++) {         index = row * width + col;         if (Float.MAX_VALUE != dis[index]) {           int gray = clamp((int) (dis[index]));           inPixels[index] = (255 << 24) | (gray << 16) | (gray << 8)               | gray;         }       }     }     setRGB(dest, 0, 0, width, height, inPixels);     return dest;   }    private int clamp(int i) {     return i > 255 ? 255 : (i < 0 ? 0 : i);   }  } 

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VeVb武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到JAVA教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 巴里| 确山县| 沙河市| 西贡区| 绥芬河市| 乳山市| 永吉县| 平南县| 遂川县| 贵定县| 承德县| 乐东| 德令哈市| 郑州市| 潜江市| 万安县| 财经| 澳门| 鄯善县| 全南县| 宜丰县| 松江区| 西盟| 青海省| 湟源县| 安吉县| 灌南县| 沧源| 车险| 始兴县| 昭觉县| 兴和县| 高淳县| 广宗县| 巴里| 金门县| 许昌县| 淮北市| 祥云县| 阜新市| 迭部县|