以前写过两篇关于快速高斯滤波的文章,但是代码都没写完整。
算法来源及介绍请参考博主Imageshop的博文http://www.cnblogs.com/Imageshop/archive/2013/01/07/2849782.html。
为了避免需要的朋友在看我的文章时过于浪费时间,所以删除前两篇文章,重写此篇目的为需要的朋友提供有用的信息。
下面给出的是功能完整的 c代码,下面代码无论是格式还是速度都可以进一步优化,请自行处理
1 /**************************************** 2 * src : 原始图像数据 * 3 * dst : 模糊后图像数据 * 4 * width : 图像宽 * 5 * height : 图像高 * 6 * stride : 图像每一行字节数 * 7 * chan : 图像通道数 * 8 * sigma : 高斯参数 * 9 * chan : 图像通道数 * 10 *****************************************/ 11 void IMG_GaussBlur(unsigned char* src, unsigned char* dst, int width, int height, int stride, int chan, float sigma) 12 { 13 int i = 0; 14 int h,w; 15 int row = 0; 16 int col = 0; 17 int pos = 0; 18 int channel = 0; 19 int n = 0; 20 int bufsize = 0; 21 int size = 0; 22 int rowstride = 0; 23 int itemp0 = 0; 24 int itemp1 = 0; 25 float temp = 0; 26 float fTab[256] = {0}; 27 unsigned char* ps; 28 float *pIn; 29 30 int blurH = height+3; 31 int blurW = width+3; 32 for (i=0; i<256; i++) 33 { 34 fTab[i] = i+1; 35 } 36 37 int channelsize = width*height+(width+height)*6; 38 39 if (width>height) 40 { 41 bufsize = width+6; 42 } 43 else 44 { 45 bufsize = height+6; 46 } 47 48 float* w1 = (float *) malloc (bufsize * sizeof (float)); 49 float *w2 = (float *) malloc (bufsize * sizeof (float)); 50 float *in = (float *) malloc (channelsize * sizeof (float)); 51 float *out = (float *) malloc (channelsize * sizeof (float)); 52 53 //----------------计算高斯核---------------------------------------// 54 float q = 0; 55 float q2, q3; 56 double b0; 57 double b1; 58 double b2; 59 double b3; 60 double B = 0; 61 int N = 3; 62 63 if (sigma >= 2.5) 64 { 65 q = 0.98711 * sigma - 0.96330; 66 } 67 else if ((sigma >= 0.5) && (sigma < 2.5)) 68 { 69 q = 3.97156 - 4.14554 * (float) sqrt ((double) 1 - 0.26891 * sigma); 70 } 71 else 72 { 73 q = 0.1147705018520355224609375; 74 } 75 76 q2 = q * q; 77 q3 = q * q2; 78 b0 = (1.57825+(2.44413*q)+(1.4281 *q2)+(0.422205*q3)); 79 b1 = ( (2.44413*q)+(2.85619*q2)+(1.26661 *q3)); 80 b2 = ( -((1.4281*q2)+(1.26661 *q3))); 81 b3 = ( (0.422205*q3)); 82 B = 1.0-((b1+b2+b3)/b0); 83 84 //加速方法 减少循环多次/b0 85 b1 /= b0; 86 b2 /= b0; 87 b3 /= b0; 88 89 //----------------计算高斯核结束---------------------------------------// 90 // 处理图像的多个通道 91 for (channel = 0; channel < chan; channel++) 92 { 93 // 获取一个通道的所有像素值 94 pIn = in; 95 for (h=0; h<height; h++) 96 { 97 ps = src + h*stride; 98 for (w=0;w<width;w++) 99 { 100 /* 0-255 => 1-256 */ 101 *pIn++ = fTab[ps[channel]]; 102 103 if (w==width-1) 104 { 105 *pIn++ = fTab[ps[channel]]; 106 *pIn++ = fTab[ps[channel]]; 107 *pIn++ = fTab[ps[channel]]; 108 } 109 ps+=chan; 110 } 111 } 112 memcpy(in+(height)*(width+3), in+(height-1)*(width+3), (width+3)*sizeof(float)); 113 memcpy(in+(height+1)*(width+3), in+(height-1)*(width+3), (width+3)*sizeof(float)); 114 memcpy(in+(height+2)*(width+3), in+(height-1)*(width+3), (width+3)*sizeof(float)); 115 116 //纵向处理 117 size = blurW; 118 bufsize = size+3; 119 size -= 1; 120 for (row=0 ;row < blurH; row++) 121 { 122 pos = row * blurW; 123 temp = (in + pos)[0]; 124 w1[0] = temp; 125 w1[1] = temp; 126 w1[2] = temp; 127 128 for ( i = 0 , n=3; i <= size ; i++, n++) 129 { 130 w1[n] = (float)(B*(in + pos)[i] + ((b1*w1[n-1] + b2*w1[n-2] + b3*w1[n-3] ))); 131 } 132 133 temp = w1[size+3]; 134 w2[size+1]= temp; 135 w2[size+2]= temp; 136 w2[size+3]= temp; 137 for (i = size, n = i; i >= 0; i--, n--) 138 { 139 (out + pos)[i] = w2[n] = (float)(B*w1[n] + ((b1*w2[n+1] + b2*w2[n+2] + b3*w2[n+3] ))); 140 } 141 } 142 143 144 //横向处理 145 size = blurH; 146 rowstride = blurW; 147 bufsize = size+3; 148 size -= 1; 149 for (col=0; col < blurW; col++) 150 { 151 temp = (out + col)[0]; 152 w1[0] = temp; 153 w1[1] = temp; 154 w1[2] = temp; 155 for ( i = 0 , n=3; i <= size ; i++, n++) 156 { 157 w1[n] = (float)(B*(out + col)[i*rowstride] + ((b1*w1[n-1] + b2*w1[n-2] + b3*w1[n-3] ))); 158 } 159 160 temp = w1[size+3]; 161 w2[size+1] = temp; 162 w2[size+2] = temp; 163 w2[size+3] = temp; 164 for (i = size, n = i; i >= 0; i--, n--) 165 { 166 (in + col)[i * rowstride] =w2[n]= (float)(B*w1[n] + ((b1*w2[n+1] + b2*w2[n+2] + b3*w2[n+3] ))); 167 } 168 } 169 170 //修正偏移的拷贝方法 171 for(int y=0; y<height; y++) 172 { 173 ps = dst+ y*stride; 174 itemp1 = (y+3)*blurW; // +3 175 for (int x=0; x<width; x++) 176 { 177 ps[channel] = in[itemp1+x+3]-1; 178 ps+=chan; 179 } 180 } 181 } 182 183 free (w1); 184 free (w2); 185 free (in); 186 free (out); 187 }
调用参考
1 IplImage* src = cvLoadImage("./test.jpg", 1); 2 IplImage* dst = cvLoadImage("./test.jpg", 1); 3 4 IMG_GaussBlur((unsigned char*)src->imageData, 5 (unsigned char*)dst->imageData, 6 src->width, src->height, 7 src->widthStep, 8 src->nChannels, 2);