【问题标题】:How do I compute DFT and its reverse with EMGU?如何使用 EMGU 计算 DFT 及其反向?
【发布时间】:2013-05-29 11:42:43
【问题描述】:

如何计算图像的 DFT(使用 EMGU)、显示它,然后计算反向以返回原始图像?

我将在这里回答我自己的问题,因为我花了一段时间才弄清楚。

【问题讨论】:

    标签: c# image-processing emgucv


    【解决方案1】:

    为了测试它是否有效,这里有一张图片
    这是应用 DFT 后的预期结果。

    不用多说,代码如下:

    // Load image
    Image<Gray, float> image = new Image<Gray, float>(@"C:\Users\me\Desktop\lines.png");
    
    // Transform 1 channel grayscale image into 2 channel image
    IntPtr complexImage = CvInvoke.cvCreateImage(image.Size, Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_32F, 2);
    CvInvoke.cvSetImageCOI(complexImage, 1); // Select the channel to copy into
    CvInvoke.cvCopy(image, complexImage, IntPtr.Zero);
    CvInvoke.cvSetImageCOI(complexImage, 0); // Select all channels
    
    // This will hold the DFT data
    Matrix<float> forwardDft = new Matrix<float>(image.Rows, image.Cols, 2); 
    CvInvoke.cvDFT(complexImage, forwardDft, Emgu.CV.CvEnum.CV_DXT.CV_DXT_FORWARD, 0);
    
    CvInvoke.cvReleaseImage(ref complexImage);
    
    // We'll display the magnitude
    Matrix<float> forwardDftMagnitude = GetDftMagnitude(forwardDft); 
    SwitchQuadrants(ref forwardDftMagnitude); 
    
    // Now compute the inverse to see if we can get back the original
    Matrix<float> reverseDft = new Matrix<float>(forwardDft.Rows, forwardDft.Cols, 2);
    CvInvoke.cvDFT(forwardDft, reverseDft, Emgu.CV.CvEnum.CV_DXT.CV_DXT_INV_SCALE, 0);
    Matrix<float> reverseDftMagnitude = GetDftMagnitude(reverseDft);    
    
    pictureBox1.Image = image.ToBitmap();
    pictureBox2.Image = Matrix2Bitmap(forwardDftMagnitude);
    pictureBox3.Image = Matrix2Bitmap(reverseDftMagnitude);
    
    private Bitmap Matrix2Bitmap(Matrix<float> matrix)
    {
        CvInvoke.cvNormalize(matrix, matrix, 0.0, 255.0, Emgu.CV.CvEnum.NORM_TYPE.CV_MINMAX, IntPtr.Zero);            
    
        Image<Gray, float> image = new Image<Gray, float>(matrix.Size);
        matrix.CopyTo(image);
    
        return image.ToBitmap();
    }
    
    // Real part is magnitude, imaginary is phase. 
    // Here we compute log(sqrt(Re^2 + Im^2) + 1) to get the magnitude and 
    // rescale it so everything is visible
    private Matrix<float> GetDftMagnitude(Matrix<float> fftData)
    {
        //The Real part of the Fourier Transform
        Matrix<float> outReal = new Matrix<float>(fftData.Size);
        //The imaginary part of the Fourier Transform
        Matrix<float> outIm = new Matrix<float>(fftData.Size);
        CvInvoke.cvSplit(fftData, outReal, outIm, IntPtr.Zero, IntPtr.Zero);
    
        CvInvoke.cvPow(outReal, outReal, 2.0);
        CvInvoke.cvPow(outIm, outIm, 2.0);
    
        CvInvoke.cvAdd(outReal, outIm, outReal, IntPtr.Zero);
        CvInvoke.cvPow(outReal, outReal, 0.5);
    
        CvInvoke.cvAddS(outReal, new MCvScalar(1.0), outReal, IntPtr.Zero); // 1 + Mag
        CvInvoke.cvLog(outReal, outReal); // log(1 + Mag)            
    
        return outReal;
    }
    
    // We have to switch quadrants so that the origin is at the image center
    private void SwitchQuadrants(ref Matrix<float> matrix)
    {
        int cx = matrix.Cols / 2;
        int cy = matrix.Rows / 2;
    
        Matrix<float> q0 = matrix.GetSubRect(new Rectangle(0, 0, cx, cy));
        Matrix<float> q1 = matrix.GetSubRect(new Rectangle(cx, 0, cx, cy));
        Matrix<float> q2 = matrix.GetSubRect(new Rectangle(0, cy, cx, cy));
        Matrix<float> q3 = matrix.GetSubRect(new Rectangle(cx, cy, cx, cy));
        Matrix<float> tmp = new Matrix<float>(q0.Size);
    
        q0.CopyTo(tmp);
        q3.CopyTo(q0);
        tmp.CopyTo(q3);
        q1.CopyTo(tmp);
        q2.CopyTo(q1);
        tmp.CopyTo(q2);
    }
    

    此答案中的大部分信息来自 OpenCV 邮件列表上的 question 和图像处理中 FFT 的 Steve Eddins 的 article

    【讨论】:

    • 我也+1 - 很高兴你终于把它整理好了!接受你自己的答案并获得荣誉:-)
    • @RogerRowland 忘记感谢您在 OpenCV 邮件列表中向我指出该问题。谢谢!
    • 你能解释一下你在做什么吗?具体来说,你能解释一下为什么直观的 forwardDft.Convert();不工作?
    猜你喜欢
    • 2017-01-05
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 2020-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多