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实现的计算最大下标距离算法示例
  • Java动态规划之编辑距离问题示例代码
  • 利用java、js或mysql计算高德地图中两坐标之间的距离
  • Java实现控制台输出两点间距离
  • Java编程获取经纬度之间距离的方法
  • java实现计算地理坐标之间的距离
  • java计算两点间的距离方法总结
(0)

相关推荐

  • Java动态规划之编辑距离问题示例代码

    动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移.一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划. 动态规划实际上是一类题目的总称,并不是指某个固定的算法.动态规划的意义就是通过采用递推(或者分而治之)的策略,通过解决大问题的子问题从而解决整体的做法.动态规划的核心思想是巧妙的将问题拆分成多个子问题,通过计算子问题而得到整体问题的解.而子问题又可以拆分成更多的子问题,从而用类似递推迭代的方法解决要求的问题.问题描述: 对于序列S和T,

  • java计算两点间的距离方法总结

    使用java自带的Point类 import java.awt.Point;//引用awt包下的Point类,此类的功能是表示 (x,y) 坐标空间中的位置的点 public class Distance { public static void main(String[] args) { Point p1 = new Point(5, 6);// 定义第一个点的坐标(5,6) Point p2 = new Point(7,8);// 定义第二个点的坐标(7,8) //定位坐标 System.o

  • Java实现的计算最大下标距离算法示例

    本文实例讲述了Java实现的计算最大下标距离算法.分享给大家供大家参考,具体如下: 题目描述 给定一个整形数组,找出最大下标距离j−i, 当且A[i] < A[j] 和 i < j 解法 复杂度:三次扫描,每次的复杂度O(N) 算法:{5,3,4,0,1,4,1} 找出从第一个元素开始的下降序列{5,3,0} i=3,j=6, j从尾部扫描 初始化,i=3, j=6, A[i]=0 实现代码 public static int maxindexdistance(int A[]) { boole

  • Java编程获取经纬度之间距离的方法

    本文实例讲述了Java编程获取经纬度之间距离的方法.分享给大家供大家参考,具体如下: public class GeoUtil { /** * 根据经纬度和距离返回一个矩形范围 * * @param lng * 经度 * @param lat * 纬度 * @param distance * 距离(单位为米) * @return [lng1,lat1, lng2,lat2] 矩形的左下角(lng1,lat1)和右上角(lng2,lat2) */ public static double[] ge

  • Java实现控制台输出两点间距离

    计算两点之间的距离然后在控制台输出,这个题目还是挺简单的.下面我们来看看具体代码. package com.swift; import java.util.Scanner; public class PToP { public static void main(String[] args) { Scanner scan=new Scanner(System.in); System.out.println("请输入第一个点的坐标值x1"); Double x1=Double.parseD

  • 利用java、js或mysql计算高德地图中两坐标之间的距离

    前言 因为工作的原因,最近在做与地图相关的应用,使用了高德地图,研究了下高德地图计算两坐标距离的方法,官网上提供的开发包中有相关的方法,但是我的产品中比较特殊,无法直接使用提供的方法,所以就自己封装了相关计算方法,供大家参考,下面话不多说了,来一起看看详细的介绍吧. Java实现 首先定义一个用于存储经纬度的类,这里起个名字叫:LngLat package amap; import java.text.DecimalFormat; import java.text.DecimalFormatSy

  • java实现计算地理坐标之间的距离

    java实现计算两经纬度点之间的距离,直接上代码,具体解释请参考注释 复制代码 代码如下: package com.jttx.poi.utils; import com.jttx.poi.entity.Point; /**  * Created by louis on 2014/9/2.  */ public class GeoUtils {     /**      * 计算两经纬度点之间的距离(单位:米)      * @param lng1  经度      * @param lat1 

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

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

  • OpenCV实现图像距离变换

    图像中两个像素之间的距离有多种定义方式,图像处理中常用的距离有欧式距离.街区距离和棋盘距离 欧式距离 略 街区距离 两个像素点X方向和Y方向的距离之和.欧式距离表示的是从一个像素点到另一个像素点的最短距离,然而有时我们并不能以两个点之间连线的方向前进,例如在一个城市内两点之间的连线可能存在障碍物的阻碍,因此从一个点到另一个点需要沿着街道行走,因此这种距离的度量方式被称为街区距离.街区距离就是由一个像素点到另一个像素点需要沿着X方向和Y方向一共行走的距离,数学表示形式如式所示. 棋盘距离 两个像素

  • OpenCV基于距离变换和分水岭实现图像分割

    目录 一.图像分割 二.基于距离变换和分水岭的图像分割 代码实现 图像处理效果 一.图像分割 图像分割是根据灰度.颜色.纹理和形状等特征,把图像分成若干个特定的.具有独特性质的区域,这些特征在同一区域内呈现出相似性,而在不同区域间呈现出明显的差异性,并提出感兴趣目标的技术和过程. 它是由图像处理到图像分析的关键步骤.从数学角度来看,图像分割是将数字图像划分成互不相交的区域的过程.图像分割的过程也是一个标记过程,即把属于同一区域的像索赋予相同的编号. 其目的是将图像中像素根据一定的规则分为若干(N

  • 基于OpenCv与JVM实现加载保存图像功能(JAVA 图像处理)

    目录 加载图片 保存图片 加载图片 openCv有一个名imread的简单函数,用于从文件中读取图像 imread 函数位于Imgcodecs类的同名包中. 加载图片代码 import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.Core; import org.opencv.imgcodecs.Imgcodecs; import origami.Origami; public class

  • Java图像处理之RGB调色面板

    本文实例为大家分享了Java图像处理之RGB调色面板的具体代码,供大家参考,具体内容如下 一.概述 因为我们知道颜色是由R.G.B.三种颜色所组成的,那么我们只需要更改这三个的数值.我们就可以实现一个简单的调色面板:以下是代码演示: 二.代码 import javax.swing.*; import java.awt.*; import java.awt.event.ActionListener; import java.awt.event.*; public class RgbJpanel {

  • Java图像处理之获取用户感兴趣的区域

    目录 需求背景 概念解释 ROI openCV 掩膜mask 代码实现 效果如下 工具类 需求背景 获取ROI图片:现在有一张图片,用户能够在坐标上选择一些点组成一个区域,这个区域称为用户感兴趣的区域,需要利用mask掩膜生成,需要生成mask图片.ROI图片,要求使用OpenCV+Java实现. 概念解释 ROI ROI: region of interest 感兴趣的区域 openCV OpenCV(Open Source Computer Vision Library)是一个开源的计算机视

  • Java图像处理工具类

    本工具类的功能:缩放图像.切割图像.图像类型转换.彩色转黑白.文字水印.图片水印等 复制代码 代码如下: package net.kitbox.util; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Re

  • Java图像处理教程之正片叠底效果的实现

    前言 本文主要给大家介绍了关于利用Java如何实现正片叠底效果的方法,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 正片叠底,在Photoshop中是一种混合模式,简单的说就是可以让2个图层的内容融合起来. PS中最佳展示用例 融合的计算公式其实非常简单,就是 A*B/255.(A.B是指的图层A和图层B) 再解释一下就是: A图层中的红色通道和B图层中的红色通道所对应的每一个像素的灰阶值相乘,再被255除.得到一个新的红色通道. 蓝色与绿色通道的操作也是一样的. 实现方法

随机推荐