OpenCVSharp4でフーリエ画像の作成

サンプルプログラムをほとんどそのまま流用して、プログラムの順序を観察した。
ちなみにOpenCVでのフーリエ変換FFTでなくDFTである。

方法

  1. VisualStudioにNuGetでOpenCVSHarp4とOpenCVSHarp4.runtime.winをインストール
  2. 下記のプログラムを実行
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);  

            //③0で拡張された別の平面に移す  
            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);  


            //④dftを入力画像とフィットさせDFT(フーリエ変換)  
            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);  



            //Cv2.MinMaxLoc(magnitude, out minVal, out maxVal);  
            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)];  


            //⑧原点が画像の中心になるように4象限を入れ替え  
            int cx = spectrum.Cols / 2;//各象限の行数と列数を計算  
            int cy = spectrum.Rows / 2;  

            Mat q0 = new Mat(spectrum, new Rect( 0,  0, cx, cy));//各象限に対応するMatを作成  
            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);//第1象限と第3象限の入れ替え  
            q3.CopyTo(q0);  
            tmp.CopyTo(q3);  

            q1.CopyTo(tmp);//第2象限と第3象限の入れ替え  
            q2.CopyTo(q1);  
            tmp.CopyTo(q2);  


            Cv2.Normalize(spectrum, spectrum, 0, 255, NormTypes.MinMax);//0~255に正規化  
            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();  


        }  
    }  
}