OpenCVSharp4で位相画像の作成

位相画像とは

位相限定相関法(Phase Only Correlation)などで使用される画像。フーリエ変換した画像の位相だけを取り出した画像のこと。

F[Xij]=GuvとするとPhaseImage(Xij)=F1[Guv|Guv|]定義より画像の明るさを何倍しても位相画像は変わらない。

方法

  1. 画像を読み込む
  2. 画像のサイズ調整
  3. 画像を複素平面に移す
  4. フーリエ変換(DFT)を行う
  5. 各画素の大きさ(実部と虚部の2乗平均)を取得
  6. 各画素を正規化(大きさで除算する)
  7. フーリエ変換を行う

※事前に
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));  

            //③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);  
            Mat magnitude = new Mat();  
            Cv2.Magnitude(dftPlanes[0], dftPlanes[1], magnitude);  


            //⑥大きさで各要素を割って正規化  
            Mat phase = new Mat();  
            Cv2.Divide(dftPlanes[0], magnitude, dftPlanes[0]);  
            Cv2.Divide(dftPlanes[1], magnitude, dftPlanes[1]);  
            Cv2.Merge(dftPlanes, phase);  


            //⑦逆フーリエ   
            Mat inverseTransform = new Mat();  
            Cv2.Dft(phase, inverseTransform, DftFlags.Inverse | DftFlags.RealOutput);  


            //⑧逆フーリエ変換した結果を8bitに正規化して表示  
            Cv2.Normalize(inverseTransform, inverseTransform, 0, 255, NormTypes.MinMax);  
            inverseTransform.ConvertTo(inverseTransform, MatType.CV_8U);  

            Cv2.ImShow("Reconstructed by Inverse DFT", inverseTransform);  


            Cv2.WaitKey();  


        }  
    }  
}  

結果

入力画像

f:id:negizoku:20200920230803p:plain



出力画像

f:id:negizoku:20200920230820p:plain



参考

https://rest-term.com/archives/1375/
https://www.jstage.jst.go.jp/article/itej1997/54/10/54_10_1408/_pdf
http://www.aoki.ecei.tohoku.ac.jp/~ito/vol1_030.pdf