EMGU/OpenCV不产生预期结果的图像的FFT
问题描述:
我试图用EMGU可视化图像的FFT。下面是我在处理图像:EMGU/OpenCV不产生预期结果的图像的FFT
这里是预期的结果:
这里就是我得到:
这里是我的代码:
Image<Gray, float> image = new Image<Gray, float>(@"C:\Users\me\Desktop\sample3.jpg");
IntPtr complexImage = CvInvoke.cvCreateImage(image.Size, Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_32F, 2);
CvInvoke.cvSetZero(complexImage);
CvInvoke.cvSetImageCOI(complexImage, 1);
CvInvoke.cvCopy(image, complexImage, IntPtr.Zero);
CvInvoke.cvSetImageCOI(complexImage, 0);
Matrix<float> dft = new Matrix<float>(image.Rows, image.Cols, 2);
CvInvoke.cvDFT(complexImage, dft, Emgu.CV.CvEnum.CV_DXT.CV_DXT_FORWARD, 0);
Matrix<float> outReal = new Matrix<float>(image.Size);
Matrix<float> outIm = new Matrix<float>(image.Size);
CvInvoke.cvSplit(dft, outReal, outIm, IntPtr.Zero, IntPtr.Zero);
Image<Gray, float> fftImage = new Image<Gray, float>(outReal.Size);
CvInvoke.cvCopy(outReal, fftImage, IntPtr.Zero);
pictureBox1.Image = image.ToBitmap();
pictureBox2.Image = fftImage.Log().ToBitmap();
我在这里犯了什么错误?
更新:根据罗杰罗兰的建议,这里是我的更新代码。结果看起来更好,但我不是100%确定它是正确的。这里的结果:
Image<Gray, float> image = new Image<Gray, float>(@"C:\Users\yytov\Desktop\sample3.jpg");
IntPtr complexImage = CvInvoke.cvCreateImage(image.Size, Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_32F, 2);
CvInvoke.cvSetZero(complexImage); // Initialize all elements to Zero
CvInvoke.cvSetImageCOI(complexImage, 1);
CvInvoke.cvCopy(image, complexImage, IntPtr.Zero);
CvInvoke.cvSetImageCOI(complexImage, 0);
Matrix<float> dft = new Matrix<float>(image.Rows, image.Cols, 2);
CvInvoke.cvDFT(complexImage, dft, Emgu.CV.CvEnum.CV_DXT.CV_DXT_FORWARD, 0);
//The Real part of the Fourier Transform
Matrix<float> outReal = new Matrix<float>(image.Size);
//The imaginary part of the Fourier Transform
Matrix<float> outIm = new Matrix<float>(image.Size);
CvInvoke.cvSplit(dft, 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)
// Swap quadrants
int cx = outReal.Cols/2;
int cy = outReal.Rows/2;
Matrix<float> q0 = outReal.GetSubRect(new Rectangle(0, 0, cx, cy));
Matrix<float> q1 = outReal.GetSubRect(new Rectangle(cx, 0, cx, cy));
Matrix<float> q2 = outReal.GetSubRect(new Rectangle(0, cy, cx, cy));
Matrix<float> q3 = outReal.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);
CvInvoke.cvNormalize(outReal, outReal, 0.0, 255.0, Emgu.CV.CvEnum.NORM_TYPE.CV_MINMAX, IntPtr.Zero);
Image<Gray, float> fftImage = new Image<Gray, float>(outReal.Size);
CvInvoke.cvCopy(outReal, fftImage, IntPtr.Zero);
pictureBox1.Image = image.ToBitmap();
pictureBox2.Image = fftImage.ToBitmap();
答
我不能对所得到的图像的大小/强度发表评论,但我可以给你一个点的图像的空间分布提示。
OpenCV不会重新安排将原点[0,0]置于图像中心的象限。您必须手动重新安排象限。
看第6步下页: http://docs.opencv.org/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.html
它是OpenCV的官方文档,所以它在C++中,但原则成立。
+0
我的代码的最新版本起作用。这是你的答案和罗杰罗兰的结果。谢谢! – Johnny
我还没有检查过你创建了DFT,但是你没有显示你的想法 - 你应该计算并显示对数功率谱,而不仅仅是Image.Log。请参阅此链接了解OpenCV示例 - http://opencv-users.1802565.n2.nabble.com/faint-image-after-Inverse-DFT-using-cvDFT-td2193072.html –
根据您的建议更新了我的代码,但我得到相同的结果。 – Johnny
还有一个想法。强度的差异是否可以由不同的比特深度引起? 理想的结果似乎是8位,四舍五入。但是你的结果是浮动图像。 – jnovacho