zoukankan      html  css  js  c++  java
  • 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);
        /* -- 第十步:截取左上部分,大小等于输入图像的大小 --*/
        
        
        
    }
  • 相关阅读:
    Microsoft.mshtml到底是什么?
    编译.NET程序自动产生版本号的规则
    VB.NET(2005)中关于dll调用的错误信息(转)
    C# RichTextBox控件 滚动条 自动移至 最后一条记录处
    如何刪除richtextbox最後一行
    Using Hudson for C++/CMake/CppUnit
    让开发自动化: 选择持续集成服务器
    C#加载窗体错误
    各种CI工具对比表
    用 Hudson 实现 Visual Studio (C++) 项目的 daily build
  • 原文地址:https://www.cnblogs.com/hsy1941/p/11398722.html
Copyright © 2011-2022 走看看