// 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;
}
One thing i am taking fourier() as 2 channels instead of only taking real channel. i am not sure if i am wrong in this regard. Also thats why i had to take filter as 2 channels also where 2 channels are used to represent data of Gray and Alpha in both cases.
Problem occurs at bitmapdata object initialization due to pixelFormat.Canonical parameter. The result of multiply of fourier matrix and filter matrix is in matrix float. All i want to do is to take its IDFT and display the filtered image. Not sure about the PixelFormat. Any help would be great.
Read this chapter: opencv DFT tutorial , C code DFT and opencv DFT pythonit explains all you need to know about DFT in opencv. About the types
1) Image is Real
2) DFT(Image) result in a complex image.
3) butterworth is a one channel matrix with the same size of image.
4) to filter, multiply each channel of DFT resulting image by butterworth filter. each channel must be multplied separated beacouse we have the real and complex parts of each pixel allocated in one channel as result of DFT.how filtering works
5) After filtering you will have a complex image
6) now you can apply the IDFT that have as result a real image. In opencv you maybe get as result a complex image, but the second channel are entirely zeros so you can discart.
Look here to:opencv C++ DFT