圖像濾波
對圖像進行單個像素操作,主要是進行對比度和閾值處理
而圖像濾波在像素鄰域間進行,一來達到我們希望的效果,二來進一步進行圖像特征提取
濾波分為空間域和頻域濾波,空間域濾波又分線性、非線性濾波
常用的線性濾波有,均值濾波,高斯濾波;非線性濾波有中值濾波,雙邊濾波
線性濾波
均值模糊:blur()
void blur( InputArray src, OutputArray dst, Size ksize, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT );
- src 源圖像
- dst 輸出圖像
- ksize 卷積核
- anchor 錨點在核中心
- borderType 圖像邊界處理方式
卷積核如下圖所示
高斯模糊:GaussianBlur()
void GaussianBlur( InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT );
- src 源圖像
- dst 目的圖像
- ksize 高斯核,ksize.width與ksize.height可以不同,但必須為正的奇數.可以為0,通過simga計算得到
- sigmaX 高斯核在x方向的標准差
- sigmaY 高斯核在y方向的標准差
- borderType 邊界像素處理方式
均值與高斯模糊代碼:
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 int main() { 8 9 Mat srcImage = imread("D:/lena.png"); 10 if (!srcImage.data) { 11 cout << "could not load image" << endl; 12 return -1; 13 } 14 imshow("src Image", srcImage); 15 16 Mat bImage, gImage; 17 blur(srcImage, bImage, Size(3, 3)); 18 GaussianBlur(srcImage, gImage, Size(3, 3), 11, 11); 19 20 imshow("blur", bImage); 21 imshow("Gaussblur", bImage); 22 waitKey(0); 23 return 0; 24 }
效果圖:
非線性濾波
統計排序濾波器是一種非線性濾波器,最知名的便是中值濾波。它將濾波器所包含的圖像區域進行排序,選取中間值代替該點像素值,
其對椒鹽噪聲處理十分有效
中值濾波
void medianBlur( InputArray src, OutputArray dst, int ksize );
- src 源圖像
- dst 目的圖像
- ksize 孔徑尺寸,必須為大於1的奇數
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 8 //加入椒鹽噪聲 9 void salt(Mat image, int n) 10 { 11 int i, j; 12 for (int k = 0; k<n; k++) 13 { 14 // rand()是隨機數生成器 15 i = rand() % image.cols; 16 j = rand() % image.rows; 17 if (image.type() == CV_8UC1) 18 { // 灰度圖像 19 if(rand()% 2 == 0) 20 image.at<uchar>(j, i) = 255; 21 else 22 image.at<uchar>(j, i) = 0; 23 } 24 else if (image.type() == CV_8UC3) 25 { // 彩色圖像 26 if (rand()%2==0) { 27 image.at<cv::Vec3b>(j, i)[0] = 255; 28 image.at<cv::Vec3b>(j, i)[1] = 255; 29 image.at<cv::Vec3b>(j, i)[2] = 255; 30 } 31 else{ 32 image.at<cv::Vec3b>(j, i)[0] = 0; 33 image.at<cv::Vec3b>(j, i)[1] = 0; 34 image.at<cv::Vec3b>(j, i)[2] = 0; 35 } 36 } 37 } 38 } 39 40 int main() { 41 42 Mat srcImage = imread("D:/lena.png"); 43 if (!srcImage.data) { 44 cout << "could not load image" << endl; 45 return -1; 46 } 47 salt(srcImage, 1500); //加入椒鹽噪聲 48 imshow("src Image", srcImage); 49 50 Mat mImage; 51 medianBlur(srcImage, mImage, 3); //中值濾波 52 imshow("medianblur", mImage); 53 54 waitKey(0); 55 return 0; 56
效果圖:
雙邊濾波
1.介紹 雙邊濾波(Bilateral Filtering)是一種簡單,非迭代的保邊去噪算法。
在最廣泛的意義上“濾波”這一詞,濾波圖像在給定位置的值是輸入圖像在相同位置小鄰域中的函數。
例如,高斯低通濾波(Gaussian low-pass fitering)計算像素鄰域中得加權平均值,權重隨着遠離鄰域中心減少。
雖然可以給出這種權重下降的正式和定量解釋,但直覺是圖像通常在空間上緩慢變化,
因此鄰近像素可能具有相似的值,因此將它們平均在一起是合適的。
破壞這些鄰近像素的噪聲值與信號值相互關聯較少,因此,當信號被保留時,噪聲平均消失。
然而在邊緣處,假設的緩慢空間變化失效了,因此會被線性低通濾波器模糊。
如何在平滑圖像的同時,防止邊緣被平均呢?下面介紹雙邊濾波的基本思路。
2.思路
雙邊濾波的基本思想是在傳統空域濾波中引入值域濾波。兩個像素可以彼此接近,即占據附近的空間位置,或者它們可以彼此相似,即具有鄰近的值。
考慮應用於圖像的平移不變低通域濾波器:
歸一化常數
類似的定義值濾波器:
在這種情況下歸一化常數:
解決方案是結合空域和值濾波,組合濾波可以描述如下:
歸一化常數是,
結合空域與值域濾波被定義為雙邊濾波。在光滑的區域,鄰域中像素的值差異不大,雙邊濾波的效果與標准空間濾波等同,
平均的消除噪聲引起的像素值之間的小的、弱相關的差異。
在邊緣處,濾波器用其附近的明亮像素的平均值代替中心處的明亮像素,並且基本上忽略了暗像素,
反之,當濾波器以暗像素為中心時,則忽略了明亮像素。
至此,由於濾波器的空域成分,邊界得以保存;由於濾波器的值域成分,清晰的邊緣也得以保存
void bilateralFilter( InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT );
- src 單通道,浮點類型,源圖像
- dst 輸出圖像,與src類型一致
- d 用於濾波的每個像素鄰域的直徑。如果它是非正的,
它是從sigmaSpace計算出來的
- sigmaColor 較大的參數值意味着像素鄰域內的較遠顏色(參見sigmaSpace)將混合在一起
- sigmaSpace 坐標空間中的sigmaSpace濾波器。參數值越大意味着越遠處的像素(若像素足夠接近)會影響該點像素
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 int main() { 8 Mat src, dst; 9 src = imread("D:/kitten-orig.png"); 10 if (src.empty()) { 11 cout << "could not load image..." << endl; 12 return -1; 13 } 14 bilateralFilter(src, dst, 9, 75, 75); 15 namedWindow("input", CV_WINDOW_AUTOSIZE); 16 imshow("input", src); 17 namedWindow("output", CV_WINDOW_AUTOSIZE); 18 imshow("output", dst); 19 imwrite("kitten-outp.png", dst); 20 waitKey(0); 21 }
效果對比: