图像处理之倒角距离变换

简介: 图像处理之倒角距离变换

图像处理之倒角距离变换

图像处理中的倒角距离变换(Chamfer Distance Transform)在对象匹配识别中经常用到,

算法基本上是基于3x3的窗口来生成每个像素的距离值,分为两步完成距离变换,第一

步从左上角开始,从左向右、从上到下移动窗口扫描每个像素,检测在中心像素x的周

围0、1、2、3四个像素,保存最小距离与位置作为结果,图示如下:

第二步从底向上、从右向左,对每个像素,检测相邻像素4、5、6、7保存最小距离与

位置作为结果,如图示所:

完成这两步以后,得到的结果输出即为倒角距离变换的结果。完整的图像倒角距离变

换代码实现可以分为如下几步:

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

  离为0

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

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

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

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

完整的二值图像倒角距离变换的源代码如下:

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);
  }
 
}
相关文章
|
6月前
|
算法 计算机视觉
图像处理之距离变换
图像处理之距离变换
116 8
|
6月前
|
算法 API 计算机视觉
图像处理之角点检测与亚像素角点定位
图像处理之角点检测与亚像素角点定位
79 1
|
6月前
|
算法 计算机视觉
图像处理之积分图应用四(基于局部均值的图像二值化算法)
图像处理之积分图应用四(基于局部均值的图像二值化算法)
558 0
|
6月前
|
算法 计算机视觉
图像处理之基于一维高斯快速模糊
图像处理之基于一维高斯快速模糊
40 8
|
6月前
|
算法 计算机视觉
图像处理之错切变换
图像处理之错切变换
123 1
|
6月前
|
算法 计算机视觉
图像处理之图像快速旋转算法
图像处理之图像快速旋转算法
457 1
|
6月前
|
算法 计算机视觉
图像处理之基于采样距离变换算法
图像处理之基于采样距离变换算法
42 0
|
6月前
|
算法 C语言 计算机视觉
图像处理之图像快速插值放缩算法
图像处理之图像快速插值放缩算法
41 0
|
6月前
|
算法 计算机视觉
图像处理之霍夫变换圆检测算法
图像处理之霍夫变换圆检测算法
72 0
|
6月前
|
算法 计算机视觉
图像处理之Lanczos采样放缩算法
图像处理之Lanczos采样放缩算法
93 0