OpenCVSharp4で画像に等高線を描く

ゲームをやっていたら等高線を書きたくなったので。。。

方法

  1. 画像の正規化
  2. 画像の階調を粗くする
  3. 階調を荒くした画像でエッジ検出
  4. 階調を荒くした画像にエッジを上描き
  5. 等高線画像の表示

プログラム

using System;  
using OpenCvSharp;  

namespace 等高線 {  
    class Program {  
        static void Main(string[] args) {  
            //ガウス関数を作成  
            float[,] wave = new float[500, 500];  
            for(int i = 0; i < 500; i++) {  
                for(int j =0; j < 500; j++) {  
                    double r = Math.Sqrt(i * i + 2 * j * j);  
                    wave[i, j] = (float)Math.Pow(Math.E, -r * r / 150000);  
                }  
            }  
            Mat src = new Mat(500, 500, MatType.CV_32FC1, wave);  

            //①0~255に正規化して、MatTypeをCV_8UC1に変更  
            Cv2.Normalize(src, src, 0, 255, NormTypes.MinMax);  
            src.ConvertTo(src, MatType.CV_8UC1);  
            Cv2.ImShow("src", src);  
            src.ImWrite(@"D:\src1.png");  

            //⑤画像の表示  
            Mat dst = drawContourLine(src, 20, Scalar.Brown, ColormapTypes.Pink);  

            Cv2.ImShow("dst", dst);  
            dst.ImWrite(@"D:\dst1.png");  
            Cv2.WaitKey();  
        }  


        static Mat drawContourLine(Mat src, int contourNum,Scalar contourColor, ColormapTypes? colormapTypes = ColormapTypes.Hot) {  
            //②等高線の数から、等高線の高さを計算  
            int step = 256 / contourNum;  

            //②階調変換用のヒストグラムを作成  
            byte[] lut = new byte[256];  
            for(int i = 0; i < lut.Length; i++) {  
                lut[i] = (byte)(Math.Floor((double)i / step) * step);  
            }  

            Console.WriteLine(Scalar.White);  

            //②階調を粗くする  
            Mat roughGrad = new Mat();  
            Cv2.LUT(src, lut, roughGrad);  

            //③階調を荒くした画像のエッジ検出  
            Mat contour = new Mat();  
            Cv2.Canny(roughGrad, contour, 1, step - 1);  

            //④カラーマップに変更  
            if(colormapTypes == null) {   
                return contour;  
            }  
            else {  
                Cv2.ApplyColorMap(roughGrad, roughGrad, (ColormapTypes)colormapTypes);  
                for(int j = 0; j < contour.Rows; j++) {  
                    for(int i = 0; i < contour.Cols; i++) {  

                    if(contour.At<char>(j, i) > 0) roughGrad.Set<Vec3b>(j, i, new Vec3b((byte)contourColor[0], (byte)contourColor[1], (byte)contourColor[2]));  
                    }  
                }   
            }  



            return roughGrad;  
        }  

    }  
}  

結果

入力画像

f:id:negizoku:20200920231910p:plain



出力画像

f:id:negizoku:20200920231922p:plain