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

算法是别人提出来的,感兴趣可以搜索《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[n]; 		  int[] v = new int[n]; 		  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年的最后一篇!谢谢一直关注的各位!