首页 > 编程语言 >C#+OpenCV实战(三)_玉米粒计数

C#+OpenCV实战(三)_玉米粒计数

时间:2024-07-11 11:56:41浏览次数:14  
标签:Mat Point C# 玉米粒 Cv2 OpenCV new 轮廓 CV

/// <summary>
/// 标注物体 -物体计数标注
/// 比如玉米粒计数并标注每个玉米
/// </summary>
/// <param name="imgFile1"></param>
/// <returns>物体位置;数量=contours.Length</returns>
public static Point[][] ImageDetector_CountAndLabel(Mat srcMat, out Mat dstMat)
{
    dstMat = new Mat();
    srcMat.CopyTo(dstMat);

    // 二值化操作
    Mat grayimg = new Mat();
    Cv2.CvtColor(srcMat, grayimg, ColorConversionCodes.BGR2GRAY);
    Mat binaryImg = new Mat();
    Cv2.Threshold(grayimg, binaryImg, 240, 255, ThresholdTypes.Binary);

    // 腐蚀
    Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(15, 15));
    Mat morhImage = new Mat();
    Cv2.Dilate(binaryImg, morhImage, kernel, null, 2);

    // 距离变换:用于二值化图像中的每一个非零点距自己最近的零点的距离,距离变换图像上越亮的点,代表了这一点距离零点的距离越远
    Mat dist = new Mat();
    Cv2.BitwiseNot(morhImage, morhImage);

    // 计算物体之间的距离
    Cv2.DistanceTransform(morhImage, dist, DistanceTypes.L1, DistanceTransformMasks.Mask3);  // 曼哈顿距离,
    Cv2.Normalize(dist, dist, 0, 1.0, NormTypes.MinMax);   //范围在0~1之间

    // 形态学处理
    Mat morphImg = new Mat();
    dist.ConvertTo(morphImg, MatType.CV_8U);
    Cv2.Threshold(morphImg, morphImg, 0.99, 255, ThresholdTypes.Binary);  //上图像素值在0~1之间
    kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(7, 3), new Point(-1, -1));
    Cv2.MorphologyEx(morphImg, morphImg, MorphTypes.Open, kernel);        //开操作

    // 找到种子的轮廓区域
    /*
     * 找轮廓(输入图像,out 轮廓集合,out 级别,轮廓检索模式,近似法,偏移量)
     * 输入图像:单通道图像矩阵,可以是灰度图,但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像;
     * 轮廓集合:contours 
     * 历史轮廓:hierarchy:0:后一个轮廓,1:前一个轮廓,2:父轮廓,3:内嵌轮廓
     * 轮廓检索模式:轮廓的检索模式
     *         取值一:CV_RETR_EXTERNAL 只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略
     *         取值二:CV_RETR_LIST     检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到
     *         取值三:CV_RETR_CCOMP    检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层
     *         取值四:CV_RETR_TREE     检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。
     * 近似方法:轮廓的近似方法
     *         取值一:CV_CHAIN_APPROX_NONE   保存物体边界上所有连续的轮廓点到contours向量内
     *         取值二:CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留
     *         取值三和四:CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
     * 偏移量:Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,且Point可以是负值。不填为默认不偏移Point()
    */
    Cv2.FindContours(morphImg, out Point[][] contours, out HierarchyIndex[] hierarchly, RetrievalModes.External, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0));

    // 标识位置
    for (int i = 0; i < contours.Length; i++)
    {
        Rect rect = Cv2.BoundingRect(contours[i]);
        int x = rect.X;
        int y = rect.Y;
        int w = rect.Width;
        int h = rect.Height;
        Cv2.Circle(dstMat, x + w / 2, y + h / 2, 20, new Scalar(0, 0, 255), -1);
        if (i >= 9)
        {
            Cv2.PutText(dstMat, (i + 1).ToString(), new Point(x + w / 2 - 18, y + h / 2 + 8), HersheyFonts.HersheySimplex, 0.8, new Scalar(0, 255, 0), 2);
        }
        else
        {
            Cv2.PutText(dstMat, (i + 1).ToString(), new Point(x + w / 2 - 8, y + h / 2 + 8), HersheyFonts.HersheySimplex, 0.8, new Scalar(0, 255, 0), 2);
        }
    }

    return contours;
}

标签:Mat,Point,C#,玉米粒,Cv2,OpenCV,new,轮廓,CV
From: https://www.cnblogs.com/qq2806933146xiaobai/p/18295839

相关文章

  • C#+OpenCV实战(四)_特定钢板缺陷检测
    ///<summary>///板材瑕疵检测(凹凸坑、划痕、颜料瑕疵)///</summary>///<paramname="mat">图片</param>///<paramname="resultMat">结果图片</param>///<paramname="minArcLength">最小有效斑弧长;默认为5</param>......
  • 详解C#委托与事件
    在C#中,委托是一种引用类型的数据类型,允许我们封装方法的引用。通过使用委托,我们可以将方法作为参数传递给其他方法,或者将多个方法组合在一起,从而实现更灵活的编程模式。委托类似于函数指针,但提供了类型安全和垃圾回收等现代语言特性。基本概念定义委托定义委托需要指定它所代......
  • Cesium 点击查询
    代码letclickHandler=null;//functioninitClickHandler(){//初始化clickHandler=newCesium.ScreenSpaceEventHandler(viewer.scene.canvas);//绑定左点击事件clickHandler.setInputAction((click)=>{//获取球面坐标可用于定位或者渲染点位数据......
  • Marking criteria for COMP9444 project
    Marking criteria for COMP9444 projectTotal marks for the project work:35 marks.1.   Project Notebook(s):20 Marks2.   Summary Report (max 4pages): 5 marks3.   Project Presentation: 10 MarksBreakdownofmarksforeachcompon......
  • elasticsearch: 插件安装与删除
    一,安装插件1,查看已安装的插件:[lhdop@blog~]$curl-XGET"localhost:9200/_cat/plugins?v&s=component"namecomponentversion2,从命令行安装smartcn分词插件:[lhdop@blogbin]$./elasticsearch-plugininstallanalysis-smartcnwarning:ignoringJAVA_HOME=/usr/loc......
  • Linux学习笔记(03)——C编程入门
    vim编辑器需要先安装:sudoapt-getinstallvim使用vimxxx.txt:打开文件一般模式(指令模式):默认模式编辑模式:一般按下“a”进入编辑,按下ESC键可退出编辑模式命令行模式(底行模式):先进入一般模式,后输入:/?任意一个进入保存退出:进入底行模式,下面会出现:可在:后输入x保......
  • C#+OpenCV进阶(一)_人体识别
      效果排名:Lbp<Haar<CNN1、Lbp///<summary>///Lbp人脸识别///</summary>publicstaticMatFaceDetection_Lbp(Matmat){varlbpCascade=newCascadeClassifier("model/lbpcascade_frontalface.xml");MatoutMat=newMat();......
  • golang sync.Pool 的基本原理
    sync.Pool包寥寥不过300行代码,却可以为我们提供类似对象池的功能,减少了对象的重复创建于销毁,减少了性能损耗,增加内存复用,同时自带mutex锁可以保证Put/Get操作的并发安全特性,在一些对象需要重复创建销毁的场景中很是实用,今天来看看sync.Pool的基本原理。sync.Pool就在标准......
  • QtQuick.Dialogs中的FileDialog设置默认目录的问题
    在QML中,假如想要使用文件浏览器选择文件或者文件夹时。可以使用FileDialog。FileDialog有个属性folder,设置好路径之后,当你打开fileDialog时,fileDialog当前定位到的路径就是你设置的路径。但是这个folder的设置有点问题,和路径的层级有关系假如你的目标路径是大于等于三级的(比如......
  • C#+OpenCV进阶(三)_操作摄像头与视频文件
    1、VideoCapture的常用属性#region常用属性//_=videoCapture.CaptureType;//获取视频的捕获类型(文件或摄像头)//_=videoCapture.PosAviRatio;//获取或设置视频的相对位置(0开头1结尾)//_=videoCapture.FourCC;//获取或设置视频的编解码的4字符代码//_=......