OpenCV中文網站

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
熱搜: 安裝 配置
查看: 551|回復: 1
打印 上一主題 下一主題

双色球蓝球奇偶分布图: OpenCV Blob分析-基于FindContours聯通區域分析

[復制鏈接]
跳轉到指定樓層
1#
發表于 2019-5-23 19:42:08 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
本文是一個較完整的Blob分析思路解說,是用OpenCvSharp聯合c#編寫的。
思路如下:
1、對圖像進行二值化
2、設定ROI
3、腐蝕、膨脹(可?。?br /> 4、邊緣提?。ㄓ星質欠裥杼畛淇錐矗?br /> 5、進行篩選
本來是要提供圖片的,但發現上傳不方便就算了,可以去我文庫看完整版:file:///C:/Users/Administrator/Desktop/%E5%9B%BE%E7%89%871.png

部分源代碼解說:
InputImage來自輸入的要處理的圖片。
gray_min、gray_max二值化的上下閾值
1、對圖像進行二值化(根據二值化的上下閾值來判定二值化方式)
Mat binaryImage = new Mat(InputImage.Size(), MatType.CV_8UC1, Scalar.Black);
            if (gray_min != 0 && gray_max != 255)
            {
                binaryImage = InputImage.Threshold(gray_min, 255, ThresholdTypes.Binary);
                Mat binaryImage2 = InputImage.Threshold(gray_max, 255, ThresholdTypes.BinaryInv);
                Mat binaryImage3 = new Mat(InputImage.Size(), MatType.CV_8UC1, Scalar.Black);
                binaryImage.CopyTo(binaryImage3, binaryImage2);
                binaryImage = binaryImage3.Clone();
                binaryImage2.Dispose();
                binaryImage3.Dispose();
            }
            else
            {
                if (gray_min == 0) binaryImage = InputImage.Threshold(gray_max, 255, ThresholdTypes.BinaryInv);
                if (gray_max == 255) binaryImage = InputImage.Threshold(gray_min, 255, ThresholdTypes.Binary);
            }
            Mat binaryImage1 = new Mat(InputImage.Size(), MatType.CV_8UC1, Scalar.Black); 2、設定ROI(Mask就是ROI感興趣區域)
binaryImage.CopyTo(binaryImage1, Mask);
3、腐蝕、膨脹(可?。?br /> if (erosion_dilation == "腐蝕")
                {
                    Cv2.Erode(binaryImage1, binaryImage1, element);
                }
                else
                {
                    Cv2.Dilate(binaryImage1, binaryImage1, element);
                }
4、邊緣提?。ㄓ星質欠裥杼畛淇錐矗?br /> if (fill_up_flag == true)
            {
                Cv2.FindContours(binaryImage1, out contours, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            }
            else
            {
                Cv2.FindContours(binaryImage1, out contours, hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple);
            }
5、進行篩選
Mat uu = hierarchy.GetMat();

            // 篩選那些面積小的
            List<MyCenter> centers = new List<MyCenter>();
            List<RotatedRect> regions = new List<RotatedRect>();

            var detectorParams = new SimpleBlobDetector.Params
            {
                MinDistBetweenBlobs = 10, // 10 pixels between blobs
                MinRepeatability = 1,

                MinThreshold = 0,
                MaxThreshold = 128,
                ThresholdStep = 2,

                FilterByArea = area_bool,
                MinArea = area_min, // 10 pixels squared
                MaxArea = area_max,

                //圓度
                FilterByCircularity = circularity_bool,
                MinCircularity = circularity_min,
                MaxCircularity = circularity_max,

                // 凸包形狀分析 - 過濾凹包
                FilterByConvexity = false,
                //FilterByConvexity = true,
                MinConvexity = 0.001f,
                MaxConvexity = 10,

                FilterByInertia = false,
                //FilterByInertia = true,
                MinInertiaRatio = 0.001f,

                FilterByColor = false,
                //FilterByColor = true,
                BlobColor = 255 // to extract light blobs

            };

            MyCenter center;

            int j = 0;
            Vec4i value;
            Mat cnt = new Mat();
            foreach (Mat cnt0 in contours)
            {
                value = uu.Get<Vec4i>(0, j);
                j++;
                //int i = hierarchy;
                // 根據輪廓面積進行篩選      
                if (value[3] != -1)
                {
                    cnt = contours[value[3]];
                }
                else
                {
                    cnt = cnt0;
                }

                center.confidence = 1;
                Moments moms = Cv2.Moments(cnt);
                if (detectorParams.FilterByArea)    //斑點面積的限制
                {
                    double area = moms.M00;    //零階矩即為二值圖像的面積
                    //如果面積超出了設定的范圍,則不再考慮該斑點
                    if (area < detectorParams.MinArea || area >= detectorParams.MaxArea)
                        continue;
                }

                if (detectorParams.FilterByCircularity)    //斑點圓度的限制
                {
                    double area = moms.M00;    //得到斑點的面積
                    //計算斑點的周長
                    double perimeter = Cv2.ArcLength(cnt, true);
                    //由公式3得到斑點的圓度
                    double ratio = 4 * Cv2.PI * area / (perimeter * perimeter);
                    //如果圓度超出了設定的范圍,則不再考慮該斑點
                    if (ratio < detectorParams.MinCircularity || ratio >= detectorParams.MaxCircularity)
                        continue;
                }

                if (detectorParams.FilterByInertia)    //斑點慣性率的限制
                {

                    //計算公式13中最右側等式中的開根號的值
                    double denominator = Math.Sqrt(Math.Pow(2 * moms.Mu11, 2) + Math.Pow(moms.Mu20 - moms.Mu02, 2));
                    const double eps = 1e-2;    //定義一個極小值
                    double ratio;
                    if (denominator > eps)
                    {
                        //cosmin和sinmin用于計算圖像協方差矩陣中較小的那個特征值λ2
                        double cosmin = (moms.Mu20 - moms.Mu02) / denominator;
                        double sinmin = 2 * moms.Mu11 / denominator;
                        //cosmin和sinmin用于計算圖像協方差矩陣中較大的那個特征值λ1
                        double cosmax = -cosmin;
                        double sinmax = -sinmin;
                        //imin為λ2乘以零階中心矩μ00
                        double imin = 0.5 * (moms.Mu20 + moms.Mu02) - 0.5 * (moms.Mu20 - moms.Mu02) * cosmin - moms.Mu11 * sinmin;
                        //imax為λ1乘以零階中心矩μ00
                        double imax = 0.5 * (moms.Mu20 + moms.Mu02) - 0.5 * (moms.Mu20 - moms.Mu02) * cosmax - moms.Mu11 * sinmax;
                        ratio = imin / imax;    //得到斑點的慣性率
                    }
                    else
                    {
                        ratio = 1;    //直接設置為1,即為圓
                    }
                    //如果慣性率超出了設定的范圍,則不再考慮該斑點
                    if (ratio < detectorParams.MinInertiaRatio || ratio >= detectorParams.MaxInertiaRatio)
                        continue;
                    //斑點中心的權值定義為慣性率的平方
                    center.confidence = ratio * ratio;
                }

                if (detectorParams.FilterByConvexity)    //斑點凸度的限制
                {
                    Mat hull = new Mat();  //定義凸殼變量
                    //調用convexHull函數,得到該斑點的凸殼
                    Cv2.ConvexHull(cnt, hull);
                    //分別得到斑點和凸殼的面積,contourArea函數本質上也是求圖像的零階矩
                    double area = Cv2.ContourArea(cnt);
                    double hullArea = Cv2.ContourArea(hull);
                    double ratio = area / hullArea;    //公式5,計算斑點的凸度
                    //如果凸度超出了設定的范圍,則不再考慮該斑點
                    if (ratio < detectorParams.MinConvexity || ratio >= detectorParams.MaxConvexity)
                        continue;
                }

                //根據公式7,計算斑點的質心
                center.location = new Point2d(moms.M10 / moms.M00, moms.M01 / moms.M00);

                // 根據輪廓近似進行篩選,作用很小
                double epsilon = 0.001 * Cv2.ArcLength(cnt, true);
                Mat approx = new Mat();
                Cv2.ApproxPolyDP(cnt, approx, epsilon, true);

                // 根據最小矩形進行篩選,該矩形可能有方向
                RotatedRect rect = Cv2.MinAreaRect(approx);                        
                if (width_bool)
                {
                    int width = rect.BoundingRect().Width;
                    if (width < width_min || width > width_max) continue;
                }
                if (height_bool)
                {
                    int height = rect.BoundingRect().Height;
                    if (height < height_min || height > height_max) continue;
                }
                //根據質心來判斷顏色不合理,但是我覺得這個不合理就把它禁用了
                centers.Add(center);
                outcontours.Add(cnt0);
            }





分享到:  QQ好友和群QQ好友和群
收藏收藏
2#
 樓主| 發表于 2019-5-23 19:44:11 | 只看該作者
本帖最后由 千年傲冰 于 2019-5-23 19:51 編輯

可到我的百度文庫看完整版:wenku.baidu.com/view/19660440370cba1aa8114431b90d6c85ec3a88fc
同時也給大家推薦一本書:《OpenCV計算機視覺編程攻略(第3版)》高清中文版PDF+英文版PDF+源代碼
pan.baidu.com/s/10R9C_Mv638DOk8z-X_p2jg 提取碼:akdy
*滑动验证:
您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|河北快三遗漏分布图  

GMT+8, 2019-7-23 19:25 , Processed in 0.025037 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回復 河北快三遗漏分布图 返回列表