1、圖像濾波理論
1.1圖像濾波理論
圖像濾波即在盡量保留圖像細節特征的條件下對目標圖像的噪聲進行抑制,是圖像預處理中不可缺少的操作。消除圖像中的噪聲又叫做圖像濾波或平滑,濾波的目的有兩個,一是突出特征以方便處理,二是抑制噪聲。
空間域濾波就是在圖像平面上對像素進行操作。空間域濾波大體分為兩類:平滑、銳化。
平滑濾波:模糊處理,用於減小噪聲,實際上是低通濾波,典型的濾波器是高斯濾波。
銳化濾波:提取邊緣突出邊緣及細節、彌補平滑濾波造成的邊緣模糊。實際上是高通濾波。
空間域處理可由下式表示:
g(x,y)=T[f(x,y)]
式中,f(x,y)是輸入圖像,g(x,y)是處理后的圖像,T是在點(x,y)的鄰域上定義的關於f的一種算子,算子可應用於單幅圖像或圖像集合。
1.2鄰域濾波算子
1)空間濾波器由一個鄰域(通常是一個較小的矩形)和對該鄰域所包圍圖像像素執行的預定義操作組成。對預定義的點(x,y)為中心的領域內的像素進行計算。
2)濾波產生一個新像素,用計算后的新像素值代替點(x,y)的值。
3)循環步驟1和2,濾波器的中心遍歷圖像中的每個像素后,就生成了濾波后的圖像。
4)如果在圖像像素上執行的是線性操作,則該濾波器稱為線性空間濾波器,否則,稱為非線性空間濾波器。
一般來說,使用大小為 m×n的濾波器對大小為 M×N的圖像進行線性空間濾波,可由下式表示:
2、OpenCV濾波方法
濾波處理分為兩大類:線性濾波和非線性濾波。OpenCV里有這些濾波的函數,使用起來非常方便。
線性濾波:
1.方框濾波BoxBlur:模糊圖像
2.均值濾波Blur:模糊圖像
3.高斯濾波GaussianBlur:信號的平滑處理,去除符合正太分布的噪聲
非線性濾波:
1.中值濾波mediaBlur:去除椒鹽噪聲
2.雙邊濾波BilateralFilter:保邊去噪
3、線性濾波器
3.1平滑濾波
一般來說,圖像具有局部連續的性質,即相鄰的像素的值相近,而噪聲使得噪點處產生像素跳躍,所以通過平滑噪點可以減少噪聲,去除圖像中的不相關細節。
方框濾波BoxBlur和均值濾波Blur都是對鄰域內做平均值來濾波,屬於平滑濾波。濾波的輸出是包含在濾波器模板鄰域內的像素的平均值,方框濾波做歸一化之后就變為均值濾波,這兩個濾波器都是低通濾波器。
函數原型如下:
CV_EXPORTS_W void boxFilter( InputArray src, OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1,-1), bool normalize=true, int borderType=BORDER_DEFAULT ); CV_EXPORTS_W void blur( InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT );
3.2高斯濾波
高斯濾波對於圖像來說就是一個低通濾波,廣泛用於消除高斯噪聲,高速濾波就是一種加權濾波,只不過模板中的系數由高斯分布來確定的,高斯濾波器根據高斯函數的形狀來選擇濾波模板權值的線性平滑濾波器。高斯平滑濾波器對於抑制服從正態分布的噪聲非常有效。
CV_EXPORTS_W void GaussianBlur( InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT );
3.3測試實驗
Mat img; Mat img1, img2, img3; int gBoxFilterValue = 3; int gMeanBlurValue = 3; int gGaussianBlurValue = 3; static void OnBoxFilter(int filterSz, void *) { boxFilter(img, img1, -1, Size(filterSz +1, filterSz +1)); imshow("方框濾波", img1); } static void OnMeaanBlur(int filterSz, void *) { blur(img, img2, Size(filterSz + 1, filterSz + 1)); imshow("均值濾波", img2); } static void OnGaussinanBlur(int filterSz, void *) { GaussianBlur(img, img3, Size(filterSz*2 + 1, filterSz*2 + 1), 0, 0); imshow("高斯濾波", img3); } int main() { img = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic2.bmp"); img1 = img.clone(); img2 = img.clone(); img3 = img.clone(); imshow("原圖", img); namedWindow("方框濾波", 1); createTrackbar("內核值", "方框濾波", &gBoxFilterValue, 40, OnBoxFilter); OnBoxFilter(gBoxFilterValue, 0); namedWindow("均值濾波", 1); createTrackbar("內核值", "均值濾波", &gMeanBlurValue, 40, OnMeaanBlur); OnMeaanBlur(gMeanBlurValue, 0); namedWindow("高斯濾波", 1); createTrackbar("內核值", "高斯濾波", &gGaussianBlurValue, 40, OnGaussinanBlur); OnGaussinanBlur(gGaussianBlurValue, 0); waitKey(0); }
輸出結果如下圖。
4、非線性濾波器
4.1中值濾波
中值濾波屬於非線性濾波,其思想用濾波模板鄰域內的像素的平均值來代替像素點的灰度值。中值濾波器是一種統計排序濾波器,圖像上點(x,y),中值濾波以該點為中心,領域內所有像素的統計排序中值作為此點的響應,中值濾波是非線性濾波。相比與均值濾波和高斯濾波,中值濾波可以有效的降低隨機噪聲,直接忽略掉噪聲點,把噪聲引起的模糊降到最低。線性濾波器在濾波的同時會造成圖像細節模糊,中值濾波可以避免這個問題,其典型的應用就是中值濾波消除斑點噪聲、椒鹽噪聲。
CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );
使用中值濾波,濾除椒鹽噪聲例子如下。
img = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic2.bmp"); salt(img, 1000); img1 = img.clone(); img2 = img.clone(); img3 = img.clone(); imshow("原圖", img); namedWindow("高斯濾波", 1); createTrackbar("內核值", "高斯濾波", &gGaussianBlurValue, 40, OnGaussinanBlur); OnGaussinanBlur(gGaussianBlurValue, 0); namedWindow("中值濾波", 1); createTrackbar("內核值", "中值濾波", &gMedianBlurValue, 40, OnMedianBlur); OnMedianBlur(gMedianBlurValue, 0); waitKey(0); }
輸出結果如下圖。高斯濾波在濾除噪點的同時也造成了圖像模糊,如果增大內核則會造成嚴重模糊失真,而中值濾波對椒鹽噪聲有很好的抑制作用。
4.2雙邊濾波
高斯濾波屬於加權平均濾波,距離中心點越近的點越有較大權重,這種方法符合圖像的平滑變化的特征,但是在邊緣區域,像素值出現突變,這種方法反而會濾掉邊緣輪廓,損失掉有用的邊緣信息。邊緣保護濾波方法,雙邊濾波就是最常用的邊緣保護濾波方法,就是為了處理這種情況而發明的。
雙邊濾波(Bilateral filter)是一種非線性的濾波方法,是結合圖像的空間鄰近度和像素值相似度的一種折衷處理,同時考慮空域信息和灰度相似性,達到保邊去噪的目的。雙邊濾波將高斯濾波中通過各個點到中心點的空間臨近度計算的各個權值進行優化,將其優化為空間臨近度計算的權值和像素值相似度計算的權值的乘積,優化后的權值再與圖像作卷積運算,從而達到保邊去噪的效果。
CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT );
InputArray src: 輸入圖像,可以是Mat類型,圖像必須是8位或浮點型單通道、三通道的圖像。
OutputArray dst: 輸出圖像,和原圖像有相同的尺寸和類型。
int d: 表示在過濾過程中每個像素鄰域的直徑范圍。如果這個值是非正數,則函數會從第五個參數sigmaSpace計算該值。
double sigmaColor: 顏色空間過濾器的sigma值,這個參數的值越大,更大的值域空間影響結果。
double sigmaSpace: 坐標空間中濾波器的sigma值,如果該值較大,更大的定義域空間影響結果。
int borderType=BORDER_DEFAULT:邊界模式,有默認值BORDER_DEFAULT.
static void OnBilateralFilter(int filterSz, void *) { bilateralFilter(img, img3, filterSz, filterSz * 2, filterSz / 2); imshow("雙邊濾波", img3); } namedWindow("雙邊濾波", 1); createTrackbar("內核值", "雙邊濾波", &gMedianBlurValue, 40, OnBilateralFilter); OnBilateralFilter(gMedianBlurValue, 0);
輸出效果如下圖。雙邊濾波在較大的參數范圍內都保持了很好的噪聲抑制特性,並且沒有造成邊緣模糊。
5、遇到的問題medianBlur報異常
調節中值濾波的滑動條時,出現異常。
vs報錯:
未經處理的異常:
0x00007FF835C09159 處(位於 Day1.exe 中)有未經處理的異常: Microsoft C++ 異常: cv::Exception,位於內存位置 0x000000F29FAFE138 處。
解決方法:
中值濾波的參數ksize需要為偶數。
@param src input 1-, 3-, or 4-channel image; when ksize is 3 or 5, the image depth should be CV_8U, CV_16U, or CV_32F, for larger aperture sizes, it can only be CV_8U. @param dst destination array of the same size and type as src. @param ksize aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7 ... @sa bilateralFilter, blur, boxFilter, GaussianBlur */ CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );
使用例子:
static void OnMedianBlur(int filterSz, void *) { if (filterSz % 2 == 0) filterSz += 1; medianBlur(img, img2, filterSz); imshow("中值濾波", img2); }
測試效果圖如下:
6、參考文獻
1、《OpenCV3 編程入門》,電子工業出版社,毛星雨著
2、《學習OpenCV》,清華大學出版社,Gary Bradski, Adrian kaehler著
3、OpenCV雙邊濾波詳解及實代碼實現
https://blog.csdn.net/qq_36359022/article/details/80198890
4、Bilateral Filtering for Gray and Color Images
https://users.soe.ucsc.edu/~manduchi/Papers/ICCV98.pdf
5、Smoothing Images
https://docs.opencv.org/4.1.2/dc/dd3/tutorial_gausian_median_blur_bilateral_filter.html
6、OpenCV圖像處理之濾波
https://blog.csdn.net/qq_30815237/article/details/86690190
尊重原創技術文章,轉載請注明。