C# OpenCvSharp 玉米粒计数

效果

项目

代码

复制代码
using OpenCvSharp;
using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace OpenCvSharp_Demo
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string image_path = "";

        DateTime dt1 = DateTime.Now;
        DateTime dt2 = DateTime.Now;

        Mat image;
        Mat result_image;

        StringBuilder sb = new StringBuilder();

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;

            pictureBox1.Image = null;
            pictureBox2.Image = null;
            textBox1.Text = "";

            image_path = ofd.FileName;
            pictureBox1.Image = new Bitmap(image_path);
            image = new Mat(image_path);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //test
            image_path = "test_img/1.jpg";
            image = new Mat(image_path);
            pictureBox1.Image = new Bitmap(image_path);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (image_path == "")
            {
                return;
            }
            textBox1.Text = "检测中,请稍等......";
            pictureBox2.Image = null;
            Application.DoEvents();

            result_image = image.Clone();

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

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

            //距离变换:用于二值化图像中的每一个非零点距自己最近的零点的距离,距离变换图像上越亮的点,代表了这一点距离零点的距离越远
            Mat dist = new Mat();
            Cv2.BitwiseNot(morhImage, morhImage);
            /*
            OpenCV中,函数distanceTransform()用于计算图像中每一个非零点像素与其最近的零点像素之间的距离,
            输出的是保存每一个非零点与最近零点的距离信息,图像上越亮的点,代表了离零点的距离越远。
            用途:
            可以根据距离变换的这个性质,经过简单的运算,用于细化字符的轮廓和查找物体质心(中心)。
            */
            /*
            距离变换的处理图像通常都是二值图像,而二值图像其实就是把图像分为两部分,即背景和物体两部分,物体通常又称为前景目标。
            通常我们把前景目标的灰度值设为255(即白色),背景的灰度值设为0(即黑色)。
            所以定义中的非零像素点即为前景目标,零像素点即为背景。
            所以图像中前景目标中的像素点距离背景越远,那么距离就越大,如果我们用这个距离值替换像素值,那么新生成的图像中这个点越亮。
            */
            //User:用户自定义
            //L1:  曼哈顿距离
            //L2:  欧式距离
            //C:   棋盘距离
            Cv2.DistanceTransform(morhImage, dist, DistanceTypes.L1, DistanceTransformMasks.Mask3);
            Cv2.Normalize(dist, dist, 0, 1.0, NormTypes.MinMax);   //范围在0~1之间
            //Cv2.ImShow("distance", dist);

            //形态学处理
            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 OpenCvSharp.Size(7, 3), new OpenCvSharp.Point(-1, -1));
            Cv2.MorphologyEx(MorphImg, MorphImg, MorphTypes.Open, kernel);  //开操作
            //Cv2.ImShow("t-distance", MorphImg);

            //找到种子的轮廓区域
            OpenCvSharp.Point[][] contours;
            HierarchyIndex[] hierarchly;
            Cv2.FindContours(MorphImg, out contours, out hierarchly, RetrievalModes.External, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0));
            Mat markers = Mat.Zeros(image.Size(), MatType.CV_8UC3);
            int x, y, w, h;
            Rect rect;
            for (int i = 0; i < contours.Length; i++)
            {
                // Cv2.DrawContours(markers, contours, i, Scalar.RandomColor(), 2, LineTypes.Link8, hierarchly);
                rect = Cv2.BoundingRect(contours[i]);
                x = rect.X;
                y = rect.Y;
                w = rect.Width;
                h = rect.Height;
                Cv2.Circle(result_image, x + w / 2, y + h / 2, 20, new Scalar(0, 0, 255), -1);
                if (i >= 9)
                {
                    Cv2.PutText(result_image, (i + 1).ToString(), new OpenCvSharp.Point(x + w / 2 - 18, y + h / 2 + 8), HersheyFonts.HersheySimplex, 0.8, new Scalar(0, 255, 0), 2);
                }
                else
                {
                    Cv2.PutText(result_image, (i + 1).ToString(), new OpenCvSharp.Point(x + w / 2 - 8, y + h / 2 + 8), HersheyFonts.HersheySimplex, 0.8, new Scalar(0, 255, 0), 2);
                }
            }

            textBox1.Text = "number of corns: " + contours.Length;
            pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());


        }

        private void pictureBox2_DoubleClick(object sender, EventArgs e)
        {
            Common.ShowNormalImg(pictureBox2.Image);
        }

        private void pictureBox1_DoubleClick(object sender, EventArgs e)
        {
            Common.ShowNormalImg(pictureBox1.Image);
        }
    }
}

下载

Demo下载

相关推荐
deephub2 小时前
TPU 架构与 Pallas Kernel 编程入门:从内存层次结构到 FlashAttention
人工智能·python·深度学习·tpu
人工智能培训2 小时前
少量样本下具身智能的新环境快速适应路径
人工智能·深度学习·机器学习
枫叶林FYL3 小时前
【脑电图信号自动睡眠分期(机器学习驱动睡眠质量评估)】第二章 应用场景拓展、可穿戴集成与临床转化挑战
人工智能·深度学习·机器学习
K姐研究社3 小时前
Pexo AI视频制作教程 – 零门槛生成UGC带货视频
人工智能
智能工业品检测-奇妙智能3 小时前
绩效考核系统的核心功能
人工智能·目标检测·计算机视觉·奇妙智能
多租户观察室3 小时前
工作流新生态:2026年工作流与Coding的重新分工
前端·人工智能·后端·低代码
枫叶林FYL3 小时前
公开数据集类型汇总分类
人工智能·分类·数据挖掘
Daydream.V3 小时前
opencv项目实战——抠图
opencv·抠图
张驰咨询公司3 小时前
电池制造进入“统计控制时代”:六西格玛如何解锁材料一致性的终极密码
人工智能·六西格玛培训·六西格玛绿带培训·精益六西格·六西格玛培训公司
FluxMelodySun3 小时前
机器学习(二十六) 降维:流形学习
人工智能·机器学习