背景介绍
测试图如下,图中有个别米粒相互粘连,本文主要演示如何使用OpenCV用两种不同方法将其分割并计数。

方法一:基于分水岭算法
基于分水岭算法分割步骤如下:
【1】高斯滤波 + 二值化 +开运算
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray,(5,5),0) ret, binary= cv2.threshold(gray, 115, 255, cv2.THRESH_BINARY) kernel = np.ones((5, 5), np.uint8) binary=cv2.morphologyEx(binary,cv2.MORPH_OPEN,kernel,iterations=1) cv2.imshow('thres', binary)

【2】距离变换 + 提取前景
dist = cv2.distanceTransform(binary, cv2.DIST_L2, 3)
dist_out = cv2.normalize(dist, 0, 1.0, cv2.NORM_MINMAX)
cv2.imshow('distance-Transform', dist_out * 100)
ret, surface = cv2.threshold(dist_out, 0.35*dist_out.max(), 255, cv2.THRESH_BINARY)
cv2.imshow('surface', surface)
sure_fg = np.uint8(surface)# 转成8位整型
cv2.imshow('Sure foreground', sure_fg)


【3】标记位置区域
# 未知区域标记为0 markers[unknown == 255] = 0 kernel = np.ones((5, 5), np.uint8) binary = cv2.morphologyEx(binary, cv2.MORPH_DILATE, kernel, iterations=1) unknown = binary - sure_fg cv2.imshow('unknown',unknown)

【4】分水岭算法分割
markers = cv2.watershed(img, markers=markers) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(markers)
【5】轮廓查找和标记
contours,hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) forcntincontours: M = cv2.moments(cnt) cx = int(M['m10']/M['m00']) cx = int(M['m10']/M['m00']) cy = int(M['m01']/M['m00'])#轮廓重心 cv2.drawContours(img,contours,-1,colors[rd.randint(0,5)],2) cv2.drawMarker(img, (cx,cy),(0,255,0),1,8,2)

方法二:轮廓凸包缺陷方法
基于轮廓凸包缺陷分割步骤如下:
【1】高斯滤波 + 二值化 +开运算
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray,(5,5),0)
ret, binary= cv2.threshold(gray, 115, 255, cv2.THRESH_BINARY)
kernel=np.ones((5,5),np.uint8)
binary=cv2.morphologyEx(binary,cv2.MORPH_OPEN,kernel,iterations=1)
cv2.imshow('thres', binary)

【2】轮廓遍历 + 筛选轮廓含有凸包缺陷的轮廓
contours,hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt in contours:
hull = cv2.convexHull(cnt,returnPoints=False)#默认returnPoints=True
defects = cv2.convexityDefects(cnt,hull)
#print defects
pt_list = []
if defects is not None:
flag = False
for i in range(0,defects.shape[0]):
s,e,f,d = defects[i,0]
if d > 4500:
flag = True

【3】将距离d最大的两个凸包缺陷点连起来,将二值图中对应的粘连区域分割开,红色圆标注为分割开的部分
if len(pt_list) > 0:
cv2.line(binary,pt_list[0],pt_list[1],0,2)
cv2.imshow('binary2',binary)


【4】重新查找轮廓并标记结果
contours,hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt in contours:
try:
M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])#轮廓重心
cv2.drawContours(img,cnt,-1,colors[rd.randint(0,5)],2)
cv2.drawMarker(img, (cx,cy),(0,0,255),1,8,2)
except:
pass

审核编辑:刘清
-
高斯滤波
+关注
关注
0文章
18浏览量
8210 -
OpenCV
+关注
关注
33文章
651浏览量
44420
原文标题:实战 | OpenCV两种不同方法实现粘连大米分割计数(步骤 + 代码)
文章出处:【微信号:vision263com,微信公众号:新机器视觉】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
两种LED驱动模式的功能及使用方法
两种verilog语言写法的实现问题!求解答~
基于LabVIEW的Modbus协议两种校验码的实现方法
单片机系统实现延时的两种方法解析
Multibool的两种实现方法详细资料介绍
片机实现延时的两种方法
PCI设备两种底层访问方法的实现及比较分析

OpenCV两种不同方法实现粘连大米分割计数
评论