经由厉害博主Imageshop的博文http://www.cnblogs.com/Imageshop/archive/2013/01/07/2849782.html提示,
我这里实现了高斯模糊函数,但是有一下几点问题向各位讨教探讨:
①这个函数处理速度没有Imageshop博主描述的速度快,如何提高效率。
②高斯模糊后感觉整幅图像会向右下角平移一定距离,没有详细研究过算法本身,这样是否为正常,有何解决方案,大家一起探讨。(反正我用高斯模糊后图像载进行USM锐化得到了我觉得很不理想的结果,原因应该就是这个平移造成的)
③高手帮看看我这个函数是否本身就有错
我做的工作很简单
①我将contrast-retinex.c中关于高斯模糊的代码全集中在一个函数中,使这个此函数更加独立。这样也减少了一些内存分配释放的次数
②纵向处理后将数据指针in和out直接对调处理,省去了在此不值一提的拷贝过程
③调用这个函数实现高斯模糊查看结果
现在将代码及结果贴出:
/**************************************** * src : 原始图像数据 * * dst : 模糊后图像数据 * * width : 图像宽 * * height : 图像高 * * sigma : 高斯参数 * * chan : 图像通道数 * *****************************************/ void IMG_GaussBlur(unsigned char* src, unsigned char*& dst, int width, int height, float sigma, int chan) { int i = 0; int row = 0; int col = 0; int pos = 0; int channel = 0; int n = 0; int bufsize = 0; int size = 0; int rowstride = 0; int channelsize = width*height; if (width>height) { bufsize = width+3; } else { bufsize = height+3; } float* w1 = (float *) malloc (bufsize * sizeof (float)); float *w2 = (float *) malloc (bufsize * sizeof (float)); float *in = (float *) malloc (channelsize * sizeof (float)); float *out = (float *) malloc (channelsize * sizeof (float)); //----------------计算高斯核---------------------------------------// //compute_coefs3(coef, sigma); float q = 0; float q2, q3; double b[4] = {0}; double B = 0; int N = 3; if (sigma >= 2.5) { q = 0.98711 * sigma - 0.96330; } else if ((sigma >= 0.5) && (sigma < 2.5)) { q = 3.97156 - 4.14554 * (float) sqrt ((double) 1 - 0.26891 * sigma); } else { q = 0.1147705018520355224609375; } q2 = q * q; q3 = q * q2; b[0] = (1.57825+(2.44413*q)+(1.4281 *q2)+(0.422205*q3)); b[1] = ( (2.44413*q)+(2.85619*q2)+(1.26661 *q3)); b[2] = ( -((1.4281*q2)+(1.26661 *q3))); b[3] = ( (0.422205*q3)); B = 1.0-((b[1]+b[2]+b[3])/b[0]); //----------------计算高斯核结束---------------------------------------// // 处理图像的多个通道 for (channel = 0; channel < chan; channel++) { // 获取一个通道的所有像素值 for (i = 0, pos = channel; i < channelsize ; i++, pos += chan) { /* 0-255 => 1-256 */ in[i] = (float)(src[pos] + 1.0); } //纵向处理 for (row=0 ;row < height; row++) { pos = row * width; //gausssmooth(in + pos, out + pos, width, 1, &coef); size = width; rowstride = 1; bufsize = size+3; size -= 1; w1[0] = (in + pos)[0]; w1[1] = (in + pos)[0]; w1[2] = (in + pos)[0]; for ( i = 0 , n=3; i <= size ; i++, n++) { w1[n] = (float)(B*(in + pos)[i*rowstride] + ((b[1]*w1[n-1] + b[2]*w1[n-2] + b[3]*w1[n-3] ) / b[0])); } /** backward pass */ w2[size+1]= w1[size+3]; w2[size+2]= w1[size+3]; w2[size+3]= w1[size+3]; for (i = size, n = i; i >= 0; i--, n--) { w2[n]= (out + pos)[i * rowstride] = (float)(B*w1[n] + ((b[1]*w2[n+1] + b[2]*w2[n+2] + b[3]*w2[n+3] ) / b[0])); } } //下面的横向处理直接将数据 out 与 in 对调 省去memcpy //memcpy(in, out, channelsize * sizeof(float)); //memset(out, 0 , channelsize * sizeof(float)); //横向处理 for (col=0; col < width; col++) { //gausssmooth(out + col, in + col, height, width, &coef); size = height; rowstride = width; bufsize = size+3; size -= 1; w1[0] = (out + col)[0]; w1[1] = (out + col)[0]; w1[2] = (out + col)[0]; for ( i = 0 , n=3; i <= size ; i++, n++) { w1[n] = (float)(B*(out + col)[i*rowstride] + ((b[1]*w1[n-1] + b[2]*w1[n-2] + b[3]*w1[n-3] ) / b[0])); } w2[size+1]= w1[size+3]; w2[size+2]= w1[size+3]; w2[size+3]= w1[size+3]; for (i = size, n = i; i >= 0; i--, n--) { w2[n]= (in + col)[i * rowstride] = (float)(B*w1[n] + ((b[1]*w2[n+1] + b[2]*w2[n+2] + b[3]*w2[n+3] ) / b[0])); } } //拷贝结果到函数输出指针 for (i = 0, pos = channel; i < channelsize ; i++, pos += chan) { dst[pos] = in[i]-1; } } free (w1); free (w2); free (in); free (out); }
调用方法:
Mat src = imread(".\test.jpg"); Mat dst = imread(".\test.jpg"); IMG_GaussBlur(src.data, dst.data, src.cols, src.rows, 2.0, 3); //保存或显示结果,略...
执行结果:
sigma=2.0
379 x 513 耗时 61ms
sigma=5.0
2304 x 1728 耗时 1870ms
博问可以贴代码,点击编辑器中倒数第2个按钮
谢谢!已调整。