Пример #1
0
        private List <Rect> ConditionNMS(Mat binaryImg)
        {
            var rectList = new List <Rect>();
            var indexer  = binaryImg.GetGenericIndexer <Vec3b>();

            var contours        = new OpenCvSharp.Point[][] { };
            var hierarchy       = new OpenCvSharp.HierarchyIndex[] { };
            var contourAreaList = new List <double>()
            {
            };
            var contourCenterList = new List <System.Drawing.Point>()
            {
            };

            Cv2.FindContours(binaryImg, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxNone);
            for (int i = 0; i < hierarchy.Length; i++)
            {
                //contourAreaList.Add(Cv2.ContourArea(contours[i]));
                //精炼出的输入为binary、一个加号还是箭头的flag,返回的是有效的rect类型的List,加号需要 rect的中心点;箭头需要rect的两边坐标以及方向
                //var S = Cv2.ContourArea(contours[i]);
                var M = Cv2.Moments(contours[i]);
                if (M.M00 != 0)
                {
                    var cx = (int)(M.M10 / M.M00);
                    var cy = (int)(M.M01 / M.M00);
                    if (indexer[cy, cx].Item0 == 255)             //相同条件1:反向二值图的轮廓中心为0
                                                                  //相同条件2:四角为0
                    {
                        var rect = Cv2.BoundingRect(contours[i]); //相同条件3:截出来的框轮廓数量为4

                        try
                        {
                            if (indexer[rect.Y, rect.X].Item0 == 0 && indexer[rect.Y + rect.Height, rect.X + rect.Width].Item0 == 0 &&
                                indexer[rect.Y + rect.Height, rect.X].Item0 == 0 && indexer[rect.Y, rect.X + rect.Width].Item0 == 0)
                            {
                                //Rect r = new Rect(new OpenCvSharp.Point(rect.X, rect.Y), new OpenCvSharp.Size(rect.Width, rect.Height));
                                //Cv2.Rectangle(binaryImg, r, Scalar.LimeGreen, 1);
                                //Cv2.DrawContours(srcImg, contours, i, Scalar.Gray, 2, LineTypes.Link8, hierarchy, 4);
                                var tempROI = new Mat();
                                binaryImg[rect].CopyTo(tempROI);//截出连通域

                                if (Math.Max(rect.Width, rect.Height) / Math.Min(rect.Width, rect.Height) < 1.2 && rect.Width < 200 &&
                                    PlusCondition(tempROI))     //plus
                                {
                                    rectList.Add(rect);
                                }
                            }
                        }
                        catch (Exception er)
                        {
                            //do nothing.
                        }
                    }
                }
            }
            return(rectList);
        }
Пример #2
0
        private bool PlusCondition(Mat tempROI)
        {
            bool flag = false;

            Cv2.Threshold(tempROI, tempROI, 200, 255, ThresholdTypes.BinaryInv); //反向二值化

            var tempContours  = new OpenCvSharp.Point[][] { };
            var tempHierarchy = new OpenCvSharp.HierarchyIndex[] { };

            Cv2.FindContours(tempROI, out tempContours, out tempHierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone);

            //对于每一个tempROI,对于箭头 或者 判断是否符合条件
            if (tempContours.GetLength(0) == 4)
            {
                var    pointListX = new List <double>();//4个轮廓中心点
                var    pointListY = new List <double>();
                var    euDisList = new List <double>();
                double sumX = 0, sumY = 0;

                for (int i = 0; i < 4; i++)
                {
                    var M = Cv2.Moments(tempContours[i]);
                    if (M.M00 != 0)
                    {
                        var cx = (M.M10 / M.M00);
                        var cy = (M.M01 / M.M00);
                        pointListX.Add(cx);
                        pointListY.Add(cy);
                        sumX += cx;
                        sumY += cy;
                    }
                    else
                    {
                        return(false);
                    }
                }
                var centerPointX = sumX / 4;
                var centerPointY = sumY / 4;
                for (int i = 0; i < 4; i++)
                {
                    euDisList.Add(Math.Pow(Math.Pow(Math.Abs(centerPointX - pointListX[i]), 2) + Math.Pow(Math.Abs(centerPointY - pointListY[i]), 2), 0.5));
                }
                var stdDev = CalculateStdDev(euDisList);

                if (stdDev < 0.12)
                {
                    flag = true;
                    // Console.WriteLine(stdDev);
                }
            }
            return(flag);
        }
Пример #3
0
        /// <summary>
        /// 2値画像中の輪郭を検出します.
        /// </summary>
        /// <param name="image">入力画像,8ビット,シングルチャンネル.0以外のピクセルは 1として,0のピクセルは0のまま扱われます.
        /// また,この関数は,輪郭抽出処理中に入力画像 image の中身を書き換えます.</param>
        /// <param name="contours">検出された輪郭.各輪郭は,点のベクトルとして格納されます.</param>
        /// <param name="hierarchy">画像のトポロジーに関する情報を含む出力ベクトル.これは,輪郭数と同じ数の要素を持ちます.各輪郭 contours[i] に対して,
        /// 要素 hierarchy[i]のメンバにはそれぞれ,同じ階層レベルに存在する前後の輪郭,最初の子輪郭,および親輪郭の 
        /// contours インデックス(0 基準)がセットされます.また,輪郭 i において,前後,親,子の輪郭が存在しない場合,
        /// それに対応する hierarchy[i] の要素は,負の値になります.</param>
        /// <param name="mode">輪郭抽出モード</param>
        /// <param name="method">輪郭の近似手法</param>
        /// <param name="offset">オプションのオフセット.各輪郭点はこの値の分だけシフトします.これは,ROIの中で抽出された輪郭を,画像全体に対して位置づけて解析する場合に役立ちます.</param>
#else
        /// <summary>
        /// Finds contours in a binary image.
        /// </summary>
        /// <param name="image">Source, an 8-bit single-channel image. Non-zero pixels are treated as 1’s. 
        /// Zero pixels remain 0’s, so the image is treated as binary.
        /// The function modifies the image while extracting the contours.</param> 
        /// <param name="contours">Detected contours. Each contour is stored as a vector of points.</param>
        /// <param name="hierarchy">Optional output vector, containing information about the image topology. 
        /// It has as many elements as the number of contours. For each i-th contour contours[i], 
        /// the members of the elements hierarchy[i] are set to 0-based indices in contours of the next 
        /// and previous contours at the same hierarchical level, the first child contour and the parent contour, respectively. 
        /// If for the contour i there are no next, previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative.</param>
        /// <param name="mode">Contour retrieval mode</param>
        /// <param name="method">Contour approximation method</param>
        /// <param name="offset"> Optional offset by which every contour point is shifted. 
        /// This is useful if the contours are extracted from the image ROI and then they should be analyzed in the whole image context.</param>
#endif
        public static void FindContours(InputOutputArray image, out Point[][] contours,
            out HierarchyIndex[] hierarchy, RetrievalModes mode, ContourApproximationModes method, Point? offset = null)
        {
            if (image == null)
                throw new ArgumentNullException(nameof(image));
            image.ThrowIfNotReady();

            Point offset0 = offset.GetValueOrDefault(new Point());
            IntPtr contoursPtr, hierarchyPtr;
            NativeMethods.imgproc_findContours1_vector(image.CvPtr, out contoursPtr, out hierarchyPtr, (int)mode, (int)method, offset0);

            using (var contoursVec = new VectorOfVectorPoint(contoursPtr))
            using (var hierarchyVec = new VectorOfVec4i(hierarchyPtr))
            {
                contours = contoursVec.ToArray();
                Vec4i[] hierarchyOrg = hierarchyVec.ToArray();
                hierarchy = EnumerableEx.SelectToArray(hierarchyOrg, HierarchyIndex.FromVec4i);
            }
            image.Fix();
        }
Пример #4
0
    /// <summary>
    /// 2値画像中の輪郭を検出します.
    /// 入力画像は,8ビット,シングルチャンネル.0以外のピクセルは 1として,0のピクセルは0のまま扱われます.
    /// また,この関数は,輪郭抽出処理中に入力画像の中身を書き換えます.
    /// </summary>
    /// <param name="contours">検出された輪郭.各輪郭は,点のベクトルとして格納されます.</param>
    /// <param name="hierarchy">画像のトポロジーに関する情報を含む出力ベクトル.これは,輪郭数と同じ数の要素を持ちます.各輪郭 contours[i] に対して,
    /// 要素 hierarchy[i]のメンバにはそれぞれ,同じ階層レベルに存在する前後の輪郭,最初の子輪郭,および親輪郭の 
    /// contours インデックス(0 基準)がセットされます.また,輪郭 i において,前後,親,子の輪郭が存在しない場合,
    /// それに対応する hierarchy[i] の要素は,負の値になります.</param>
    /// <param name="mode">輪郭抽出モード</param>
    /// <param name="method">輪郭の近似手法</param>
    /// <param name="offset">オプションのオフセット.各輪郭点はこの値の分だけシフトします.これは,ROIの中で抽出された輪郭を,画像全体に対して位置づけて解析する場合に役立ちます.</param>
#else
        /// <summary>
        /// Finds contours in a binary image.
        /// The source is an 8-bit single-channel image. Non-zero pixels are treated as 1’s. 
        /// Zero pixels remain 0’s, so the image is treated as binary. The function modifies this image while extracting the contours.
        /// </summary>
        /// <param name="contours">Detected contours. Each contour is stored as a vector of points.</param>
        /// <param name="hierarchy">Optional output vector, containing information about the image topology. 
        /// It has as many elements as the number of contours. For each i-th contour contours[i], 
        /// the members of the elements hierarchy[i] are set to 0-based indices in contours of the next 
        /// and previous contours at the same hierarchical level, the first child contour and the parent contour, respectively. 
        /// If for the contour i there are no next, previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative.</param>
        /// <param name="mode">Contour retrieval mode</param>
        /// <param name="method">Contour approximation method</param>
        /// <param name="offset"> Optional offset by which every contour point is shifted. 
        /// This is useful if the contours are extracted from the image ROI and then they should be analyzed in the whole image context.</param>
#endif
        public void FindContours(out Point[][] contours, out HierarchyIndex[] hierarchy,
            RetrievalModes mode, ContourApproximationModes method, Point? offset = null)
        {
            Cv2.FindContours(this, out contours, out hierarchy, mode, method, offset);
        }
Пример #5
0
        private List <Rect> ConditionNMS(Mat binaryImg, ref List <int> orientationList)
        {
            var rectList = new List <Rect>();
            var indexer  = binaryImg.GetGenericIndexer <Vec3b>();

            var contours        = new OpenCvSharp.Point[][] { };
            var hierarchy       = new OpenCvSharp.HierarchyIndex[] { };
            var contourAreaList = new List <double>()
            {
            };
            var contourCenterList = new List <System.Drawing.Point>()
            {
            };

            Cv2.FindContours(binaryImg, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxNone);
            for (int i = 0; i < hierarchy.Length; i++)
            {
                var M = Cv2.Moments(contours[i]);
                if (M.M00 != 0)
                {
                    var cx = (int)(M.M10 / M.M00);
                    var cy = (int)(M.M01 / M.M00);
                    if (indexer[cy, cx].Item0 == 255)
                    {
                        var rect = Cv2.BoundingRect(contours[i]);

                        if (indexer[rect.Y, rect.X].Item0 == 0 && indexer[rect.Y + rect.Height, rect.X + rect.Width].Item0 == 0 &&
                            indexer[rect.Y + rect.Height, rect.X].Item0 == 0 && indexer[rect.Y, rect.X + rect.Width].Item0 == 0 &&
                            rect.Width / rect.Height > 4 && rect.Width > 40)
                        {
                            //Rect r = new Rect(new OpenCvSharp.Point(rect.X, rect.Y), new OpenCvSharp.Size(rect.Width, rect.Height));
                            //Cv2.Rectangle(binaryImg, r, Scalar.LimeGreen, 1);
                            //Cv2.DrawContours(srcImg, contours, i, Scalar.Gray, 2, LineTypes.Link8, hierarchy, 4);
                            var point1 = new OpenCvSharp.Point(cx, cy);

                            Cv2.FloodFill(binaryImg, point1, new Scalar(155, 155, 155));

                            var tempROI = new Mat();
                            binaryImg[rect].CopyTo(tempROI);//截出连通域, 按中心点做漫水填充
                            int orientation = 0;
                            ///////////////
                            Vec3b color = new Vec3b(0, 0, 0);
                            int   sLeft = 0, sRight = 0;
                            var   ROIIndexer = tempROI.GetGenericIndexer <Vec3b>();
                            for (int k = 0; k < tempROI.Rows; k++)
                            {
                                for (int j = 0; j < tempROI.Cols; j++)
                                {
                                    if (ROIIndexer[k, j].Item0 == 255)
                                    {
                                        ROIIndexer[k, j] = color;
                                        continue;
                                    }
                                    else if (ROIIndexer[k, j].Item0 == 155)
                                    {
                                        if (j < tempROI.Cols / 2)
                                        {
                                            sLeft++;
                                        }
                                        else
                                        {
                                            sRight++;
                                        }
                                    }
                                }
                            }
                            Cv2.Threshold(tempROI, tempROI, 154, 255, ThresholdTypes.BinaryInv);

                            if (sLeft < sRight)
                            {
                                orientation = 1; //正向箭头
                            }
                            //////////////////
                            var tempContours  = new OpenCvSharp.Point[][] { };
                            var tempHierarchy = new OpenCvSharp.HierarchyIndex[] { };
                            Cv2.FindContours(tempROI, out tempContours, out tempHierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone);
                            if (tempContours.GetLength(0) == 4 && Math.Abs(sLeft - sRight) > 10)
                            {
                                rectList.Add(rect);
                                orientationList.Add(orientation);
                            }
                        }
                    }
                }
            }
            return(rectList);
        }