首页 > 开发 > Java > 正文

java图像处理之倒角距离变换

2024-07-13 10:16:58
字体:
来源:转载
供稿:网友

图像处理中的倒角距离变换(Chamfer Distance Transform)在对象匹配识别中经常用到,算法基本上是基于3x3的窗口来生成每个像素的距离值,分为两步完成距离变换,第一步从左上角开始,从左向右、从上到下移动窗口扫描每个像素,检测在中心像素x的周围0、1、2、3四个像素,保存最小距离与位置作为结果,图示如下:

java,倒角,距离变换,java二值图像倒角距离变换,java倒角距离

第二步从底向上、从右向左,对每个像素,检测相邻像素4、5、6、7保存最小距离与位置作为结果,如图示所:

java,倒角,距离变换,java二值图像倒角距离变换,java倒角距离

完成这两步以后,得到的结果输出即为倒角距离变换的结果。完整的图像倒角距离变换代码实现可以分为如下几步:

1.对像素数组进行初始化,所有背景颜色像素点初始距离为无穷大,前景像素点距离为0

2.开始倒角距离变换中的第一步,并保存结果

3.基于第一步结果完成倒角距离变换中的第二步

4.根据距离变换结果显示所有不同灰度值,形成图像

最终结果显示如下(左边表示原图、右边表示CDT之后结果)

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);     // 随机生成距离变换点     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);   }  } 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VeVb武林网。


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表