zoukankan      html  css  js  c++  java
  • 低通滤波

    #pragma 
    #include <opencv2/opencv.hpp>
    #include <iostream>
    using namespace cv;
    using namespace std;
    //低通滤波的类型:
    enum LPFILTER_TYPE { ILP_FILTER = 0, BLP_FILTER = 1, GLP_FILTER = 2 };
    namespace mycv
    {
        void Im_Contrast(cv::Mat src,cv::Mat &dst);
        cv::Mat createLPFilter(Size size, Point center, float radius, int type, int n);
        //1-理想低通滤波器,2-巴特沃斯低通滤波器,3-高斯低通滤波器
        void fftFilter(cv::Mat srcImage,cv::Mat&dstImage,int rudus,int type);
        
    }
    //构造低通滤波器
    cv::Mat mycv::createLPFilter(Size size, Point center, float radius, int type, int n)
    {
        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;
    }
    void mycv::Im_Contrast(cv::Mat src, cv::Mat & dst)
    {
        int r = src.rows;
        int c = src.cols;
        double minValue;
        double maxValue;
        cv::Point minLocation;
        cv::Point maxLocation;
        cv::Point matchLocation;
        minMaxLoc(src, &minValue, &maxValue, &minLocation, &maxLocation, cv::Mat());
        src.convertTo(dst, CV_32FC1);
        cv::Mat src_32fc = dst + 0.001;
        cv::log(src_32fc, src_32fc);
        float src_aver =exp(cv::sum(src_32fc)[0] / (r*c));//平均值
        dst = (dst / src_aver + 1);
        cv::log(dst, dst);
        float m_denormitor;
        m_denormitor=cv::log(maxValue / src_aver + 1);
        dst = dst / m_denormitor;
        dst.convertTo(dst, CV_8UC1,255,0);
    }
    
    void mycv::fftFilter(cv::Mat srcImage, cv::Mat & dstImage, int radius, int type)
    {
        //数据类型转换,转换为 浮点型
         
        Mat srcFc1;
        srcImage.convertTo(srcFc1, CV_32FC1, 1.0, 0.0);
        /* -- 第二步:每一个数乘以(-1)^(r+c) -- */
        for (int r = 0; r < srcFc1.rows; r++)
        {
            for (int c = 0; c < srcImage.cols; c++)
            {
                if ((r + c) % 2)
                    srcFc1.at<float>(r, c) *= -1;
            }
        }
        //【2】将输入图像延扩到最佳的尺寸,边界用0补充
        int m = getOptimalDFTSize(srcImage.rows);
        int n = getOptimalDFTSize(srcImage.cols);
        //将添加的像素初始化为0.
        Mat padded;
        copyMakeBorder(srcFc1, padded, 0, m - srcImage.rows, 0, n - srcImage.cols, BORDER_CONSTANT, Scalar::all(0));
        //【3】为傅立叶变换的结果(实部和虚部)分配存储空间。
        //将planes数组组合合并成一个多通道的数组complexI
        Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
        Mat complexI;
        merge(planes, 2, complexI);
        //【4】进行就地离散傅里叶变换
        dft(complexI, complexI);
        //【5】将复数转换为幅值,即=> log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
        split(complexI, planes); // 将多通道数组complexI分离成几个单通道数组,planes[0] = Re(DFT(I), planes[1] = Im(DFTI))
        magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude  
        Mat magnitudeImage = planes[0];//幅度谱
        //【6】进行对数尺度(logarithmic scale)缩放
        magnitudeImage += Scalar::all(1);
        log(magnitudeImage, magnitudeImage);//求自然对数
        normalize(magnitudeImage, magnitudeImage, 0, 1, NORM_MINMAX);
        //为了进行灰度级显示,做类型转换
        //magnitudeImage.convertTo(magnitudeImage, CV_8UC1, 255, 0);
        //找到傅里叶谱的最大值的坐标
        cv::Point maxLoc;//傅里叶谱的最大值的坐标
        minMaxLoc(magnitudeImage, NULL, NULL, NULL, &maxLoc);
    
        cv::Mat lpFilter = createLPFilter(magnitudeImage.size(), maxLoc, radius, type, 2);
    
        cv::Mat F_lpFilter;
    
        F_lpFilter.create(complexI.size(), complexI.type());
    
        for (int r = 0; r < F_lpFilter.rows; r++)
        {
            for (int c = 0; c < F_lpFilter.cols; c++)
            {
                //分别取出当前位置的快速傅里叶变换和理想低通滤波器的值
                Vec2f F_rc = complexI.at<Vec2f>(r, c);
                float lpFilter_rc = lpFilter.at<float>(r, c);
                //低通滤波器和图像的快速傅里叶变换对应位置相乘
                F_lpFilter.at<Vec2f>(r, c) = F_rc*lpFilter_rc;
            }
        }
    
        cv::dft(F_lpFilter, dstImage, DFT_SCALE + DFT_INVERSE + DFT_REAL_OUTPUT);
        /* -- 第九步:同乘以(-1)^(x+y) -- */
        for (int r = 0; r < dstImage.rows; r++)
        {
            for (int c = 0; c < dstImage.cols; c++)
            {
                if ((r + c) % 2)
                    dstImage.at<float>(r, c) *= -1;
            }
        }
        //注意将结果转换 CV_8U 类型
        normalize(dstImage, dstImage, 0,255, NORM_MINMAX);
        dstImage.convertTo(dstImage, CV_8UC1);
        dstImage = dstImage(Rect(0, 0, srcImage.cols, srcImage.rows)).clone();
    
    }
    
     
  • 相关阅读:
    动词的形态及变化(转)
    数论基础
    P1505 [国家集训队]旅游
    贪心常见题
    主席树
    卡常火车头
    AC自动机
    左偏树
    位运算
    Linux下Vim常用操作
  • 原文地址:https://www.cnblogs.com/hsy1941/p/14084489.html
Copyright © 2011-2022 走看看