java图像识别出距离_java图像处理之倒角距离变换

本文介绍了Java中如何实现图像处理的倒角距离变换算法,该算法常用于对象匹配识别。通过3x3窗口扫描每个像素,分别进行前后两步距离计算,最终得到每个像素点的倒角距离变换结果。文章提供了完整的Java代码实现,包括初始化、两步距离变换和结果显示的过程。
摘要由CSDN通过智能技术生成

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

4125d6163cf748e49e65af6e0f13b86a.png

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

7001d9b0851d0b06127ad8f2491d8824.png

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

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

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

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

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

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

10d2d2398d651753a2388cac6e8172b2.png

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

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);

}

}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值