OpenCVSharp4で射影変換

射影変換とは

画像平面を任意の3D視点から見直すこと

方法

  1. 画像の読み込み
  2. 入力画像の4点を指定
  3. 出力画像の4点を指定
  4. 指定した点を対応させる射影変換のパラメータを求める
  5. 射影変換を行う

射影変換の数式は以下の通り。全部で9個のパラメータがあるが、8自由度である。(分母と分子をc3で割ればよい)

(x,y)(a1x+b1y+c1a3x+b3y+c3a2x+b2y+c2a3x+b3y+c3)

対応させる4点が長方形の頂点である場合、長方形のアスペクト比(縦横比)を把握していないと正しく変換することができない。
また、今回対応させる4点の座標は、ペイントで求めた。

プログラム

using System;  
using OpenCvSharp;  

namespace 射影変換 {  
    class Program {  
        static void Main(string[] args) {  
            //①画像の読み込み  
            Mat src = new Mat(@"D:\kanban.jpg");  


            //②入力画像の4点を指定  
            float[,] srcSumi = new float[4,2];  
            srcSumi =new float[,] {  
                { 241,  89},  
                { 339, 108},  
                { 349, 334},  
                { 231, 340}  
                };  
            Mat srcPts = new Mat(4, 2, MatType.CV_32FC1, srcSumi);  


            //③出力画像の4点を指定  
            float[,] dstSumi = new float[4, 2];  
            dstSumi = new float[,] {  
                {   0,   0},  
                { 100,   0},  
                { 100, 200},  
                {   0, 200}  
                };  
            Mat dstPts = new Mat(4, 2, MatType.CV_32FC1, dstSumi);  

            //④指定した4点を対応させる射影変換のパラメータを求める  
            Mat parameters = Cv2.GetPerspectiveTransform(srcPts, dstPts);  


            //⑤射影変換を行う  
            Mat dst = new Mat();  
            Cv2.WarpPerspective(src, dst, parameters, src.Size());  


            //⑥画像の表示  
            Cv2.ImShow("射影変換", dst);  
            Cv2.WaitKey();  

        }  
    }  
}  

結果

入力画像

f:id:negizoku:20200920230950j:plain



出力画像

f:id:negizoku:20200920231007j:plain



有名なグリコの看板の四隅を正面向きにした。看板と同一平面上にない物は歪んでしまう。

参考

https://docs.opencv.org/4.0.0/d2/de8/group__core__array.html#gad327659ac03e5fd6894b90025e6900a7
https://fermiumbay13.hatenablog.com/entry/2018/08/14/032643