// Fourier transform of Image<Bgr,byte> orig object.
// output is matrix<float> with 2 channels.
private Matrix<float> fourier()
{
Image<Gray, float> image = orig.Convert<Gray, float>();
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);
return dft;
}
// butterworth filter with Do frequency and order n.
// Filter is returned as matrix<float> with 2 channels.
private Matrix<float> make_butterworth(int Do, int n)
{
Matrix<float> ff = fourier();
Matrix<float> tmp = new Matrix<float>(ff.Rows, ff.Cols, 2);
Point center=new Point(tmp.Rows/2,tmp.Cols/2);
for (int i=0;i<orig.Rows;i++)
for (int j = 0; j < orig.Cols; j++)
{
int Duv= (int) (Math.Sqrt( Math.Pow(i-center.X,2) + Math.Pow(j-center.Y,2)));
tmp[i, j] = (float) (1 / (1 + Math.Pow((Duv / Do), 2 * n)));
}
return tmp;
}
// The click event which will trigger fourier() and
make_butterworth() takes Do and n order input from user
and applies filter on orig image.
private void lowPassToolStripMenuItem2_Click(object sender, EventArgs e)
{
dialog_input d1 = new dialog_input("Enter values of Do and order n seperated by space:\n");
d1.ShowDialog();
string[] s = d1.t.Split(new char[] { ' ', ',' });
int fc = Convert.ToInt32(s[0]);
int order = Convert.ToInt32(s[1]);
Matrix<float> filter= make_butterworth(fc, order); // 2 channels
Matrix<float> m = fourier(); // 2 channels
m._Mul(filter);
// filter * with fourier image.
CvInvoke.cvDFT(m,m,CV_DXT.CV_DXT_INVERSE, 0);
IntPtr cmplx = CvInvoke.cvCreateImage(m.Size, IPL_DEPTH.IPL_DEPTH_32F, 2);
CvInvoke.cvSetZero(cmplx);
CvInvoke.cvSetImageCOI(cmplx, 0);
CvInvoke.cvCopy(m, cmplx, IntPtr.Zero);
Bitmap bm = new Bitmap(m.Width, m.Height);
BitmapData bd = bm.LockBits(new Rectangle
(0, 0, bm.Width, bm.Height),
ImageLockMode.ReadWrite,
PixelFormat.Canonical);
bd.Scan0 = cmplx;
bm.UnlockBits(bd);
pictureBox2.Image = bm;
}
有一件事我将傅里叶()作为2个频道,而不是只采用真正的频道。我不确定我在这方面是不是错了。这也就是为什么我必须将过滤器作为2个通道,其中2个通道用于表示灰色和Alpha的数据。
由于pixelFormat.Canonical参数,在bitmapdata对象初始化时出现问题。傅里叶矩阵和滤波器矩阵的乘法结果是矩阵浮点数。我想做的就是取其IDFT并显示过滤后的图像。不确定PixelFormat。任何帮助都会很棒。
答案 0 :(得分:0)
阅读本章:opencv DFT tutorial,C code DFT和opencv DFT python它解释了您在opencv中需要了解的有关DFT的所有信息。 关于类型
1)图像是真实的
2)DFT(图像)会产生复杂的图像。
3)butterworth是一个具有相同图像大小的单通道矩阵。
4)通过butterworth滤波器过滤,乘以DFT得到的图像的每个通道。每个通道必须是多重分离的beacouse,我们有一个通道中分配的每个像素的实部和复杂部分作为DFT的结果。how filtering works
5)过滤后你会有一个复杂的图像
6)现在你可以应用IDFT作为真实图像的结果。在opencv中你可能得到一个复杂的图像,但第二个通道完全是零,所以你可以放弃。
请点击此处:opencv C++ DFT