openCV中值濾波和均值濾波的代碼實現(xiàn)
在開始我們今天的博客之前,我們需要先了解一下什么是濾波:
首先我們看一下圖像濾波的概念。圖像濾波,即在盡量保留圖像細節(jié)特征的條件下對目標(biāo)圖像的噪聲進行抑制,是圖像預(yù)處理中不可缺少的操作,其處理效果的好壞將直接影響到后續(xù)圖像處理和分析的有效性和可靠性。
下圖左邊是原圖右邊是噪聲圖:
消除圖像中的噪聲成分叫作圖像的平滑化或濾波操作。信號或圖像的能量大部分集中在幅度譜的低頻和中頻段是很常見的,而在較高頻段,感興趣的信息經(jīng)常被噪聲淹沒。因此一個能降低高頻成分幅度的濾波器就能夠減弱噪聲的影響。
圖像濾波的目的有兩個:一是抽出對象的特征作為圖像識別的特征模式;另一個是為適應(yīng)圖像處理的要求,消除圖像數(shù)字化時所混入的噪聲。
而對濾波處理的要求也有兩條:一是不能損壞圖像的輪廓及邊緣等重要信息;二是使圖像清晰視覺效果好。
平滑濾波是低頻增強的空間域濾波技術(shù)。它的目的有兩類:一類是模糊;另一類是消除噪音。
空間域的平滑濾波一般采用簡單平均法進行,就是求鄰近像元點的平均亮度值。鄰域的大小與平滑的效果直接相關(guān),鄰域越大平滑的效果越好,但鄰域過大,平滑會使邊緣信息損失的越大,從而使輸出的圖像變得模糊,因此需合理選擇鄰域的大小。
關(guān)于濾波器,一種形象的比喻法是:我們可以把濾波器想象成一個包含加權(quán)系數(shù)的窗口,當(dāng)使用這個濾波器平滑處理圖像時,就把這個窗口放到圖像之上,透過這個窗口來看我們得到的圖像。
舉一個濾波在我們生活中的應(yīng)用:美顏的磨皮功能。如果將我們臉上坑坑洼洼比作是噪聲的話,那么濾波算法就是來取出這些噪聲,使我們自拍的皮膚看起來很光滑。
這篇博文會介紹中值濾波以及均值濾波兩種算法
一.均值濾波
圖片中一個方塊區(qū)域(一般為3*3)內(nèi),中心點的像素為全部點像素值的平均值。均值濾波就是對于整張圖片進行以上操作。
我們可以看下圖的矩陣進行理解
缺陷:均值濾波本身存在著固有的缺陷,即它不能很好地保護圖像細節(jié),在圖像去噪的同時也破壞了圖像的細節(jié)部分,從而使圖像變得模糊,不能很好地去除噪聲點。特別是椒鹽噪聲
實現(xiàn)代碼:
#include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include<ctime> using namespace cv; using namespace std; //均值濾波 void AverFiltering(const Mat &src,Mat &dst) { if (!src.data) return; //at訪問像素點 for (int i = 1; i<src.rows; ++i) for (int j = 1; j < src.cols; ++j) { if ((i - 1 >= 0) && (j - 1) >= 0 && (i + 1)<src.rows && (j + 1)<src.cols) {//邊緣不進行處理 dst.at<Vec3b>(i, j)[0] = (src.at<Vec3b>(i, j)[0] + src.at<Vec3b>(i - 1, j - 1)[0] + src.at<Vec3b>(i - 1, j)[0] + src.at<Vec3b>(i, j - 1)[0] + src.at<Vec3b>(i - 1, j + 1)[0] + src.at<Vec3b>(i + 1, j - 1)[0] + src.at<Vec3b>(i + 1, j + 1)[0] + src.at<Vec3b>(i, j + 1)[0] + src.at<Vec3b>(i + 1, j)[0]) / 9; dst.at<Vec3b>(i, j)[1] = (src.at<Vec3b>(i, j)[1] + src.at<Vec3b>(i - 1, j - 1)[1] + src.at<Vec3b>(i - 1, j)[1] + src.at<Vec3b>(i, j - 1)[1] + src.at<Vec3b>(i - 1, j + 1)[1] + src.at<Vec3b>(i + 1, j - 1)[1] + src.at<Vec3b>(i + 1, j + 1)[1] + src.at<Vec3b>(i, j + 1)[1] + src.at<Vec3b>(i + 1, j)[1]) / 9; dst.at<Vec3b>(i, j)[2] = (src.at<Vec3b>(i, j)[2] + src.at<Vec3b>(i - 1, j - 1)[2] + src.at<Vec3b>(i - 1, j)[2] + src.at<Vec3b>(i, j - 1)[2] + src.at<Vec3b>(i - 1, j + 1)[2] + src.at<Vec3b>(i + 1, j - 1)[2] + src.at<Vec3b>(i + 1, j + 1)[2] + src.at<Vec3b>(i, j + 1)[2] + src.at<Vec3b>(i + 1, j)[2]) / 9; } else {//邊緣賦值 dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0]; dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1]; dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2]; } } } //圖像椒鹽化 void salt(Mat &image, int num) { if (!image.data) return;//防止傳入空圖 int i, j; srand(time(NULL)); for (int x = 0; x < num; ++x) { i = rand() % image.rows; j = rand() % image.cols; image.at<Vec3b>(i, j)[0] = 255; image.at<Vec3b>(i, j)[1] = 255; image.at<Vec3b>(i, j)[2] = 255; } } void main() { Mat image = imread("路飛.jpg"); Mat Salt_Image; image.copyTo(Salt_Image); salt(Salt_Image, 3000); Mat image1(image.size(), image.type()); Mat image2; AverFiltering(Salt_Image, image1); blur(Salt_Image, image2, Size(3, 3));//openCV庫自帶的均值濾波函數(shù) imshow("原圖", image); imshow("自定義均值濾波", image1); imshow("openCV自帶的均值濾波", image2); waitKey(); }
效果圖:
可以看到圖片變模糊而且噪聲并沒有很有效的去除,該算法只是模糊化了圖片而已。
二.中值濾波
首先,我們復(fù)習(xí)中值。在一連串?dāng)?shù)字{1,4,6,8,9}中,數(shù)字6就是這串?dāng)?shù)字的中值。由此我們可以應(yīng)用到圖像處理中。依然我們在圖像中去3*3的矩陣,里面有9個像素點,我們將9個像素進行排序,最后將這個矩陣的中心點賦值為這九個像素的中值。
代碼:
//求九個數(shù)的中值 uchar Median(uchar n1, uchar n2, uchar n3, uchar n4, uchar n5, uchar n6, uchar n7, uchar n8, uchar n9) { uchar arr[9]; arr[0] = n1; arr[1] = n2; arr[2] = n3; arr[3] = n4; arr[4] = n5; arr[5] = n6; arr[6] = n7; arr[7] = n8; arr[8] = n9; for (int gap = 9 / 2; gap > 0; gap /= 2)//希爾排序 for (int i = gap; i < 9; ++i) for (int j = i - gap; j >= 0 && arr[j] > arr[j + gap]; j -= gap) swap(arr[j], arr[j + gap]); return arr[4];//返回中值 } //圖像椒鹽化 void salt(Mat &image, int num) { if (!image.data) return;//防止傳入空圖 int i, j; srand(time(NULL)); for (int x = 0; x < num; ++x) { i = rand() % image.rows; j = rand() % image.cols; image.at<Vec3b>(i, j)[0] = 255; image.at<Vec3b>(i, j)[1] = 255; image.at<Vec3b>(i, j)[2] = 255; } } //中值濾波函數(shù) void MedianFlitering(const Mat &src, Mat &dst) { if (!src.data)return; Mat _dst(src.size(), src.type()); for(int i=0;i<src.rows;++i) for (int j=0; j < src.cols; ++j) { if ((i - 1) > 0 && (i + 1) < src.rows && (j - 1) > 0 && (j + 1) < src.cols) { _dst.at<Vec3b>(i, j)[0] = Median(src.at<Vec3b>(i, j)[0], src.at<Vec3b>(i + 1, j + 1)[0], src.at<Vec3b>(i + 1, j)[0], src.at<Vec3b>(i, j + 1)[0], src.at<Vec3b>(i + 1, j - 1)[0], src.at<Vec3b>(i - 1, j + 1)[0], src.at<Vec3b>(i - 1, j)[0], src.at<Vec3b>(i, j - 1)[0], src.at<Vec3b>(i - 1, j - 1)[0]); _dst.at<Vec3b>(i, j)[1] = Median(src.at<Vec3b>(i, j)[1], src.at<Vec3b>(i + 1, j + 1)[1], src.at<Vec3b>(i + 1, j)[1], src.at<Vec3b>(i, j + 1)[1], src.at<Vec3b>(i + 1, j - 1)[1], src.at<Vec3b>(i - 1, j + 1)[1], src.at<Vec3b>(i - 1, j)[1], src.at<Vec3b>(i, j - 1)[1], src.at<Vec3b>(i - 1, j - 1)[1]); _dst.at<Vec3b>(i, j)[2] = Median(src.at<Vec3b>(i, j)[2], src.at<Vec3b>(i + 1, j + 1)[2], src.at<Vec3b>(i + 1, j)[2], src.at<Vec3b>(i, j + 1)[2], src.at<Vec3b>(i + 1, j - 1)[2], src.at<Vec3b>(i - 1, j + 1)[2], src.at<Vec3b>(i - 1, j)[2], src.at<Vec3b>(i, j - 1)[2], src.at<Vec3b>(i - 1, j - 1)[2]); } else _dst.at<Vec3b>(i, j) = src.at<Vec3b>(i, j); } _dst.copyTo(dst);//拷貝 } void main() { Mat image = imread("路飛.jpg"); Mat Salt_Image; image.copyTo(Salt_Image); salt(Salt_Image, 3000); Mat image3, image4; MedianFlitering(Salt_Image, image3); medianBlur(Salt_Image, image4, 3); imshow("自定義中值濾波處理后", image3); imshow("openCV自帶的中值濾波", image4); waitKey(); }
效果圖:
可以看到,椒鹽噪聲很好的被平滑了,而且也沒均值那樣模糊化太過于嚴(yán)重。
到此這篇關(guān)于openCV中值濾波和均值濾波的代碼實現(xiàn)的文章就介紹到這了,更多相關(guān)openCV中值濾波和均值濾波內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Anaconda安裝tensorflow報錯問題解決方法
這篇文章主要介紹了Anaconda安裝tensorflow報錯問題解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Python技巧之實現(xiàn)批量統(tǒng)一圖片格式和尺寸
大家在工作的時候基本都會接觸到很多的圖片,有時為了不同的工作需求需要修改圖片的尺寸或者大小。本文為大家整理了Python批量轉(zhuǎn)換圖片格式和統(tǒng)一圖片尺寸,希望對大家有所幫助2023-05-05python matplotlib坐標(biāo)軸設(shè)置的方法
本篇文章主要介紹了python matplotlib坐標(biāo)軸設(shè)置的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12