// Function calculates PSD(Power spectrum density) by fft with two flags // flag = 0 means to return PSD // flag = 1 means to return log(PSD) public static void calcPSD(ref Mat inputImg, ref Mat outputImg, bool flag = false) { Mat[] planes = { new Mat <float>(inputImg.Clone()), Mat.Zeros(inputImg.Size(), MatType.CV_32F) }; Mat complexI = new Mat(); Cv2.Merge(planes, complexI); Cv2.Dft(complexI, complexI); Cv2.Split(complexI, out planes); // planes[0] = Re(DFT(I)), planes[1] = Im(DFT(I)) planes[0].Set <float>(0, 0); planes[1].Set <float>(0, 0); // compute the PSD = sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)^2 Mat imgPSD = new Mat(); Cv2.Magnitude(planes[0], planes[1], imgPSD); //imgPSD = sqrt(Power spectrum density) Cv2.Pow(imgPSD, 2, imgPSD); //it needs ^2 in order to get PSD outputImg = imgPSD; // logPSD = log(1 + PSD) if (flag) { Mat imglogPSD = new Mat(); imglogPSD = imgPSD + Scalar.All(1); Cv2.Log(imglogPSD, imglogPSD); outputImg = imglogPSD; } }
public static void filter2DFreq(ref Mat inputImg, ref Mat outputImg, ref Mat H) { Mat[] planes = { new Mat <float>(inputImg.Clone()), Mat.Zeros(inputImg.Size(), MatType.CV_32F) }; Mat complexI = new Mat(); Cv2.Merge(planes, complexI); Cv2.Dft(complexI, complexI, DftFlags.Scale); Mat[] planesH = { new Mat <float>(H.Clone()), Mat.Zeros(H.Size(), MatType.CV_32F) }; Mat complexH = new Mat(); Cv2.Merge(planesH, complexH); Mat complexIH = new Mat(); Cv2.MulSpectrums(complexI, complexH, complexIH, 0); Cv2.Idft(complexIH, complexIH); Cv2.Split(complexIH, out planes); outputImg = planes[0]; }
public void Run() { Mat img = Cv2.ImRead(FilePath.Image.Lenna, ImreadModes.GrayScale); // expand input image to optimal size Mat padded = new Mat(); int m = Cv2.GetOptimalDFTSize(img.Rows); int n = Cv2.GetOptimalDFTSize(img.Cols); // on the border add zero values Cv2.CopyMakeBorder(img, padded, 0, m - img.Rows, 0, n - img.Cols, BorderTypes.Constant, Scalar.All(0)); // Add to the expanded another plane with zeros Mat paddedF32 = new Mat(); padded.ConvertTo(paddedF32, MatType.CV_32F); Mat[] planes = { paddedF32, Mat.Zeros(padded.Size(), MatType.CV_32F) }; Mat complex = new Mat(); Cv2.Merge(planes, complex); // this way the result may fit in the source matrix Mat dft = new Mat(); Cv2.Dft(complex, dft); // compute the magnitude and switch to logarithmic scale // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)) Mat[] dftPlanes; Cv2.Split(dft, out dftPlanes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) // planes[0] = magnitude Mat magnitude = new Mat(); Cv2.Magnitude(dftPlanes[0], dftPlanes[1], magnitude); magnitude += Scalar.All(1); // switch to logarithmic scale Cv2.Log(magnitude, magnitude); // crop the spectrum, if it has an odd number of rows or columns Mat spectrum = magnitude[ new Rect(0, 0, magnitude.Cols & -2, magnitude.Rows & -2)]; // rearrange the quadrants of Fourier image so that the origin is at the image center int cx = spectrum.Cols / 2; int cy = spectrum.Rows / 2; Mat q0 = new Mat(spectrum, new Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant Mat q1 = new Mat(spectrum, new Rect(cx, 0, cx, cy)); // Top-Right Mat q2 = new Mat(spectrum, new Rect(0, cy, cx, cy)); // Bottom-Left Mat q3 = new Mat(spectrum, new Rect(cx, cy, cx, cy)); // Bottom-Right // swap quadrants (Top-Left with Bottom-Right) Mat tmp = new Mat(); q0.CopyTo(tmp); q3.CopyTo(q0); tmp.CopyTo(q3); // swap quadrant (Top-Right with Bottom-Left) q1.CopyTo(tmp); q2.CopyTo(q1); tmp.CopyTo(q2); // Transform the matrix with float values into a Cv2.Normalize(spectrum, spectrum, 0, 1, NormTypes.MinMax); // Show the result Cv2.ImShow("Input Image", img); Cv2.ImShow("Spectrum Magnitude", spectrum); // calculating the idft Mat inverseTransform = new Mat(); Cv2.Dft(dft, inverseTransform, DftFlags.Inverse | DftFlags.RealOutput); Cv2.Normalize(inverseTransform, inverseTransform, 0, 1, NormTypes.MinMax); Cv2.ImShow("Reconstructed by Inverse DFT", inverseTransform); Cv2.WaitKey(); }
/// <summary> /// 离散傅里叶变换 /// </summary> /// <param name="source"></param> /// <returns></returns> public static Bitmap Dft(this Bitmap source) { var fileName = Path.GetTempPath() + "\\" + Guid.NewGuid().ToString() + ".bmp"; File.WriteAllBytes(fileName, source.GetBitmapFileData()); using (var img = Cv2.ImRead(fileName, ImreadModes.Grayscale)) { fileName = Path.GetTempPath() + "\\" + Guid.NewGuid().ToString() + ".bmp"; var padded = new Mat(); // 计算最佳 DFT 尺寸 var m = Cv2.GetOptimalDFTSize(img.Rows); var n = Cv2.GetOptimalDFTSize(img.Cols); Cv2.CopyMakeBorder(img, padded, 0, m - img.Rows, 0, n - img.Cols, BorderTypes.Constant, Scalar.All(0)); var paddedF32 = new Mat(); padded.ConvertTo(paddedF32, MatType.CV_32F); Mat[] planes = { paddedF32, Mat.Zeros(padded.Size(), MatType.CV_32F) }; var complex = new Mat(); Cv2.Merge(planes, complex); // 执行 dft var dft = new Mat(); Cv2.Dft(complex, dft); // log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)) Cv2.Split(dft, out var dftPlanes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) // planes[0] = magnitude var magnitude = new Mat(); Cv2.Magnitude(dftPlanes[0], dftPlanes[1], magnitude); magnitude += Scalar.All(1); Cv2.Log(magnitude, magnitude); var spectrum = magnitude[ new Rect(0, 0, magnitude.Cols & -2, magnitude.Rows & -2)]; // 交换象限 var cx = spectrum.Cols / 2; var cy = spectrum.Rows / 2; var q0 = new Mat(spectrum, new Rect(0, 0, cx, cy)); // 左上 var q1 = new Mat(spectrum, new Rect(cx, 0, cx, cy)); // 右上 var q2 = new Mat(spectrum, new Rect(0, cy, cx, cy)); // 左下 var q3 = new Mat(spectrum, new Rect(cx, cy, cx, cy)); // 右下 var tmp = new Mat(); q0.CopyTo(tmp); q3.CopyTo(q0); tmp.CopyTo(q3); q1.CopyTo(tmp); q2.CopyTo(q1); tmp.CopyTo(q2); // 归一化到 0~255 Cv2.Normalize(spectrum, spectrum, 0, 255, NormTypes.MinMax); var result = new Mat(); spectrum.ConvertTo(result, MatType.CV_8U); result.SaveImage(fileName); return(new Bitmap(fileName)); } }
public Mat fourier(Mat img) { Mat padded = new Mat(); int m = Cv2.GetOptimalDFTSize(img.Rows); int n = Cv2.GetOptimalDFTSize(img.Cols); // on the border add zero values Cv2.CopyMakeBorder(img, padded, 0, m - img.Rows, 0, n - img.Cols, BorderTypes.Constant, Scalar.All(0)); // Add to the expanded another plane with zeros Mat paddedF32 = new Mat(); padded.ConvertTo(paddedF32, MatType.CV_32F); Mat[] planes = { paddedF32, Mat.Zeros(padded.Size(), MatType.CV_32F) }; Mat complex = new Mat(); Cv2.Merge(planes, complex); // this way the result may fit in the source matrix Mat dft = new Mat(); Cv2.Dft(complex, dft); // compute the magnitude and switch to logarithmic scale // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)) Mat[] dftPlanes; Cv2.Split(dft, out dftPlanes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) // planes[0] = magnitude Mat magnitude = new Mat(); Cv2.Magnitude(dftPlanes[0], dftPlanes[1], magnitude); magnitude += Scalar.All(1); // switch to logarithmic scale Cv2.Log(magnitude, magnitude); // crop the spectrum, if it has an odd number of rows or columns Mat spectrum = magnitude[ new OpenCvSharp.Rect(0, 0, magnitude.Cols & -2, magnitude.Rows & -2)]; // rearrange the quadrants of Fourier image so that the origin is at the image center int cx = spectrum.Cols / 2; int cy = spectrum.Rows / 2; Mat q0 = new Mat(spectrum, new OpenCvSharp.Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant Mat q1 = new Mat(spectrum, new OpenCvSharp.Rect(cx, 0, cx, cy)); // Top-Right Mat q2 = new Mat(spectrum, new OpenCvSharp.Rect(0, cy, cx, cy)); // Bottom-Left Mat q3 = new Mat(spectrum, new OpenCvSharp.Rect(cx, cy, cx, cy)); // Bottom-Right // swap quadrants (Top-Left with Bottom-Right) Mat tmp = new Mat(); q0.CopyTo(tmp); q3.CopyTo(q0); tmp.CopyTo(q3); // swap quadrant (Top-Right with Bottom-Left) q1.CopyTo(tmp); q2.CopyTo(q1); tmp.CopyTo(q2); // Transform the matrix with float values into a Cv2.Normalize(spectrum, spectrum, 0, 1, NormTypes.MinMax); // calculating the idft Mat inverseTransform = new Mat(); Cv2.Dft(dft, inverseTransform, DftFlags.Inverse | DftFlags.RealOutput); Cv2.Normalize(inverseTransform, inverseTransform, 0, 1, NormTypes.MinMax); double minVal = 0.0, maxVal = 0.0; Cv2.MinMaxIdx(inverseTransform, out minVal, out maxVal); Cv2.ConvertScaleAbs(inverseTransform, inverseTransform, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal)); return(inverseTransform); }