频率域滤波步骤小结

频率域滤波步骤小结

1、给定一幅大小为M*N的输入图像f(x,y), 由P >= 2M-1,Q >= 2N-1;得到填充参数P,Q,典型的我们选择,P=2M,Q=2N;

如果滤波的目的仅是粗糙的视觉分析,可以跳过此步骤;

2、对f(x,y) 添加必要数量的0,形成大小为P*Q的图像 fp(x,y);

3、用-1^{(x+y)} 乘以fp(x,y)移到其变换中心;

4、计算来自步骤3图像的DFT,得到F(u,v);

5、生成一个实的、对称的滤波函数H(u,v),其大小为P*Q,中心在(P/2,Q/2)处。用阵列相乘形成乘积G(u,v)=H(u,v)F(u,v);

6、得到处理后的图像  

            g_{p}(x,y) = \left \{ real\left [ \Im ^{-1}\left [ G(u,v)) \right ] \right ] \right \}*-1^{(x+y))}           其中为忽略由于计算不准确导致的寄生复分量,选择了实部,下标p表示我们处理的是填充后的阵列;

还有一种处理方法是取模值;magnitude()函数

7、通过从   g^{_{p}}(x,y)  的左上限提取M*N,得到最终的处理结果。

原始图像-------------高斯模糊图像

fp的谱---------------     g^{_{p}}(x,y) 图像

代码实现:

#include "opencv2/opencv.hpp"

using namespace cv;

int main(int argc, char * argv[])
{
    const char* filename = argc >=2 ? argv[1] : "../data/lena.jpg";

    Mat image = imread(filename, IMREAD_GRAYSCALE);
    if( image.empty())
        return -1;


    image = image(Rect(0,0,512,512));
    resize(image, image, Size(), 0.5,0.5);

    imshow("src",image);
    image.convertTo(image,CV_32FC1);
    for(int i=0; i<image.rows; i++){        //中心化
        float *p = image.ptr<float>(i);
        for(int j=0; j<image.cols; j++){
            p[j] = p[j] * pow(-1, i+j);
        }
    }

    ////////////////////////////////////////二维基本傅里叶变换//////////////////////////////////////////////////

//    Mat dftRe = Mat::zeros(image.size(), CV_32FC1);
//    Mat dftIm = Mat::zeros(image.size(), CV_32FC1);
//    for(int u=0; u<image.rows; u++)
//    {
//        float *pRe = dftRe.ptr<float>(u);
//        float *pIm = dftIm.ptr<float>(u);
//        for(int v=0; v<image.cols; v++)
//        {
//            float sinDft=0, cosDft=0;
//            for(int i=0; i<image.rows; i++)
//            {
//                float *q = image.ptr<float>(i);
//                for(int j=0; j<image.cols; j++)
//                {
//                    float temp = PI2 *((float)u*i/image.rows + (float)v*j/image.cols);
//                    sinDft -= q[j] * sin(temp);
//                    cosDft += q[j] * cos(temp);
//                }
//            }
//            pRe[v] = sinDft;
//            pIm[v] = cosDft;
//        }
//    }
//    divide(dftRe, image.rows*image.rows, dftRe);
//    divide(dftIm, image.rows*image.rows, dftIm);
//    multiply(dftIm, dftIm, dftIm);
//    multiply(dftRe, dftRe, dftRe);
//    add(dftRe, dftIm, dftRe);
//    pow(dftRe, 0.5, dftRe);
//    imshow("mydft", dftRe);

    ///////////////////////////////////////快速傅里叶变换/////////////////////////////////////////////////////
//    int oph = getOptimalDFTSize(image.rows);
//    int opw = getOptimalDFTSize(image.cols);
    int oph = 2*image.rows;
    int opw = 2*image.cols;
    Mat padded;
    copyMakeBorder(image, padded, 0, oph-image.rows, 0, opw-image.cols,
                   BORDER_CONSTANT, Scalar::all(0));

    Mat pad_show;
    normalize(padded, pad_show, 0, 255, CV_MINMAX);
    pad_show.convertTo(pad_show, CV_8U);
    imshow("padded",pad_show);

    Mat temp[] = {padded, Mat::zeros(padded.size(),CV_32FC1)};
    Mat complexI;
    merge(temp, 2, complexI);
    dft(complexI, complexI);    //傅里叶变换

    //显示频谱图
    split(complexI, temp);
    Mat aa;
    magnitude(temp[0], temp[1], aa);
    divide(aa, oph*opw, aa);
    imshow("pu",aa);

    /////////////////////////////////////////////频域滤波///////////////////////////////////////////////////////
    //生成频域滤波核
    Mat gaussianBlur(padded.size(), CV_32FC2);
    Mat gaussianSharpen(padded.size(), CV_32FC2);
    float D0 = 2*50*50.;
    for(int i=0; i<oph; i++)
    {
        float *p = gaussianBlur.ptr<float>(i);
        float *q = gaussianSharpen.ptr<float>(i);
        for(int j=0; j<opw; j++)
        {
            float d = pow(i-oph/2, 2) + pow(j-opw/2, 2);
            p[2*j] = expf(-d / D0);
            p[2*j+1] = expf(-d / D0);

            q[2*j] = 1 - expf(-d / D0);
            q[2*j+1] = 1 - expf(-d / D0);
        }
    }

    //高斯低通滤波, 高斯高通滤波
    multiply(complexI, gaussianBlur, gaussianBlur);
    multiply(complexI, gaussianSharpen, gaussianSharpen);

    //傅里叶反变换
    idft(gaussianBlur, gaussianBlur, CV_DXT_INVERSE);
    idft(gaussianSharpen, gaussianSharpen, CV_DXT_INVERSE);

    Mat dstBlur[2], dstSharpen[2];
    split(gaussianBlur, dstBlur);
    split(gaussianSharpen, dstSharpen);

    for(int i=0; i<oph; i++)        //中心化
    {
        float *p = dstBlur[0].ptr<float>(i);
        float *q = dstSharpen[0].ptr<float>(i);
        for(int j=0; j<opw; j++)
        {
            p[j] = p[j] * pow(-1, i+j);
            q[j] = q[j] * pow(-1, i+j);
        }
    }
    normalize(dstBlur[0], dstBlur[0], 1, 0, CV_MINMAX);
    normalize(dstSharpen[0], dstSharpen[0], 1, 0, CV_MINMAX);
    imshow("dstBlur",dstBlur[0]);
    imshow("dstSharpen",dstSharpen[0]);

    waitKey(0);

    return 1;
}
 

猜你喜欢

转载自blog.csdn.net/cyf15238622067/article/details/88288659