OpenCV 低通濾波(可設置頻率)


#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <fstream>
using namespace std;
using namespace cv;
int radius = 1;//截斷頻率
Mat img;
/*(理想低通濾波器,巴特沃斯低通濾波器,高斯低通濾波器)*/
enum LPFILTER_TYPE { ILP_FILTER = 0, BLP_FILTER = 1, GLP_FILTER = 2 };
void fft2Image(InputArray _src, OutputArray _dst);
Mat createLPFilter(Size size, float radius, int type, int n);
void callback_lpFilter(Mat src, int lpType, Mat&result);

int main()
{
    
    
    Mat img = imread("1.jpg", 0);
    //數據類型轉換,轉換為 浮點型
    Mat src_32;
    img.convertTo(src_32, CV_32FC1, 1.0, 0.0);
    /* -- 第二步:每一個數乘以(-1)^(r+c) -- */
    for (int r = 0; r < src_32.rows; r++)
    {
        for (int c = 0; c < src_32.cols; c++)
        {
            if ((r + c) % 2)
                src_32.at<float>(r, c) *= -1;
        }
    }
    /* -- 第三、四步:補零和快速傅里葉變換 -- */
    Mat src_dft;
    fft2Image(src_32, src_dft);
    //傅里葉譜
    int lpType = 0;
    Mat lowpass;
    callback_lpFilter(src_dft,lpType, lowpass);
    imshow("d", lowpass);
}
void fft2Image(InputArray _src, OutputArray _dst)
{
    //得到Mat類型
    Mat src = _src.getMat();
    //判斷位深
    CV_Assert(src.type() == CV_32FC1 || src.type() == CV_64FC1);
    CV_Assert(src.channels() == 1 || src.channels() == 2);
    int rows = src.rows;
    int cols = src.cols;
    //為了進行快速的傅里葉變換,我們經行和列的擴充,找到最合適擴充值
    Mat padded;
    int rPadded = getOptimalDFTSize(rows);
    int cPadded = getOptimalDFTSize(cols);
    //進行邊緣擴充,擴充值為零
    copyMakeBorder(src, padded, 0, rPadded - rows, 0, cPadded - cols, BORDER_CONSTANT, Scalar::all(0));
    //快速的傅里葉變換(雙通道:用於存儲實部 和 虛部)
    dft(padded, _dst, DFT_COMPLEX_OUTPUT);
}
//構造低通濾波器
Mat createLPFilter(Size size, float radius, int type, int n = 2)
{
    Mat lpFilter = Mat::zeros(size, CV_32FC1);
    int rows = size.height;
    int cols = size.width;
    if (radius <= 0)
        return lpFilter;
    //構造理想低通濾波器
    if (type == ILP_FILTER)
    {
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                float norm2 = pow(abs(float(r - rows/2)), 2) + pow(abs(float(c - cols/2)), 2);
                if (sqrt(norm2) < radius)
                    lpFilter.at<float>(r, c) = 1;
                else
                    lpFilter.at<float>(r, c) = 0;
            }
        }
    }
    //構造巴特沃斯低通濾波器
    if (type == BLP_FILTER)
    {
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                lpFilter.at<float>(r, c) = float(1.0 / (1.0 + pow(sqrt(pow(r - rows / 2, 2.0) + pow(c -cols/2, 2.0)) / radius, 2.0*n)));
            }
        }
    }
    //構造高斯低通濾波
    if (type == GLP_FILTER)
    {
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                lpFilter.at<float>(r, c) = float(exp(-(pow(c - cols / 2, 2.0) + pow(r - rows/2, 2.0)) / (2 * pow(radius, 2.0))));
            }
        }
    }
    return lpFilter;
}
//低通濾波src傅里葉變換圖像
void callback_lpFilter(Mat src,int lpType, Mat &result)
{
    /* -- 第五步:構造低通濾波器 -- */
    Mat lpFilter = createLPFilter(src.size(), radius, lpType, 2);
    /*-- 第六步:低通濾波器和圖像快速傅里葉變換點乘 --*/
    Mat F_lpFilter;
    F_lpFilter.create(src.size(), src.type());
    for (int r = 0; r < F_lpFilter.rows; r++)
    {
        for (int c = 0; c < F_lpFilter.cols; c++)
        {
            //分別取出當前位置的快速傅里葉變換和理想低通濾波器的值
            Vec2f F_rc = src.at<Vec2f>(r, c);
            float lpFilter_rc = lpFilter.at<float>(r, c);
            //低通濾波器和圖像的快速傅里葉變換對應位置相乘
            F_lpFilter.at<Vec2f>(r, c) = F_rc * lpFilter_rc;
        }
    }

    /* -- 第七、八步:對低通傅里葉變換執行傅里葉逆變換,並只取實部 -- */
    
    dft(F_lpFilter, result, DFT_SCALE + DFT_INVERSE + DFT_REAL_OUTPUT);
    /* -- 第九步:同乘以(-1)^(x+y) -- */
    for (int r = 0; r < result.rows; r++)
    {
        for (int c = 0; c < result.cols; c++)
        {
            if ((r + c) % 2)
                result.at<float>(r, c) *= -1;
        }
    }
    //注意將結果轉換 CV_8U 類型
    result.convertTo(result, CV_8UC1, 1.0, 0);
    /* -- 第十步:截取左上部分,大小等於輸入圖像的大小 --*/
    
    
    
}

 


免責聲明!

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



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