快速高斯濾波函數[修正完善版],高斯濾波
原文地址:http://blog.csdn.net/markl22222/article/details/10313565
進行了修正和變數最佳化。原來作者的函數只支援2次方圖片,這次做了修正(windows的bitmap行寬是4位元組對齊的)。
( 基本完善了,但是在某些條件下,Y方向的底邊還是會出現偏差,一時找不到原因,暫且發表,希望有人能提醒一下。)
今天檢查了一下代碼,發現了一個低級的技術性錯誤,Y方向底邊的顏色偏差已經修正,這個函數趨於完美,收工。
函數結構我規整了一下,很清晰,很好閱讀。
int gauss_blur(byte_t* image,//位元影像資料int linebytes,//位元影像行位元組數,BMP資料在windows中是4位元組對齊的。否則在處理非二次冪的映像時會有偏差int width,//位元影像寬度int height,//位元影像高度int cbyte,//色彩通道數量float sigma//高斯係數){int x = 0, y = 0, n = 0;int channel = 0;int srcline = 0, dstline = 0;int channelsize = width*height;int bufsize = width > height ? width + 4 : height + 4;float *w1 = NULL, *w2 = NULL, *imgbuf = NULL;int time = 0;#if defined(_INC_WINDOWS)time = GetTickCount();#elif defined(_CLOCK_T)time = clock();#endifw1 = (float*)malloc(bufsize * sizeof(float));if(!w1){return -1;}w2 = (float*)malloc(bufsize * sizeof(float));if(!w2){free(w1);return -1;}imgbuf = (float*)malloc(channelsize * sizeof(float));if(!imgbuf){free(w1);free(w2);return -1;}//----------------計算高斯核---------------------------------------//float q = 0;float q2 = 0, q3 = 0;float b0 = 0, b1 = 0, b2 = 0, b3 = 0;float B = 0;if (sigma >= 2.5f){q = 0.98711f * sigma - 0.96330f;}else if ((sigma >= 0.5f) && (sigma < 2.5f)){q = 3.97156f - 4.14554f * (float) sqrt (1.0f - 0.26891f * sigma);}else{q = 0.1147705018520355224609375f;}q2 = q * q;q3 = q * q2;b0 = (1.57825+ (2.44413f*q)+(1.4281f *q2)+(0.422205f*q3));b1 = ( (2.44413f*q)+(2.85619f*q2)+(1.26661f* q3));b2 = ( -((1.4281f*q2)+(1.26661f* q3)));b3 = ( (0.422205f*q3));B = 1.0-((b1+b2+b3)/b0);b1 /= b0;b2 /= b0;b3 /= b0;//----------------計算高斯核結束---------------------------------------//// 處理映像的多個通道for (channel = 0; channel < cbyte; ++channel){// 擷取一個通道的所有像素值,並預先處理for(y=0; y<height; ++y){srcline = y*linebytes;dstline = y*width;for(x=0, n=channel; x<width; ++x, n+=cbyte){(imgbuf+dstline)[x] = float((image+srcline)[n]);}}for (int x=0; x<width; ++x){//橫向處理w1[0] = (imgbuf + x)[0];w1[1] = (imgbuf + x)[0];w1[2] = (imgbuf + x)[0];for (y=0, n=0; y<height; ++y, n+=width){w1[y+3] = B*(imgbuf + x)[n] + (b1*w1[y+2] + b2*w1[y+1] + b3*w1[y+0]);}w2[height+0]= w1[height+2];w2[height+1]= w1[height+1];w2[height+2]= w1[height+0];for (int y=height-1, n=y*width; y>=0; --y, n-=width){//儲存資料到緩衝(imgbuf + x)[n] = w2[y] = B*w1[y+3] + (b1*w2[y+1] + b2*w2[y+2] + b3*w2[y+3]);}}//橫向處理for (y=0, srcline=0, dstline=0; y<height; ++y, srcline+=width, dstline+=linebytes){//縱向處理//取當前行資料w1[0] = (imgbuf + srcline)[0];w1[1] = (imgbuf + srcline)[0];w1[2] = (imgbuf + srcline)[0];//正方向橫向處理3個點的資料for (x=0; x<width ; ++x){w1[x+3] = B*(imgbuf + srcline)[x] + (b1*w1[x+2] + b2*w1[x+1] + b3*w1[x+0]);}w2[width+0]= w1[width+2];w2[width+1]= w1[width+1];w2[width+2]= w1[width+0];//反方向處理for (x=width-1, n=x*cbyte+channel; x>=0; --x, n-=cbyte){//處理儲存資料到緩衝//(imgbuf + dstline)[x] = w2[x] = B*w1[x+3] + (b1*w2[x+1] + b2*w2[x+2] + b3*w2[x+3]);//儲存返回資料(image + dstline)[n] = w2[x] = B*w1[x+3] + (b1*w2[x+1] + b2*w2[x+2] + b3*w2[x+3]);}}//縱向處理/*//儲存處理完畢的通道for(int y=0; y<height; y++){int dstline = y*linebytes;int srcline = y*width;for (int x=0; x<width; x++){(image + dstline)[x * cbyte + channel] = (imgbuf + srcline)[x];//byte_edge((imgbuf + srcline)[x]-1);}}//儲存迴圈//*/}//通道迴圈free(w1);w1=NULL;free(w2);w2=NULL;free(imgbuf);imgbuf=NULL;#if defined(_INC_WINDOWS)return GetTickCount() - time;#elif defined(_CLOCK_T)return clock() - time;#elsereturn 0;#endif}
應用執行個體:
//開啟一個24位BMP映像HBITMAP hbmp = (HBITMAP)LoadImage(NULL, "a.bmp", IMAGE_BITMAP, 0, 0,LR_DEFAULTSIZE|LR_CREATEDIBSECTION|LR_LOADFROMFILE);BITMAP bm;if(hbmp){HDC dc = CreateCompatibleDC(NULL);SelectObject(dc, hbmp);GetObject(Image1->Picture->Bitmap->Handle, sizeof(bm), &bm);//高斯影像處理gauss_blur((BYTE*)bm.bmBits, bm.bmWidthBytes, bm.bmWidth, bm.bmHeight, 3, 3.0);//複製到你的DC上BitBlt(hMyDC, 0, 0, bm.bmWidth, bm.bmHeight, dc, 0, 0, SRCCOPY);DeleteObject(hbmp);DeleteDC(dc);}
用matlab編寫使用二維高斯低通濾波器的函數,使用大小為3*3,標準差分別為05,15,25
高斯低通濾波對映像進行低通濾波代碼,這個是灰階映像的
彩色映像就是取出RGB三個分量進行濾波再整合
I1=imread('flower.jpg'); %讀取映像
I=rgb2gray(I1); %將映像變為灰階圖象
%將灰階映像的二維不連續Frourier變換的零頻率成分移到頻譜的中心
s=fftshift(fft2(I));
[M,N]=size(s); %分別返回s的行數到M中,列數到N中
n=2; %對n賦初值
%GLPF濾波,d0=5,15,30(程式中以d0=30為例)
d0=30; %初始化d0
n1=floor(M/2); %對M/2進行取整
n2=floor(N/2); %對N/2進行取整
for i=1:M
for j=1:N
d=sqrt((i-n1)^2+(j-n2)^2); %點(i,j)到傅立葉變換中心的距離
h=1*exp(-1/2*(d^2/d0^2)); %GLPF濾波函數
s(i,j)=h*s(i,j); %GLPF濾波後的頻域表示
end
end
s=ifftshift(s); %對s進行反FFT移動
%對s進行二維反離散的Fourier變換後,取複數的實部轉化為無符號8位整數
s=uint8(real(ifft2(s)));
figure; %建立圖形映像對象
imshow(s); %顯示GLPF濾波處理後的映像
title('GLPF濾波(d0=30)'); %為經GLPF濾波後的映像添加標題
matlab中調用高斯濾波器,出現這個錯誤怎辦
matlab雷根本沒這個函數。
不過google可以查到有別人寫的這樣一個函數的源碼,你可以試試。