图像保边滤波算法集锦--MeanShift滤波算法与实现

匿名 (未验证) 提交于 2019-12-03 00:30:01

本文将尝试使用MeanShift滤波来做磨皮算法;

MeanShiftFukunage1975The Estimation of the Gradient of a density function.

MeanShiftMeanShift

MeanShift()

Fig.1MeanShift

RadiusaaRGB

1,aRadiusRGBMc

2,(RGB)M

3,MRadiusM

4,1-3

5,aRGBMRGBf

afafRGB

MeanShiftMeanShift

算法流程如下:

1,P(i,j)RmaxIterthreshold

2,PRSrgb()

K|x-y|

1,PM2

2,2-3maxIterPrgb

MeanShiftYCbCrY

效果图如下所示:


完整C代码如下:

#include "string.h" #include "stdio.h" #include "stdlib.h" #include "math.h" #include"f_MeanShiftFilter.h" #include"TRGB2YCbCr.h" #define MIN2(a, b) ((a) < (b) ? (a) : (b)) #define MAX2(a, b) ((a) > (b) ? (a) : (b)) #define CLIP3(x, a, b) MIN2(MAX2(a,x), b)   int MeanShiftOneChannel(unsigned char* srcData, int width ,int height, int radius, int threshold, int maxIter) {	 	int len = sizeof(unsigned long) * width * height; 	int i, j; 	int gray = 0, sum = 0, srcGray = 0, count = 0; 	unsigned char* tempData = (unsigned char*) malloc(sizeof(unsigned char) * height * width); 	memcpy(tempData, srcData, sizeof(unsigned char) * height * width); 	for(j = 0; j < height; j++ ) 	{ 		for(i = 0; i < width; i++) 		{ 			len = i + j * width; 			int nIter = 0, cx = 0, cy = 0, sumx = 0, sumy = 0; 			srcGray = tempData[len]; 			cx = i; 			cy = j;  			while(nIter < maxIter) 			{ 				sum = 0; 				sumx = 0; 				sumy = 0; 				count = 0; 				for(int y = cy - radius; y <= cy + radius; y++) 				{ 					for(int x = cx - radius; x <= cx + radius; x++) 					{ 						int px = CLIP3(x, 0, width - 1); 						int py = CLIP3(y, 0, height - 1); 						len = px + py * width; 						gray = tempData[len]; 						if(abs(gray - srcGray) < threshold) 						{ 							count++; 							sum += gray; 							sumx += x; 							sumy += y; 						} 					} 				} 				if(count == 0) 					break; 				srcGray = sum / count; 				cx = sumx / count; 				cy = sumy / count; 				nIter++; 			} 			srcData[i + j * width] = srcGray; 		} 	} 	free(tempData); 	return 0; };  void f_MeanShiftFilter(unsigned char* srcData, int nWidth, int nHeight, int nStride, int radius, int threshold, int maxIter) { 	if (srcData == NULL) 	{ 		return; 	} 	if(radius == 0 || threshold == 0) 		return; 	unsigned char* yData = (unsigned char*)malloc(sizeof(unsigned char) * nWidth * nHeight); 	unsigned char* cbData = (unsigned char*)malloc(sizeof(unsigned char) * nWidth * nHeight); 	unsigned char* crData = (unsigned char*)malloc(sizeof(unsigned char) * nWidth * nHeight); 	unsigned char* pSrc = srcData; 	int Y, CB, CR; 	unsigned char* pY = yData; 	unsigned char* pCb = cbData; 	unsigned char* pCr = crData; 	for(int j = 0; j < nHeight; j++) 	{ 		for(int i = 0; i < nWidth; i++) 		{  			RGBToYCbCr(pSrc[2],pSrc[1],pSrc[0],&Y,&CB,&CR); 			*pY = Y; 			*pCb = CB; 			*pCr = CR; 			pY++; 			pCb++; 			pCr++; 			pSrc += 4; 		} 	} 	MeanShiftOneChannel(yData, nWidth, nHeight, radius, threshold, maxIter); 	pSrc = srcData; 	pY = yData; 	pCb = cbData; 	pCr = crData; 	int R, G, B; 	for(int j = 0; j < nHeight; j++) 	{ 		for(int i = 0; i < nWidth; i++) 		{ 			YCbCrToRGB(*pY, *pCb, *pCr, &R, &G, &B);             pSrc[0] = B; 			pSrc[1] = G; 			pSrc[2] = R; 			pY++; 			pCb++; 			pCr++; 			pSrc += 4; 		} 	} 	free(yData); 	free(cbData); 	free(crData); }   

代码已经贴出来了,这里就不给DEMO了,大家可以直接使用代码进行测试,代码中YCbCr转换函数前文博客中有,或者大家自己实现,都可以。

本人QQ1358009172



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!