OpenCV中濾波器的操作


1.圖像銳化操作(純手動擋)

圖像濾波分為空域濾波和頻域濾波兩個,這篇隨筆主要針對空域濾波。

當然空域與頻域之間是有一定關系的,比如均值濾波器,就是一種低通濾波,而像邊緣檢測,空域中一般使用的是拉普拉斯算子,其也是一種高通濾波。

大家都知道空域中的拉普拉斯算子是這樣子的:

0 -1 0
-1 4 -1
0 -1 0

這個表示的是縱橫兩個方向的二階導,將這個算子應在圖像上可以得到圖像的邊緣痕跡,如果把邊緣再疊加到圖像上,則可以是邊緣更加明顯,這個操作叫做銳化處理,銳化處理的算子可以表示為:

0 -1 0
-1 5 -1
0 -1 0

之前我們知道使用指針來操作像素,格式為:

數據類型* 指針名稱 = 矩陣名稱.ptr<數據類型>(行數);

使用算子時一般我們要同時處理3行以上,我們只需要同時建立這些指針即可。

在這個操作中,我們保存原來的圖像,因此我們建立的指針類型為const,同時我們新加載一幅圖像,建立普通指針來操作:

void sharpen(cv::Mat image,cv::Mat sharpen_image)
{
    int num_channels = image.channels();

    for (int r = 1; r < image.rows - 1; r++)
    {
        const uchar* last_r = image.ptr<const uchar>(r - 1);
        const uchar* curr_r = image.ptr<const uchar>(r);
        const uchar* next_r = image.ptr<const uchar>(r + 1);
        uchar* output = sharpen_image.ptr<uchar>(r);
        for (int c = num_channels; c < (image.cols - 1)*num_channels; c++)
        {
            output[c] =cv::saturate_cast<uchar> (5 * curr_r[c]-last_r[c] - curr_r[c - 1] - curr_r[c + 1] - next_r[c]) ;
        }
    }
    sharpen_image.row(0).setTo(cv::Scalar(0, 0, 0));
    sharpen_image.row(sharpen_image.rows-1).setTo(cv::Scalar(0, 0, 0));
    sharpen_image.col(0).setTo(cv::Scalar(0, 0, 0));
    sharpen_image.col(sharpen_image.cols - 1).setTo(cv::Scalar(0, 0, 0));
}

這里我使用了uchar型,好處是可以處理各種類型的圖像,若是灰度圖像,下面4行的cv::Scalar(0,0,0)需要變成cv::Scalar(0);若只處理RGB圖像,也可以使用cv::Vec3b型:

void sharpenRGB(cv::Mat image, cv::Mat sharpen_image)
{
    int num_channels = image.channels();

    for (int r = 1; r < image.rows - 1; r++)
    {
        const cv::Vec3b* last_r = image.ptr<cv::Vec3b>(r - 1);
        const cv::Vec3b* curr_r = image.ptr<cv::Vec3b>(r);
        const cv::Vec3b* next_r = image.ptr<cv::Vec3b>(r + 1);
        cv::Vec3b* output = sharpen_image.ptr<cv::Vec3b>(r);
        for (int c = 1; c < image.cols - 1; c++)
        {
            for (int i = 0; i < 3;i++)
                output[c] = cv::saturate_cast<uchar> (5 * curr_r[c][i] - last_r[c][i] - curr_r[c - 1][i] - curr_r[c + 1][i] - next_r[c][i]);
        }
    }
    sharpen_image.row(0).setTo(cv::Scalar(0, 0, 0));
    sharpen_image.row(sharpen_image.rows - 1).setTo(cv::Scalar(0, 0, 0));
    sharpen_image.col(0).setTo(cv::Scalar(0, 0, 0));
    sharpen_image.col(sharpen_image.cols - 1).setTo(cv::Scalar(0, 0, 0));
}

圖像處理結果如下:

顏色對比度鮮明er。

2.使用自帶函數進行2D濾波器運算

當然這個程序是純手動擋的,OpenCV提供給了我們一些縣城的函數,讓我們直接可以基於算子進行運算:
cv::filter2D(輸入圖像名稱,輸出圖像名稱,輸入圖像名稱.depth(),kernel);

kernel指代內核,即算子模型,其定義方法為:


cv::Mat kernel(3(尺寸),3(尺寸),CV_32F(浮點數),cv::Scalar(0)(所有元素初始化為0);

kernel.at<float>(1,1)=5.0;

kernel.at<float>(0,1)=-1.0;

kernel.at<float>(1,0)=-1.0;

kernel.at<float>(2,1)=-1.0;

kernel.at<float>(1,2)=-1.0;

這樣可以提高效率,並易於改變算子進行新的運算。

3.自帶的濾波函數

3.1均值濾波器

均值濾波器在OpenCV中用blur(模糊)定義,函數為:

cv::blur(輸入圖片名稱,輸出圖片名稱,cv::Size(5(尺寸),5(尺寸)));

int _tmain(int argc, _TCHAR* argv[])
{
    cv::Mat image;
    cv::Mat result;
    image = cv::imread("D://OpenCV//yedanshu.jpg");
    cv::namedWindow("Original");
    cv::blur(image, result, cv::Size(5, 5));
    cv::namedWindow("Filtered");
    cv::imshow("Original", image);
    cv::imshow("Filtered", result);
    cv::waitKey(0);
    return 0;
}

 

3.2高斯加權的均值濾波:

這是為了讓臨近的像素具有更高的權值,所以在清晰度上相比於一般均值濾波有很大突破,實現代碼為:

cv::GaussianBlur(image, result, cv::Size(5, 5),1.5); //1.5代表方差

3.3中值濾波器

對於椒鹽噪聲來說,最好的處理辦法即是中值濾波,中值濾波在OpenCV中也有直接的辦法:

cv::medianBlur(輸入圖片名稱,輸出圖片名稱,int 濾波器尺寸);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM