国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位

這篇具有很好參考價值的文章主要介紹了OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

以下原圖中,物體連靠在一起,目的是將其分割開,再提取輪廓和定位

原圖:?OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位

?最終效果:

OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位

麻煩的地方是,分割開右下角部分,兩個連在一起的目標(biāo)物體,下圖所示:?OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位

基本方法:BoxFilter濾波、二值化、輪廓提取,凸包檢測,圖像的矩

代碼如下:

        /// <summary>
        /// 獲取分割點(diǎn)
        /// </summary>
        /// <param name="contours"></param>
        /// <param name="contourCount"></param>
        /// <param name="arcLength"></param>
        /// <param name="farDistance"></param>
        /// <returns></returns>
        public List<Point> GetSplitPoints(Point[][] contours, List<int> contourCount, int arcLength, int farDistance)
        {
            #region 凸包檢測
            List<double> lArc = new List<double>();
            //Mat src = srcImage.Clone();
            List<Point[]> lpContours = new List<Point[]>();
            List<int> hulls = new List<int>();
            Point lastP = new Point();
            Point firstP = new Point();
            Point farLastP = new Point();
            List<Point> lps = new List<Point>();
            int dot = 1;
            List<int> depth = new List<int>();
            for (int i = 0; i < contourCount.Count; i++)
            {
                InputArray inputArray = InputArray.Create<Point>(contours[contourCount[i]]);
                OutputArray outputArray = OutputArray.Create(hulls);
                Cv2.ConvexHull(inputArray, outputArray, false, false);
                if (Cv2.ArcLength(inputArray, true) < arcLength)
                {
                    //lArc.Add(Cv2.ArcLength(inputArray, true));
                    continue;
                }
                //前三個值得含義分別為:凸缺陷的起始點(diǎn),凸缺陷的終點(diǎn),凸缺陷的最深點(diǎn)(即邊緣點(diǎn)到凸包距離最大點(diǎn))。
                var defects = Cv2.ConvexityDefects(contours[contourCount[i]], hulls);
                for (int j = 0; j < defects.Length; j++)
                {
                    OpenCvSharp.Point start = contours[contourCount[i]][defects[j].Item0];
                    OpenCvSharp.Point end = contours[contourCount[i]][defects[j].Item1];
                    OpenCvSharp.Point far = contours[contourCount[i]][defects[j].Item2];
                    //OpenCvSharp.Point fart = contours[contourCount[i]][defects[j].Item3];
                    if (defects[j].Item3 > farDistance) //(4500 < defects[j].Item3 && defects[j].Item3 < 300000)
                    {
                        lps.Add(contours[contourCount[i]][defects[j].Item2]);
                        depth.Add(defects[j].Item3);
                    }
                }
            }
            #endregion
            return lps;
        }

        /// <summary>
        /// 獲取最小內(nèi)接矩形
        /// </summary>
        /// <param name="contours"></param>
        /// <param name="contourCount"></param>
        /// <returns></returns>
        public List<RotatedRect> GetMinRects(Point[][] contours, List<int> contourCount)
        {
            //Cv2.ImShow(",mmmm", morphImage);

            //double rotateAngel = 0;
            Point2f[] vertices = new Point2f[4];
            //Point2f minRectcenterPoint = new Point2f();
            List<RotatedRect> minRects = new List<RotatedRect>();
            for (int i = 0; i < contourCount.Count; i++)
            {
                //獲取輪廓點(diǎn)的矩形區(qū)域
                //繪制Rio區(qū)域最小矩形
                #region 繪制Rio區(qū)域最小矩形
                RotatedRect minRect = Cv2.MinAreaRect(contours[contourCount[i]]);
                minRects.Add(minRect);
                #endregion
            }
            return minRects;
        }
        /// <summary>
        /// 返回設(shè)置范圍內(nèi)的輪廓
        /// </summary>
        /// <param name="mat"></param>
        /// <param name="range1"></param>
        /// <param name="range2"></param>
        /// <param name="contourCount"></param>
        /// <returns></returns>
        public Point[][] GetImageContours(Mat mat, int length, out List<int> contourCount)
        {
            List<double> arclength = new List<double>();
            OpenCvSharp.Point[][] contours;
            HierarchyIndex[] hierarchies;
            //Cv2.ImShow(",mmmm", mat);
            Cv2.FindContours(mat, out contours, out hierarchies, RetrievalModes.External, ContourApproximationModes.ApproxSimple, new Point());
            Mat connImg = Mat.Zeros(mat.Size(), MatType.CV_8UC3);
            Point2f[] vertices = new Point2f[4];
            Mat drawOutline = Mat.Zeros(mat.Size(), mat.Type());
            int sum = 0;
            contourCount = new List<int>();
            for (int i = 0; i < contours.Length; i++)
            {
                Rect rect1 = Cv2.BoundingRect(contours[i]);
                if (Cv2.ArcLength(contours[i], true) > length)//(rect1.Width > range1 && rect1.Height < range2)
                {
                    Cv2.DrawContours(drawOutline, contours, i, new Scalar(255, 0, 255), 2, LineTypes.Link8, hierarchies);
                    contourCount.Add(i);
                    arclength.Add(Cv2.ArcLength(contours[i], true));
                    sum++;
                }
            }
            Cv2.ImShow("contours", drawOutline);
            return contours;
        }



        /// <summary>
        /// 圖像灰度
        /// 盒子濾波 保留邊緣信息
        /// 自適應(yīng)閾值 效果不錯 無需形態(tài)學(xué)降噪
        /// 取反操作 
        /// 過濾不需要輪廓信息(面積 邊長)
        /// 輪廓提取 
        /// (以上每一步都很重要,否則,無法獲取良好的輪廓)
        /// 凸包檢測
        /// 根據(jù)輪廓信息,查找大凸包,獲取分割點(diǎn)
        /// 重新操作圖像
        /// 在二值化圖像時,分割連接點(diǎn)位置
        /// 繪制輪廓
        /// 繪制最小內(nèi)接矩形和質(zhì)心點(diǎn)
        /// 識別目標(biāo)位置完成
        /// 注意:不同大小的圖像處理時,需要修改自適應(yīng)閾值參數(shù)、輪廓過濾面積、凸包檢測的分割點(diǎn)過濾
        /// </summary>
        /// <param name="srcImage"></param>
        /// <returns></returns>
        public Mat PreProcess(Mat srcImage)
        {
            Mat grayMat = new Mat();
            Cv2.CvtColor(srcImage, grayMat, ColorConversionCodes.BGRA2GRAY);
            //Cv2.ImShow("grayMat", grayMat);

            Mat blurImg = BoxFilter(grayMat);
            //Cv2.ImShow("blurImg", blurImg);

            // 注意:不同大小的圖像處理時,需要修改參數(shù)
            Mat threshold = new Mat();
            Cv2.AdaptiveThreshold(blurImg, threshold, 255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 15, 2);
            //Cv2.Threshold(threshold, threshold, 0, 255, ThresholdTypes.BinaryInv);
            Cv2.ImShow("threshold", threshold);


            //Mat morphImg = MorphImage(threshold, MorphShapes.Ellipse, MorphTypes.Dilate, 1, new OpenCvSharp.Size(3, 3));
            //Cv2.ImShow("morphImg", morphImg);

            //Mat cannyImg = new Mat();
            //Cv2.Laplacian(morphImg2, cannyImg, MatType.CV_8UC3, 5, 1);//Cv2.Canny(morphImg, cannyImg, 30, 90);//3和4參數(shù)的 最佳比例在1/3和1/2之間
            //Cv2.ImShow("cannyImg", cannyImg);

            Mat bitwiseMat = new Mat();
            Cv2.BitwiseNot(threshold, bitwiseMat);
            Cv2.ImShow("bitwiseMat", bitwiseMat);

            List<int> contourCount;
            //輪廓提取
            Point[][] contours = GetImageContours(bitwiseMat, 600, out contourCount);
            //凸包檢測
            List<Point> lps = GetSplitPoints(contours, contourCount, 800, 4500);


            // 注意:不同大小的圖像處理時,需要修改參數(shù)
            //重新處理
            Cv2.AdaptiveThreshold(blurImg, threshold, 255.0, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 13, 2);
            Cv2.ImShow("threshold1", threshold);

            //MorphImage(threshold, MorphShapes.Ellipse, MorphTypes.Close, 1, new OpenCvSharp.Size(3, 3));
            //Cv2.ImShow("morphImg1", morphImg);

            Cv2.BitwiseNot(threshold, bitwiseMat);
            Cv2.ImShow("bitwiseMat1", bitwiseMat);
            //提取凸顯點(diǎn)坐標(biāo)

            if (lps.Count > 1)
            {
                Cv2.Line(bitwiseMat, lps[0], lps[1], Scalar.Black, 2, LineTypes.Link8);
            }
            Cv2.ImShow("bitwiseMat2", bitwiseMat);
            //輪廓提取   
            contourCount.Clear();    // 注意:不同大小的圖像處理時,需要修改length參數(shù)
            Point[][] newContours = GetImageContours(bitwiseMat, 550, out contourCount);
            List<RotatedRect> rotatedRects = GetMinRects(newContours, contourCount);

            for (int i = 0; i < rotatedRects.Count; i++)
            {
                #region 繪制Rio區(qū)域最小矩形
                Point2f[] vertices = rotatedRects[i].Points();
                #endregion
                //繪制最小矩形
                #region 繪制最小矩形
                Cv2.Line(srcImage, Convert.ToInt32(vertices[0].X), Convert.ToInt32(vertices[0].Y), Convert.ToInt32(vertices[1].X), Convert.ToInt32(vertices[1].Y), new Scalar(0, 0, 255), 2);
                Cv2.Line(srcImage, Convert.ToInt32(vertices[0].X), Convert.ToInt32(vertices[0].Y), Convert.ToInt32(vertices[3].X), Convert.ToInt32(vertices[3].Y), new Scalar(0, 0, 255), 2);
                Cv2.Line(srcImage, Convert.ToInt32(vertices[1].X), Convert.ToInt32(vertices[1].Y), Convert.ToInt32(vertices[2].X), Convert.ToInt32(vertices[2].Y), new Scalar(0, 0, 255), 2);
                Cv2.Line(srcImage, Convert.ToInt32(vertices[2].X), Convert.ToInt32(vertices[2].Y), Convert.ToInt32(vertices[3].X), Convert.ToInt32(vertices[3].Y), new Scalar(0, 0, 255), 2);
                //獲取重心點(diǎn)
                Moments M;
                M = Cv2.Moments(vertices);
                double cX = M.M10 / M.M00;
                double cY = M.M01 / M.M00;
                //顯示目標(biāo)中心并提取坐標(biāo)點(diǎn)
                Cv2.Circle(srcImage, (int)cX, (int)cY, 2, Scalar.Yellow, 2);
                //Console.WriteLine("AngleRect_angle: {0}", minRect.Angle);
                #endregion
            }
            Cv2.ImShow("srcImage", srcImage);
            return null;
        }

灰度圖像后圖像二值化:

OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位

圖像取反

?OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位

?繪制輪廓

OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位

?凸包檢測,查找分割點(diǎn),下圖黃色點(diǎn)標(biāo)記處即找到的分割點(diǎn)位置

OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位

?將找到的分割點(diǎn)在二值化圖像中,連接一條線后,重新輪廓識別即可分割

OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位

最小輪廓矩形提取和繪制,以及繪制質(zhì)心位置

OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位?到此,已將連接處分隔開

注意:使用以上方法是需要根據(jù)圖像大小設(shè)置部分參數(shù),例如二值化處理參數(shù)、過濾輪廓形狀大小,凸包檢測點(diǎn)的獲取等位置,需要根據(jù)實(shí)際情況設(shè)置參數(shù);文章來源地址http://www.zghlxwxcb.cn/news/detail-503191.html

到了這里,關(guān)于OpenCv案例(九): 基于OpenCvSharp圖像分割提取目標(biāo)區(qū)域和定位的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包