Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用EMGU计算DFT及其逆函数?_C#_Image Processing_Emgucv - Fatal编程技术网

C# 如何使用EMGU计算DFT及其逆函数?

C# 如何使用EMGU计算DFT及其逆函数?,c#,image-processing,emgucv,C#,Image Processing,Emgucv,如何计算图像的DFT(使用EMGU),显示图像,然后计算反转以恢复原始图像 我要在这里回答我自己的问题,因为我花了一段时间才弄明白。为了测试它是否有效,这里有一个图像 这是应用DFT后的预期结果 不用多说,下面是代码: // Load image Image<Gray, float> image = new Image<Gray, float>(@"C:\Users\me\Desktop\lines.png"); // Transform 1 channel grays

如何计算图像的DFT(使用EMGU),显示图像,然后计算反转以恢复原始图像


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

为了测试它是否有效,这里有一个图像
这是应用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);
}
//加载图像
Image Image=新图像(@“C:\Users\me\Desktop\lines.png”);
//将1通道灰度图像转换为2通道图像
IntPtr complexImage=CvInvoke.cvCreateImage(image.Size,Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_32F,2);
CvInvoke.cvSetImageCOI(complexImage,1);//选择要复制到的频道
CvInvoke.cvCopy(image,complexImage,IntPtr.Zero);
CvInvoke.cvSetImageCOI(complexImage,0);//选择所有频道
//这将保存DFT数据
Matrix forwardDft=新矩阵(image.Rows,image.Cols,2);
CvInvoke.cvDFT(complexImage,forwardDft,Emgu.CV.CvEnum.CV_DXT.CV_DXT_FORWARD,0);
CvInvoke.cvreleasemage(ref complexImage);
//我们将显示震级
矩阵ForwardDFTMancing=GetDFTMancing(forwardDft);
开关象限(参考幅值);
//现在计算倒数,看看我们是否能得到原始值
矩阵反转ft=新矩阵(forwardDft.Rows,forwardDft.Cols,2);
CvInvoke.cvDFT(正向DFT,反向DFT,Emgu.CV.CvEnum.CV_DXT.CV_DXT_INV_SCALE,0);
矩阵ReversedFtMagnite=GetDtFtMagnite(reverseDft);
pictureBox1.Image=Image.ToBitmap();
pictureBox2.Image=matrix2位图(前向DFT幅值);
pictureBox3.Image=Matrix2位图(反转的ftMagnitude);
专用位图矩阵x2位图(矩阵矩阵)
{
CvInvoke.cvNormalize(矩阵,矩阵,0.0,255.0,Emgu.CV.CvEnum.NORM\u TYPE.CV\u MINMAX,IntPtr.Zero);
图像=新图像(矩阵大小);
matrix.CopyTo(图像);
返回image.ToBitmap();
}
//实部是幅值,虚部是相位。
//这里我们计算log(sqrt(Re^2+Im^2)+1)来得到震级和
//重新缩放,使所有内容都可见
私有矩阵GetDftMagnitude(矩阵fftData)
{
//傅里叶变换的实部
矩阵outReal=新矩阵(fftData.Size);
//傅里叶变换的虚部
矩阵outIm=新矩阵(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,新的MCvScalar(1.0),outReal,IntPtr.Zero);//1+Mag
CvInvoke.cvLog(outReal,outReal);//log(1+Mag)
回归现实;
}
//我们必须切换象限,以便原点位于图像中心
专用空心开关象限(参考矩阵)
{
int cx=矩阵Cols/2;
int cy=矩阵行/2;
矩阵q0=Matrix.GetSubRect(新矩形(0,0,cx,cy));
矩阵q1=Matrix.GetSubRect(新矩形(cx,0,cx,cy));
矩阵q2=矩阵.GetSubRect(新矩形(0,cy,cx,cy));
矩阵q3=Matrix.GetSubRect(新矩形(cx,cy,cx,cy));
矩阵tmp=新矩阵(q0.尺寸);
q0.CopyTo(tmp);
q3.复制到(q0);
tmp.CopyTo(第三季度);
q1.复制到(tmp);
q2.抄袭(q1);
tmp.CopyTo(第2季度);
}

这个答案中的大部分信息都来自OpenCV邮件列表中的a和Steve Eddins关于图像处理中FFT的文章。

+1我也是-很高兴你终于把它整理好了!接受你自己的答案,并承担责任:-)@RogerRowland忘了感谢你在OpenCV邮件列表中向我指出了这个问题。谢谢你能解释一下你在做什么吗?具体来说,您能否解释一下为什么会使用直观的forwardDft.Convert();不起作用?