OpenCV3入門(六)影象濾波
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
尊重原創技術文章,轉載請註明。
https://www.cnblogs.com/pingwen/p/12305777.html