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

 更新时间:2018年01月19日 10:53:52   作者:gloomyfish  
这篇文章主要为大家详细介绍了java图像处理之倒角距离变换的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

图像处理中的倒角距离变换(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); 
  } 
 
} 

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

相关文章

  • 利用Java Apache POI 生成Word文档示例代码

    利用Java Apache POI 生成Word文档示例代码

    本篇文章主要介绍了利用Java Apache POI 生成Word文档示例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • Java使用递归解决算法问题的实例讲解

    Java使用递归解决算法问题的实例讲解

    递归算法的实质是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解,这里我们就来看几个Java使用递归解决算法问题的实例讲解
    2016-06-06
  • Mybatis之Select Count(*)的获取返回int的值操作

    Mybatis之Select Count(*)的获取返回int的值操作

    这篇文章主要介绍了Mybatis之Select Count(*)的获取返回int的值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • SpringSceurity实现短信验证码登陆

    SpringSceurity实现短信验证码登陆

    这篇文章主要介绍了SpringSceurity实现短信验证码登陆,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • Java语言实现最大堆代码示例

    Java语言实现最大堆代码示例

    这篇文章主要介绍了Java语言实现最大堆代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-12-12
  • Springboot中@Value注解的场景用法及可能遇到的问题详解

    Springboot中@Value注解的场景用法及可能遇到的问题详解

    这篇文章主要给大家介绍了关于Springboot中@Value注解的场景用法及可能遇到问题的相关资料, @Value通常用于注入外部化属性,即外部配置属性的注入,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • java调用接口返回乱码问题及解决

    java调用接口返回乱码问题及解决

    这篇文章主要介绍了java调用接口返回乱码问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • 盘点SpringBoot中@Async注解的遇到的坑点及解决办法

    盘点SpringBoot中@Async注解的遇到的坑点及解决办法

    SpringBoot是一个流行的Java开发框架,在异步编程方面,Spring Boot提供了@Async注解,它能够让方法异步执行,然而,在使用@Async注解时,有一些潜在的坑需要注意,本文将深入探讨Spring Boot中使用@Async注解时可能遇到的8大坑点,并提供相应的解决方案
    2024-03-03
  • Spring Boot如何支持嵌入式Servlet容器

    Spring Boot如何支持嵌入式Servlet容器

    这篇文章主要介绍了Spring Boot如何支持嵌入式Servlet容器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Spring实战之使用ClassPathResource加载xml资源示例

    Spring实战之使用ClassPathResource加载xml资源示例

    这篇文章主要介绍了Spring实战之使用ClassPathResource加载xml资源,结合实例形式分析了Spring使用ClassPathResource加载xml资源的具体实现步骤与相关操作技巧,需要的朋友可以参考下
    2019-12-12

最新评论