サンプルプログラムをほとんどそのまま流用して、プログラムの順序を観察した。
ちなみにOpenCVでのフーリエ変換はFFTでなくDFTである。
方法
- VisualStudioにNuGetでOpenCVSHarp4とOpenCVSHarp4.runtime.winをインストール
- 下記のプログラムを実行
using System;
using OpenCvSharp;
namespace フーリエ画像 {
class Program {
static void Main(string[] args) {
Mat src = new Mat(@"D:\src.png");
Cv2.CvtColor(src, src, ColorConversionCodes.RGB2GRAY);
Cv2.ImShow("①src", src);
Mat padded = new Mat();
int optimalRows = Cv2.GetOptimalDFTSize(src.Rows);
int optimalCols = Cv2.GetOptimalDFTSize(src.Cols);
Cv2.CopyMakeBorder(src, padded,
0, optimalRows - src.Rows,
0, optimalCols - src.Cols,
BorderTypes.Constant, Scalar.All(0));
Cv2.ImShow("②padded", padded);
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);
Mat dft = new Mat();
Cv2.Dft(complex, dft);
Mat[] dftPlanes = Cv2.Split(dft);
double minVal, maxVal;
Mat dft0 = new Mat(), dft1 = new Mat();
Cv2.Normalize(dftPlanes[0], dft0, 0, 255, NormTypes.MinMax);
Cv2.Normalize(dftPlanes[1], dft1, 0, 255, NormTypes.MinMax);
dft0.ConvertTo(dft0, MatType.CV_8UC1);
dft1.ConvertTo(dft1, MatType.CV_8UC1);
Cv2.MinMaxLoc(dft0, out minVal, out maxVal);
Console.WriteLine(maxVal);
Cv2.ImShow("④-1", dft0);
Cv2.ImShow("④-2", dft1);
Mat magnitude = new Mat();
Cv2.Magnitude(dftPlanes[0], dftPlanes[1], magnitude);
Mat magntuideImg = new Mat();
Cv2.Normalize(magnitude, magntuideImg, 0, 255, NormTypes.MinMax);
Cv2.ImShow("⑤", magntuideImg);
magnitude += Scalar.All(1);
Cv2.Log(magnitude, magnitude);
Cv2.MinMaxLoc(magnitude, out minVal, out maxVal);
Mat magnitudeLogImg = magnitude / maxVal * 255;
magnitudeLogImg.ConvertTo(magnitudeLogImg, MatType.CV_8UC1);
Cv2.MinMaxLoc(magnitudeLogImg, out minVal, out maxVal);
Cv2.ImShow("⑥", magnitudeLogImg);
Mat spectrum = magnitude[new Rect(0, 0, magnitude.Cols & -2, magnitude.Rows & -2)];
int cx = spectrum.Cols / 2;
int cy = spectrum.Rows / 2;
Mat q0 = new Mat(spectrum, new Rect( 0, 0, cx, cy));
Mat q1 = new Mat(spectrum, new Rect(cx, 0, cx, cy));
Mat q2 = new Mat(spectrum, new Rect( 0, cy, cx, cy));
Mat q3 = new Mat(spectrum, new Rect(cx, cy, cx, cy));
Mat tmp = new Mat();
q0.CopyTo(tmp);
q3.CopyTo(q0);
tmp.CopyTo(q3);
q1.CopyTo(tmp);
q2.CopyTo(q1);
tmp.CopyTo(q2);
Cv2.Normalize(spectrum, spectrum, 0, 255, NormTypes.MinMax);
spectrum.ConvertTo(spectrum, MatType.CV_8U);
Cv2.ImShow("⑧", spectrum);
Mat inverseTransform = new Mat();
Cv2.Dft(dft, inverseTransform, DftFlags.Inverse | DftFlags.RealOutput);
Cv2.Normalize(inverseTransform, inverseTransform, 0, 255, NormTypes.MinMax);
inverseTransform.ConvertTo(inverseTransform, MatType.CV_8U);
Cv2.ImShow("Reconstructed by Inverse DFT", inverseTransform);
Cv2.WaitKey();
}
}
}