OpenCv案例(一):OpenCvSharp识别图像中物体个数

需求:识别下图中零件的个数,包括其中有粘连部分;同理,可以识别零件以及其他产线样品数量;(如果不知如何使用OpenCvSharp,参考该文章(OpenCvSharp安装)中第一部分内容)

识别图像:

主要代码内容如下:

public Mat GetNumberByImg(Mat src, out int num)
        {
            num = 0;
            //图像灰度
            Mat matGray = new Mat();
            Cv2.CvtColor(src, matGray, ColorConversionCodes.BGR2GRAY);

            Mat blurMat = new Mat();
            Cv2.MedianBlur(matGray, blurMat, 5);
            Cv2.ImShow("blurMat", blurMat);

            //图像二值化
            Mat binaryMat = new Mat();
            Cv2.Threshold(blurMat, binaryMat, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
            Cv2.ImShow("binaryImg", binaryMat);

            //形态学操作
            Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 3), new Point(-1, -1));
            Cv2.MorphologyEx(binaryMat, binaryMat, MorphTypes.Dilate, kernel, new Point(-1, -1), 1);
            Cv2.ImShow("Dilate", binaryMat);

            //距离变换
            Mat dist = new Mat();
            Cv2.BitwiseNot(binaryMat, binaryMat);
            Cv2.ImShow("binaryMat", binaryMat);
            Cv2.DistanceTransform(binaryMat, dist, DistanceTypes.L2, DistanceMaskSize.Mask3);
            Cv2.Normalize(dist, dist, 0, 1, NormTypes.MinMax);
            //Cv2.ImShow("distImage", dist);

            //阈值化二值分割
            Mat dist_8U = new Mat();
            dist.ConvertTo(dist_8U, MatType.CV_8U);
            //自适应阈值则,是根据像素的邻域块的像素值分布来确定该像素位置上的二值化阈值
            Cv2.AdaptiveThreshold(dist_8U, dist_8U, 250, AdaptiveThresholdTypes.GaussianC, ThresholdTypes.Binary, 101, 0);
            Cv2.ImShow("dist-AdaptiveThreshold", dist_8U);
            kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 3), new Point(-1, -1));
            Cv2.Dilate(dist_8U, dist_8U, kernel, new Point(-1, -1), 2);
            Cv2.ImShow("dist-Dilate", dist_8U);

            //连通区域计算
            Point[][] contours;
            HierarchyIndex[] hierarchies;
            Cv2.FindContours(dist_8U, out contours, out hierarchies, RetrievalModes.External, ContourApproximationModes.ApproxSimple);

            //绘制结果图像
            Mat markRet = Mat.Zeros(src.Size(), MatType.CV_8UC3);
            RNG rng = new RNG(12345);
            for (int i = 0; i < contours.Length; i++)
            {
                Cv2.DrawContours(markRet, contours, i, new Scalar(rng.Uniform(0, 255), rng.Uniform(0, 255), rng.Uniform(0, 255)), -1, LineTypes.Link8);
            }
            num = contours.Length;
            return markRet;
        }

 处理后部分图像如下所示:

        二值图像

         形态学操作(膨胀操作)

          二值图像

         自适应阈值后再次形态学操作(膨胀)

         颜色填充

        打印结果 

         

 该案例基本处理步骤如上,主要难点是如何分离粘连部分的操作;不同图像需要对上述算法中一些参数进行调整(若不理解部分算法参数含义,查找相关资料学习);

猜你喜欢

转载自blog.csdn.net/qq_37835727/article/details/123571056
今日推荐