1. 程式人生 > >opencv學習筆記(十八)——影象非線性濾波

opencv學習筆記(十八)——影象非線性濾波

非線性濾波

非線性濾波是原始資料與濾波結果是一種邏輯關係,即用邏輯運算實現,而線性濾波採用的是算術運算結果。

中值濾波(Median filter)

中值濾波介紹

中值濾波是一種典型的非線性濾波技術,基本思想就是用畫素點鄰域灰度值得中值來代替該畫素點的灰度值。常用在脈衝噪聲,椒鹽噪聲的同時又能保留影象邊緣細節。

  • 優點:減小噪聲在濾波中的影響,從而達到更好的濾波效果,同時還能更好地保留邊緣細節。
  • 缺點:耗時更久。

中值濾波API函式介紹:

C++: void medianBlur(InputArray src,OutputArray dst, int ksize)  

引數詳解:

  • 第一個引數,InputArray型別的src,函式的輸入引數,填1、3或者4通道的Mat型別的影象;當ksize為3或者5的時候,影象深度需為CV_8U,CV_16U,或CV_32F其中之一,而對於較大孔徑尺寸的圖片,它只能是CV_8U。
  • 第二個引數,OutputArray型別的dst,即目標影象,函式的輸出引數,需要和源圖片有一樣的尺寸和型別。我們可以用Mat::Clone,以源圖片為模板,來初始化得到如假包換的目標圖。
  • 第三個引數,int型別的ksize,孔徑的線性尺寸(aperture linear
    size),注意這個引數必須是大於1的奇數,比如:3,5,7,9 …

中值濾波使用例項:

#include <opencv2/opencv.hpp>

int main()
{
    cv::Mat srcImage = cv::imread("medianBlur.jpg");
    cv::namedWindow("sourceImage");
    cv::imshow("sourceImage", srcImage);

    cv::Mat dstImage;
    cv::medianBlur(srcImage, dstImage, 3);
    cv::namedWindow("MedianBlur");
    cv:
:imshow("MedianBlur", dstImage); cv::waitKey(0); return 0; }

效果展示:
這裡寫圖片描述

雙邊濾波

雙邊濾波(Bilateral filter)是一種非線性的濾波方法,是結合影象的空間鄰近度和畫素值相似度的一種折衷處理,同時考慮空域資訊和灰度相似性,達到保邊去噪的目的。具有簡單、非迭代、區域性的特點。
雙邊濾波器的好處是可以做邊緣儲存(edge preserving),一般過去用的維納濾波或者高斯濾波去降噪,都會較明顯地模糊邊緣,對於高頻細節的保護效果並不明顯。雙邊濾波器顧名思義比高斯濾波多了一個高斯方差sigma-d,它是基於空間分佈的高斯濾波函式,所以在邊緣附近,離的較遠的畫素不會太多影響到邊緣上的畫素值,這樣就保證了邊緣附近畫素值的儲存。但是由於儲存了過多的高頻資訊,對於彩色影象裡的高頻噪聲,雙邊濾波器不能夠乾淨的濾掉,只能夠對於低頻資訊進行較好的濾波。

雙邊濾波API函式介紹:

C++: void bilateralFilter(InputArray src, OutputArraydst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)  
  • 第一個引數,InputArray型別的src,輸入影象,即源影象,需要為8位或者浮點型單通道、三通道的影象。
  • 第二個引數,OutputArray型別的dst,即目標影象,需要和源圖片有一樣的尺寸和型別。
  • 第三個引數,int型別的d,表示在過濾過程中每個畫素鄰域的直徑。如果這個值我們設其為非正數,那麼OpenCV會從第五個引數sigmaSpace來計算出它來。
  • 第四個引數,double型別的sigmaColor,顏色空間濾波器的sigma值。這個引數的值越大,就表明該畫素鄰域內有更寬廣的顏色會被混合到一起,產生較大的半相等顏色區域。
  • 第五個引數,double型別的sigmaSpace座標空間中濾波器的sigma值,座標空間的標註方差。他的數值越大,意味著越遠的畫素會相互影響,從而使更大的區域足夠相似的顏色獲取相同的顏色。當d>0,d指定了鄰域大小且與sigmaSpace無關。否則,d正比於sigmaSpace。
  • 第六個引數,int型別的borderType,用於推斷影象外部畫素的某種邊界模式。注意它有預設值BORDER_DEFAULT。

雙邊濾波例項:

#include <opencv2/opencv.hpp>

int main()
{
    cv::Mat srcImage = cv::imread("medianBlur.jpg");
    cv::namedWindow("sourceImage");
    cv::imshow("sourceImage", srcImage);

    cv::Mat dstImage;
    cv::bilateralFilter(srcImage, dstImage, 25, 25 * 2, 25 / 2);
    cv::namedWindow("bilateraFilter");
    cv::imshow("bilateraFilter", dstImage);

    cv::waitKey(0);
    return 0;
}

這裡寫圖片描述