c# - 如何使用 EMGU 计算 DFT 及其逆向?

标签 c# image-processing emgucv

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

我要在这里回答我自己的问题,因为我花了一段时间才弄明白。

最佳答案

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

不用多说,这里是代码:

// 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);
}

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

关于c# - 如何使用 EMGU 计算 DFT 及其逆向?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16812950/

相关文章:

java - 在android中使用opencv检测玩具车后面

c# - EmguCV 在查询高分辨率帧时性能非常差

c# - 如何(重复)从 .NET SslStream 读取超时?

c# - 通用字符串到枚举的转换

python - 是否可以使用 PIL 减少图像的深度?

Java - 在图像中正确绘制多行字符串

c# - opencv(emgu)中的模板匹配usink掩码

c# - 如何将 emgu 图像框大小设置为屏幕大小的百分比

c# - 如何使用 C# 设置打印机设置?

C#winform绑定(bind)源格式输出字符串到货币,不带$符号