一:Mean Shift算法介绍

Mean Shift是一种聚类算法,在数据挖掘,图像提取,视频对象跟踪中都有应用。本文

重要演示Mean Shift算法来实现图像的低通边缘保留滤波效果。其处理以后的图像有点

类似油画一样。Mean Shift算法的输入参数一般有三个:

1.      矩阵半径r,声明大小

2.      像素距离,常见为欧几里德距离或者曼哈顿距离

3.      像素差值value

 

算法大致的流程如下:

a.      输入像素点P(x, y)

b.      计算该点的像素值pixelv

c.      根据输入的半径r与差值value求出矩阵半径内满足差值像素平均值作为输出像素点值

d.      计算shift与repetition,如果满足条件

e.      继续c ~ d,直到条件不满足退出,得到最终的输出像素值

f.       对输入图像的每个像素重复a ~ e,得到图像输出像素数据

二:色彩空间转换

 本文Mean Shift滤波在YIQ颜色空间上完成,关于RGB与YIQ颜色空间转换可以参考

这里:http://en.wikipedia.org/wiki/YIQ我google找来的转换公式截屏:


三:程序效果


滤镜源代码:

package com.gloomyfish.filter.study;  import java.awt.image.BufferedImage;  public class MeanShiftFilter extends AbstractBufferedImageOp { 	 	private int radius; 	private float colorDistance; 	 	public MeanShiftFilter() { 		radius = 3; // default shift radius 		colorDistance = 25; // default color distance 	} 	public int getRadius() { 		return radius; 	}  	public void setRadius(int radius) { 		this.radius = radius; 	}  	public float getColorDistance() { 		return colorDistance; 	}  	public void setColorDistance(float colorDistance) { 		this.colorDistance = colorDistance; 	}  	@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];         int[] outPixels = new int[width*height];         getRGB( src, 0, 0, width, height, inPixels);                  // convert RGB color space to YIQ color space         float[][] pixelsf = new float[width*height][3];         for(int i=0; i<inPixels.length; i++) { 			int argb = inPixels[i]; 			int r = (argb >> 16) & 0xff; 			int g = (argb >>  8) & 0xff; 			int b = (argb) & 0xff; 			pixelsf[i][0] = 0.299f  *r + 0.587f *g + 0.114f  *b; // Y 			pixelsf[i][1] = 0.5957f *r - 0.2744f*g - 0.3212f *b; // I 			pixelsf[i][2] = 0.2114f *r - 0.5226f*g + 0.3111f *b; // Q         }                  int index = 0;         float shift = 0;         float repetition = 0;         float radius2 = radius * radius;         float dis2 = colorDistance * colorDistance;         for(int row=0; row<height; row++) {         	int ta = 255, tr = 0, tg = 0, tb = 0;         	for(int col=0; col<width; col++) { 				int xc = col; 				int yc = row; 				int xcOld, ycOld; 				float YcOld, IcOld, QcOld; 				index = row*width + col; 				float[] yiq = pixelsf[index]; 				float Yc = yiq[0]; 				float Ic = yiq[1]; 				float Qc = yiq[2];  				repetition = 0; 				do { 					xcOld = xc; 					ycOld = yc; 					YcOld = Yc; 					IcOld = Ic; 					QcOld = Qc;  					float mx = 0; 					float my = 0; 					float mY = 0; 					float mI = 0; 					float mQ = 0; 					int num=0;  					for (int ry=-radius; ry <= radius; ry++) { 						int y2 = yc + ry;  						if (y2 >= 0 && y2 < height) { 							for (int rx=-radius; rx <= radius; rx++) { 								int x2 = xc + rx;  								if (x2 >= 0 && x2 < width) { 									if (ry*ry + rx*rx <= radius2) { 										yiq = pixelsf[y2*width + x2];  										float Y2 = yiq[0]; 										float I2 = yiq[1]; 										float Q2 = yiq[2];  										float dY = Yc - Y2; 										float dI = Ic - I2; 										float dQ = Qc - Q2;  										if (dY*dY+dI*dI+dQ*dQ <= dis2) { 											mx += x2; 											my += y2; 											mY += Y2; 											mI += I2; 											mQ += Q2; 											num++; 										} 									} 								} 							} 						} 					} 					float num_ = 1f/num; 					Yc = mY*num_; 					Ic = mI*num_; 					Qc = mQ*num_; 					xc = (int) (mx*num_+0.5); 					yc = (int) (my*num_+0.5); 					int dx = xc-xcOld; 					int dy = yc-ycOld; 					float dY = Yc-YcOld; 					float dI = Ic-IcOld; 					float dQ = Qc-QcOld;  					shift = dx*dx+dy*dy+dY*dY+dI*dI+dQ*dQ;  					repetition++; 				} 				while (shift > 3 && repetition < 100); 				tr = (int)(Yc + 0.9563f*Ic + 0.6210f*Qc); 				tg = (int)(Yc - 0.2721f*Ic - 0.6473f*Qc); 				tb = (int)(Yc - 1.1070f*Ic + 1.7046f*Qc);      				outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;         	}         }         setRGB( dest, 0, 0, width, height, outPixels );         return dest; 	} 	 	public String toString() { 		System.out.println("Mean Shift Filter..."); 		return "MeanShiftFilter"; 	}  } 
转载请注明