1. 程式人生 > >影象濾波----低通濾波,中值濾波,高通濾波,方向濾波(Sobel),拉普拉斯變換

影象濾波----低通濾波,中值濾波,高通濾波,方向濾波(Sobel),拉普拉斯變換

①觀察灰度分佈來描述一幅影象成為空間域,觀察影象變化的頻率被成為頻域。
②頻域分析:低頻對應區域的影象強度變化緩慢,高頻對應的變化快。低通濾波器去除了影象的高頻部分,高通濾波器去除了影象的低頻部分。

(1)低通濾波
①栗子:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
int main()
{
    // Read input image
cv::Mat image= cv::imread("boldt.jpg",0); if (!image.data) return 0; // Display the image cv::namedWindow("Original Image"); cv::imshow("Original Image",image); // Blur the image with a mean filter cv::Mat result; cv::blur(image,result,cv::Size(5,5)); // Display the blurred image
cv::namedWindow("Mean filtered Image"); cv::imshow("Mean filtered Image",result);

結果:每個畫素變為相鄰畫素的平均值, 快速的強度變化轉化為平緩的過度
這裡寫圖片描述
②栗子:近的畫素新增更多的權重。:高斯濾波器

cv::GaussianBlur(image,result,cv::Size(5,5),1.5);

這裡寫圖片描述

(2)中值濾波 :非線性濾波
有效去除椒鹽噪點

cv::medianBlur(image,result,5);

這裡寫圖片描述

(3)方向濾波(Sobel)
強調影象中的高頻分量,使用高通濾波器進行邊緣檢測。
Sobel運算元是一種經典的邊緣檢測線性濾波器,可被認為是影象在垂直和水平方向變化的測量。

#include <iostream>
#include <iomanip>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "laplacianZC.h"

int main()
{
     //Read input image
    cv::Mat image= cv::imread("boldt.jpg",0);
    if (!image.data)
        return 0; 

    // Display the image
    cv::namedWindow("Original Image");
    cv::imshow("Original Image",image);

    // Compute Sobel X derivative
    cv::Mat sobelX;
    cv::Sobel(image,sobelX,CV_8U,1,0,3,0.4,128);

    // Display the image
    cv::namedWindow("Sobel X Image");
    cv::imshow("Sobel X Image",sobelX);

    // Compute Sobel Y derivative
    cv::Mat sobelY;
    cv::Sobel(image,sobelY,CV_8U,0,1,3,0.4,128);

    // Display the image
    cv::namedWindow("Sobel Y Image");
    cv::imshow("Sobel Y Image",sobelY);

    // Compute norm of Sobel     得到sobel的摸
    cv::Sobel(image,sobelX,CV_16S,1,0);
    cv::Sobel(image,sobelY,CV_16S,0,1);
    cv::Mat sobel;
    //compute the L1 norm
    sobel= abs(sobelX)+abs(sobelY);

    double sobmin, sobmax;
    cv::minMaxLoc(sobel,&sobmin,&sobmax);
    std::cout << "sobel value range: " << sobmin << "  " << sobmax << std::endl;

    // Print window pixel values
    for (int i=0; i<12; i++) {
        for (int j=0; j<12; j++)
            std::cout << std::setw(5) << static_cast<int>(sobel.at<short>(i+135,j+362)) << " ";
        std::cout << std::endl;
    }
    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    // Conversion to 8-bit image
    // sobelImage = -alpha*sobel + 255
    cv::Mat sobelImage;
    sobel.convertTo(sobelImage,CV_8U,-255./sobmax,255);

    // Display the image
    cv::namedWindow("Sobel Image");
    cv::imshow("Sobel Image",sobelImage);

    // Apply threshold to Sobel norm (low threshold value)
    cv::Mat sobelThresholded;
    cv::threshold(sobelImage, sobelThresholded, 225, 255, cv::THRESH_BINARY);

    // Display the image
    cv::namedWindow("Binary Sobel Image (low)");
    cv::imshow("Binary Sobel Image (low)",sobelThresholded);

    // Apply threshold to Sobel norm (high threshold value)
    cv::threshold(sobelImage, sobelThresholded, 190, 255, cv::THRESH_BINARY);

    // Display the image
    cv::namedWindow("Binary Sobel Image (high)");
    cv::imshow("Binary Sobel Image (high)",sobelThresholded);

結果:
這裡寫圖片描述
(4)影象的拉普拉斯變換
是一種基於影象導數的高通線性濾波器,計算二階倒數已衡量影象的彎曲度。

// Compute Laplacian 3x3
    cv::Mat image = cv::imread("boldt.jpg", 0);
    cv::Mat laplace;
    cv::Laplacian(image,laplace,CV_8U,1,1,128);

    // Display the image
    cv::namedWindow("Laplacian Image");
    cv::imshow("Laplacian Image",laplace);

    // Print window pixel values
    for (int i=0; i<12; i++) {
        for (int j=0; j<12; j++)
            std::cout << std::setw(5) << static_cast<int>(laplace.at<uchar>(i+135,j+362))-128 << " ";
        std::cout << std::endl;
    }
    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    // Compute Laplacian 7x7
    cv::Laplacian(image,laplace,CV_8U,7,0.01,128);

    // Display the image 
    cv::namedWindow("Laplacian Image");
    cv::imshow("Laplacian Image",laplace);

    // Print window pixel values
    for (int i=0; i<12; i++) {
        for (int j=0; j<12; j++)
            std::cout << std::setw(5) << static_cast<int>(laplace.at<uchar>(i+135,j+362))-128 << " ";
        std::cout << std::endl;
    }

    // Extract small window
    cv::Mat window(image,cv::Rect(362,135,12,12));
    cv::namedWindow("Image window");
    cv::imshow("Image window",window);
    cv::imwrite("window.bmp",window);

    // Compute Laplacian using LaplacianZC class
    LaplacianZC laplacian;
    laplacian.setAperture(7);
    cv::Mat flap= laplacian.computeLaplacian(image);
    double lapmin, lapmax;
    cv::minMaxLoc(flap,&lapmin,&lapmax);
    std::cout << "Laplacian value range=[" << lapmin << "," << lapmax << "]\n";
    laplace= laplacian.getLaplacianImage();
    cv::namedWindow("Laplacian Image (7x7)");
    cv::imshow("Laplacian Image (7x7)",laplace);

    // Print Laplacian values
    std::cout << std::endl;
    for (int i=0; i<12; i++) {
        for (int j=0; j<12; j++)
            std::cout << std::setw(5) << static_cast<int>(flap.at<float>(i+135,j+362)/100) << " ";
        std::cout << std::endl;
    }
    std::cout << std::endl;

    // Compute and display the zero-crossing points
    cv::Mat zeros;
    zeros= laplacian.getZeroCrossings(lapmax);
    cv::namedWindow("Zero-crossings");
    cv::imshow("Zero-crossings",zeros);

    // Compute and display the zero-crossing points (Sobel version)
    zeros= laplacian.getZeroCrossings();
    zeros= laplacian.getZeroCrossingsWithSobel(50);
    cv::namedWindow("Zero-crossings (2)");
    cv::imshow("Zero-crossings (2)",zeros);

    // Print window pixel values
    for (int i=0; i<12; i++) {
        for (int j=0; j<12; j++)
            std::cout << std::setw(2) << static_cast<int>(zeros.at<uchar>(i+135,j+362)) << " ";
        std::cout << std::endl;
    }

    // Display the image with window
    cv::rectangle(image,cv::Point(362,135),cv::Point(374,147),cv::Scalar(255,255,255));
    cv::namedWindow("Original Image with window");
    cv::imshow("Original Image with window",image);

    cv::waitKey();
    return 0;
}

這裡寫圖片描述