• OpenCV 低通滤波


    #include<opencv2/core/core.hpp>
    #include<opencv2/highgui/highgui.hpp>
    #include<opencv2/imgproc/imgproc.hpp>
    using namespace std;
    using namespace cv;
    Mat I;//输入的图像矩阵
    Mat F;//图像的快速傅里叶变换
    Point maxLoc;//傅里叶谱的最大值的坐标
    int radius = 20;//截断频率
    const int Max_RADIUS = 100;//设置最大的截断频率
    Mat lpFilter;//低通滤波器
    int lpType = 0;//低通滤波器的类型
    const int MAX_LPTYPE = 2;
    Mat F_lpFilter;//低通傅里叶变换
    Mat FlpSpectrum;//低通傅里叶变换的傅里叶谱灰度级
    Mat result;//低通滤波后的效果
    string lpFilterspectrum = "低通傅里叶谱";//显示窗口的名称
    //快速傅里叶变换
    void fft2Image(InputArray _src, OutputArray _dst);
    //幅度谱
    void amplitudeSpectrum(InputArray _srcFFT, OutputArray _dstSpectrum)
    {
        //判断傅里叶变换是两个通道
        CV_Assert(_srcFFT.channels() == 2);
        //分离通道
        vector<Mat> FFT2Channel;
        split(_srcFFT, FFT2Channel);
        //计算傅里叶变换的幅度谱 sqrt(pow(R,2)+pow(I,2))
        magnitude(FFT2Channel[0], FFT2Channel[1], _dstSpectrum);
    }
    //幅度谱的灰度级显示
    Mat graySpectrum(Mat spectrum)
    {
        Mat dst;
        log(spectrum + 1, dst);
        //归一化
        normalize(dst, dst, 0, 1, NORM_MINMAX);
        //为了进行灰度级显示,做类型转换
        dst.convertTo(dst, CV_8UC1, 255, 0);
        return dst;
    }
    void callback_lpFilter(int, void*);
    /*
    低通滤波的类型:
    (理想低通滤波器,巴特沃斯低通滤波器,高斯低通滤波器)
    */
    enum LPFILTER_TYPE { ILP_FILTER = 0, BLP_FILTER = 1, GLP_FILTER = 2 };
    //构建低通滤波器
    Mat createLPFilter(Size size, Point center, float radius, int type, int n = 2);
    int main(int argc, char*argv[])
    {
        /* -- 第一步:读入图像矩阵 -- */
        I = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
        if (!I.data)
            return -1;
        imwrite("I1.jpg", I);
        //数据类型转换,转换为 浮点型
        Mat fI;
        I.convertTo(fI, CV_32FC1, 1.0, 0.0);
        /* -- 第二步:每一个数乘以(-1)^(r+c) -- */
        for (int r = 0; r < fI.rows; r++)
        {
            for (int c = 0; c < fI.cols; c++)
            {
                if ((r + c) % 2)
                    fI.at<float>(r, c) *= -1;
            }
        }
        /* -- 第三、四步:补零和快速傅里叶变换 -- */
        fft2Image(fI, F);
        //傅里叶谱
        Mat amplSpec;
        amplitudeSpectrum(F, amplSpec);
        //傅里叶谱的灰度级显示
        Mat spectrum = graySpectrum(amplSpec);
        imshow("原傅里叶谱的灰度级显示", spectrum);
        imwrite("spectrum.jpg", spectrum);
        //找到傅里叶谱的最大值的坐标
        minMaxLoc(spectrum, NULL, NULL, NULL, &maxLoc);
        /* -- 低通滤波 -- */
        namedWindow(lpFilterspectrum, WINDOW_AUTOSIZE);
        createTrackbar("低通类型:", lpFilterspectrum, &lpType, MAX_LPTYPE, callback_lpFilter);
        createTrackbar("半径:", lpFilterspectrum, &radius, Max_RADIUS, callback_lpFilter);
        callback_lpFilter(0, 0);
        waitKey(0);
        return 0;
    }
    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);
    }
    //回调函数:调整低通滤波的类型,及截断频率
    void callback_lpFilter(int, void*)
    {
        /* -- 第五步:构造低通滤波器 -- */
        lpFilter = createLPFilter(F.size(), maxLoc, radius, lpType, 2);
        /*-- 第六步:低通滤波器和图像快速傅里叶变换点乘 --*/
        F_lpFilter.create(F.size(), F.type());
        for (int r = 0; r < F_lpFilter.rows; r++)
        {
            for (int c = 0; c < F_lpFilter.cols; c++)
            {
                //分别取出当前位置的快速傅里叶变换和理想低通滤波器的值
                Vec2f F_rc = F.at<Vec2f>(r, c);
                float lpFilter_rc = lpFilter.at<float>(r, c);
                //低通滤波器和图像的快速傅里叶变换对应位置相乘
                F_lpFilter.at<Vec2f>(r, c) = F_rc * lpFilter_rc;
            }
        }
    
        //低通傅里叶变换的傅里叶谱
        amplitudeSpectrum(F_lpFilter, FlpSpectrum);
        //低通傅里叶谱的灰度级的显示
        FlpSpectrum = graySpectrum(FlpSpectrum);
        imshow(lpFilterspectrum, FlpSpectrum);
        imwrite("FlpSpectrum.jpg", FlpSpectrum);
        /* -- 第七、八步:对低通傅里叶变换执行傅里叶逆变换,并只取实部 -- */
        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);
        /* -- 第十步:截取左上部分,大小等于输入图像的大小 --*/
        result = result(Rect(0, 0, I.cols, I.rows)).clone();
        imshow("经过低通滤波后的图片", result);
        imwrite("lF.jpg", result);
    }
    //构造低通滤波器
    Mat createLPFilter(Size size, Point center, 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 - center.y)), 2) + pow(abs(float(c - center.x)), 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 - center.y, 2.0) + pow(c - center.x, 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 - center.x, 2.0) + pow(r - center.y, 2.0)) / (2 * pow(radius, 2.0))));
                }
            }
        }
        return lpFilter;
    }
     
  • 相关阅读:
    CentOS 7中cAdvisor的安装过程
    怎么查看centos版本
    使docker命令不用加sudo的方法
    Linux进程相关函数system,fork,exec函数族的区别
    git pre-commit hook failed 解决办法
    lint-staged 教程
    用webpack将多个scss文件打包成一个css文件
    js连按键盘事件
    vscode快捷键
    vim 操作命令大全
  • 原文地址:https://www.cnblogs.com/hsy1941/p/11395262.html
Copyright © 2020-2023  润新知