您的位置:首页 > 其它

图像处理之基于采样距离变换算法

2016-07-29 00:00 806 查看
图像处理之基于采样距离变换算法

算法是别人提出来的,感兴趣可以搜索《Distance Transforms of Sampled Functions》

这篇论文,网上也有很多实现的代码,但是结构不是很好,而且很分散不是一个完整的

算法。所以我整理了一下,写成一个单独的类,只要简单调用一下即可出结果图片。

至于算法原理什么的,我真很难解释清楚,大致的思想是基于能量最小化的,分别

进行行与列的1D距离变变换采样。

运行结果:



算法代码:

package com.gloomyfish.image.transform;

import java.awt.image.BufferedImage;

import com.gloomyfish.filter.study.GrayFilter;
/**
*
* @author gloomyfish
*
*/
public class FastDistanceTransformAlg extends GrayFilter {
public final static double INF = 1E20;
private int backgroundColor = 0; // default black

public int getBackgroundColor() {
return backgroundColor;
}

public void setBackgroundColor(int backgroundColor) {
this.backgroundColor = backgroundColor;
}

@Override
public BufferedImage filter(BufferedImage src, BufferedImage dest) {
int width = src.getWidth();
int height = src.getHeight();
dest = super.filter(src, null);

//
int[] inPixels = new int[width*height];
float[] outPixels = new float[width*height];
getRGB( dest, 0, 0, width, height, inPixels );
int index = 0;
for(int row=0; row<height; row++) {
int tr = 0;
for(int col=0; col<width; col++) {
index = row * width + col;
tr = (inPixels[index] >> 16) & 0xff;
if(tr == backgroundColor)
outPixels[index] = (float)INF;
else
outPixels[index] = 0;
}
}

// transform along columns
float[] f = new float[Math.max(width, height)];
for(int col=0; col<width; col++) {
for(int row=0; row<height; row++) {
index = row * width + col;
f[row] = outPixels[index];
}
float[] disColumns = distance1DTransform(f, height);
for(int row=0; row<height; row++) {
index = row * width + col;
outPixels[index] = disColumns[row];
}
}

// transform along rows
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
index = row * width + col;
f[col] = outPixels[index];
}
float[] disColumns = distance1DTransform(f, width);
for (int col = 0; col < width; col++) {
index = row * width + col;
outPixels[index] = disColumns[col];
}
}

// post sqrt calculation
int[] result = new int[width*height];
for(int row=0; row<height; row++) {
for(int col=0; col<width; col++) {
index = row * width + col;
int pc = clamp(Math.sqrt(outPixels[index]));
result[index] = (255 << 24) | (pc << 16) | (pc << 8) | pc;
}
}
setRGB( dest, 0, 0, width, height, result );
return dest;
}

public static int clamp(double c)
{
return c > 255 ? 255 : (c < 0 ? 0 : (int)c);
}

/**
* 1D distance transform using squared distance
*
* @param data
* @param n
* @return
*/
private float[] distance1DTransform(float[] f, int n)
{
float[] d = new float
;
int[] v = new int
;
double[] z = new double[n+1];
int k = 0;
v[0] = 0;
z[0] = -INF;
z[1] = +INF;
for (int q = 1; q <= n-1; q++) {
double s  = ((f[q]+square(q))-(f[v[k]]+square(v[k])))/(2*q-2*v[k]);
while (s <= z[k]) {
k--;
s  = ((f[q]+square(q))-(f[v[k]]+square(v[k])))/(2*q-2*v[k]);
}
k++;
v[k] = q;
z[k] = s;
z[k+1] = +INF;
}

k = 0;
for (int q = 0; q <= n-1; q++) {
while (z[k+1] < q)
k++;
d[q] = (float)square(q-v[k]) + f[v[k]];
}
return d;
}

private double square(double v)
{
return v*v;
}

}
2013年的最后一篇!谢谢一直关注的各位!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: