0
点赞
收藏
分享

微信扫一扫

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)


Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_OpenCVSharp

本文作者Color Space,文章未经作者允许禁止转载!

本文将介绍OpenCVSharp应用实例--粘连物体分割与计数(基于形态学+连通域计算)!

本文使用的OpenCVSharp版本---》v4.5.3。

实现目标①:将下图中的糖豆分割出来并计算数量。

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_计算机视觉_02

预期效果图:

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_C# OpenCV_03

实现目标②:将下图中的工件分割出来并计算数量。

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_C# OpenCV_04

预期效果图: 

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_C# OpenCV_05

实现步骤:

【1】Otsu阈值或区间阈值做二值化处理;

//Otsu二值化
Cv2.Threshold(grayImg, thresImg, 0, 255, ThresholdTypes.Otsu);

//或者区间二值化
//Cv2.Threshold(grayImg, thresImg, 106, 255, ThresholdTypes.Binary);

 

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_OpenCVSharp_06

【2】创建圆形结构元素 + 腐蚀操作 --》将粘连区域断开

//创建圆形结构元素
Mat kernal = Mat.Zeros(new Size(15, 15), MatType.CV_8U);
Cv2.Circle(kernal, new Point(7, 7), 7, new Scalar(1, 1, 1), -1);
Cv2.Erode(thresImg, thresImg, kernal);

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_计算机视觉_07

【3】计算连通域 + 连通域膨胀操作

//获得连通域及其属性
ConnectedComponents cc = Cv2.ConnectedComponentsEx(thresImg, PixelConnectivity.Connectivity8, ConnectedComponentsAlgorithmsTypes.Default);
int count = cc.Blobs.Count; //连通域数量0~N, 0对应背景,前景连通域数量N-1
cc.RenderBlobs(imgCopy); //绘制连通域到指定图像
Cv2.ImShow("RenderBlobs", imgCopy);
Cv2.Dilate(imgCopy, imgCopy, kernal);
Cv2.ImShow("dilate", imgCopy);

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_计算机视觉_08

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_OpenCVSharp_09

【4】连通域膨胀结果和原图按权重叠加 + 标注连通域中心 + 输出连通域数量

Mat result = new Mat();
Cv2.AddWeighted(srcImg, 0.8, imgCopy, 0.5, 0, result);
for (int i = 1; i < count; i++) //Blobs[0]对应背景, 这里跳过
{
Point center = new Point((int)cc.Blobs[i].Centroid.X, (int)cc.Blobs[i].Centroid.Y);
Cv2.DrawMarker(result, center, new Scalar(0, 0, 255), MarkerTypes.TiltedCross,
10, 2);
}
Cv2.PutText(result, "count="+(count-1).ToString(), new Point(260, 20),
HersheyFonts.HersheySimplex, 0.7, new Scalar(0, 255, 0), 2);
Cv2.ImShow("result", result);
Cv2.WaitKey(0);

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_连通域_10

OpenCVSharp完整源码:

//公众号:OpenCV与AI深度学习
//作者:Color Space
//CSDN: https://blog.csdn.net/stq054188?spm=1010.2135.3001.5343
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace Segment_And_Count_Objects
{
class Program
{
static void Main(string[] args)
{
Mat srcImg = Cv2.ImRead("pellets.png");
Mat imgCopy = srcImg.Clone();
Cv2.ImShow("src", srcImg);
Mat grayImg = new Mat();
Mat thresImg = new Mat();
Cv2.CvtColor(srcImg, grayImg, ColorConversionCodes.BGR2GRAY);
Cv2.Threshold(grayImg, thresImg, 0, 255, ThresholdTypes.Otsu);
//Cv2.Threshold(grayImg, thresImg, 106, 255, ThresholdTypes.Binary);
Cv2.ImShow("threshold", thresImg);
//创建圆形结构元素
Mat kernal = Mat.Zeros(new Size(15, 15), MatType.CV_8U);
Cv2.Circle(kernal, new Point(7, 7), 7, new Scalar(1, 1, 1), -1);
Cv2.Erode(thresImg, thresImg, kernal);
Cv2.ImShow("erode", thresImg);
//获得连通域及其属性
ConnectedComponents cc = Cv2.ConnectedComponentsEx(thresImg, PixelConnectivity.Connectivity8, ConnectedComponentsAlgorithmsTypes.Default);
int count = cc.Blobs.Count; //连通域数量0~N, 0对应背景,前景连通域数量N-1
cc.RenderBlobs(imgCopy); //绘制连通域到指定图像
Cv2.ImShow("RenderBlobs", imgCopy);
Cv2.Dilate(imgCopy, imgCopy, kernal);
Cv2.ImShow("dilate", imgCopy);
//foreach (var blob in cc.Blobs) //获取每个连通域属性
Mat result = new Mat();
Cv2.AddWeighted(srcImg, 0.8, imgCopy, 0.5, 0, result);
for (int i = 1; i < count; i++) //Blobs[0]对应背景, 这里跳过
{
Point center = new Point((int)cc.Blobs[i].Centroid.X, (int)cc.Blobs[i].Centroid.Y);
Cv2.DrawMarker(result, center, new Scalar(0, 0, 255), MarkerTypes.TiltedCross,
10, 2);
}
Cv2.PutText(result, "count="+(count-1).ToString(), new Point(260, 20), HersheyFonts.HersheySimplex, 0.7, new Scalar(0, 255, 0), 2);
Cv2.ImShow("result", result);
Cv2.WaitKey(0);
}
}
}

实例二对应的代码除了部分参数不同,其他代码都不变,下面是效果图和源码,大家可以自己学习体会:

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_C# OpenCV_11

Halcon实例转OpenCVSharp--粘连物体分割与计数(基于形态学+连通域计算) (附源码)_C#图像处理_12

 OpenCVSharp源码:

8?spm=1010.2135.3001.5343
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace Segment_And_Count_Objects
{
class Program
{
static void Main(string[] args)
{
Mat srcImg = Cv2.ImRead("B0.jpg");
Mat imgCopy = srcImg.Clone();
Cv2.ImShow("src", srcImg);
Mat grayImg = new Mat();
Mat thresImg = new Mat();
Cv2.CvtColor(srcImg, grayImg, ColorConversionCodes.BGR2GRAY);
Cv2.Threshold(grayImg, thresImg, 70, 255, ThresholdTypes.Binary);
Cv2.ImShow("threshold", thresImg);
//创建圆形结构元素
Mat kernal = Mat.Zeros(new Size(53, 53), MatType.CV_8U);
Cv2.Circle(kernal, new Point(26, 26), 26, new Scalar(1, 1, 1), -1);
Cv2.Erode(thresImg, thresImg, kernal);
Cv2.ImShow("erode", thresImg);
//获得连通域及其属性
ConnectedComponents cc = Cv2.ConnectedComponentsEx(thresImg, PixelConnectivity.Connectivity8, ConnectedComponentsAlgorithmsTypes.Default);
int count = cc.Blobs.Count; //连通域数量0~N, 0对应背景,前景连通域数量N-1
cc.RenderBlobs(imgCopy); //绘制连通域到指定图像
Cv2.ImShow("RenderBlobs", imgCopy);
Cv2.Dilate(imgCopy, imgCopy, kernal);
Cv2.ImShow("dilate", imgCopy);
//foreach (var blob in cc.Blobs) //获取每个连通域属性
Mat result = new Mat();
Cv2.AddWeighted(srcImg, 0.8, imgCopy, 0.5, 0, result);
for (int i = 1; i < count; i++) //Blobs[0]对应背景, 这里跳过
{
Point center = new Point((int)cc.Blobs[i].Centroid.X, (int)cc.Blobs[i].Centroid.Y);
Cv2.DrawMarker(result, center, new Scalar(0, 0, 255), MarkerTypes.TiltedCross,
20, 2);
}
Cv2.PutText(result, "count=" + (count - 1).ToString(), new Point(20, 30), HersheyFonts.HersheySimplex, 1.0, new Scalar(0, 255, 0), 2);
Cv2.ImShow("result", result);
Cv2.WaitKey(0);
}
}
}

更多内容请关注微信公众号:OpenCV与AI深度学习 

举报

相关推荐

0 条评论