OpenCVSharp4で内外判定

内外判定とは

点が「領域の内側にあるか外側にあるか」判定すること

Cv2.PointPolygoonTest()を使うと判定できる。オプションで領域との距離を測定することもできる。

プログラム

OpenCVSharp4の導入はコチラ

using System;  
using OpenCvSharp;  

namespace pointPolygonTest {  
    class Program {  
        static void Main(string[] args) {  
            //4r*4rの正方形を作成  
            const int r = 100;  
            Mat mat = new Mat(new Size(r * 4, r * 4), MatType.CV_8UC1, Scalar.All(0));  


            //六角形を作図  
            Point[] hexagon = new Point[6];  
            for(int i = 0; i < 6; i++) {  
                hexagon[i] = new Point(  
                    r * Math.Cos(2 * Math.PI / 6 * i) + 2 * r,  
                    r * Math.Sin(2 * Math.PI / 6 * i) + 2 * r  
                    );  
            }  
            for(int i=0; i < 6; i++) {  
                mat.Line(hexagon[i], hexagon[(i + 1) % 6], Scalar.White);  

            }  


            //輪郭検出  
            Mat edge = new Mat();  
            Point[][] contours;  
            HierarchyIndex[] hierarchyIndices;  
            Cv2.FindContours(mat, out contours, out hierarchyIndices, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple);  


            //輪郭との距離を測定  
            Mat rawDist = new Mat(mat.Size(), MatType.CV_64FC1);  
            for(int i=0;i<mat.Rows; i++) {  
                for(int j = 0; j < mat.Cols; j++) {  
                    var dist = Cv2.PointPolygonTest(contours[0], new Point2f(j, i), true);  
                    rawDist.Set<double>(i, j, dist);  
                }  
            }  



            //描画  
            Mat draw = new Mat(rawDist.Size(), MatType.CV_8UC3, Scalar.All(0));  
            double min, max;  
            Cv2.MinMaxLoc(rawDist, out min, out max);  

            rawDist *= 255 / Math.Max(max, -min);//正規化  
            for(int i = 0; i < mat.Rows; i++) {  
                for(int j = 0; j < mat.Cols; j++) {  

                    var dist = Cv2.PointPolygonTest(contours[0], new Point2f(j, i), true);  

                    Vec3b px;  
                    if(dist > 0) { px = new Vec3b(0, (byte)dist, 0); }  
                    else {         px = new Vec3b(0, 0, (byte)(-dist)); }  


                    draw.Set<Vec3b>(i, j, px);  
                }  
            }  

            Cv2.ImShow("mat", mat);  
            Cv2.ImShow("draw", draw);  
            Cv2.WaitKey();  

        }  
    }  
}  

結果

f:id:negizoku:20200920232832p:plain



f:id:negizoku:20200920232846p:plain



パプリカの断面のようである。

参考

https://docs.opencv.org/4.0.0/dc/d48/tutorial_point_polygon_test.html