前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实战 | OpenCV两种不同方法实现粘连大米分割计数(步骤 + 代码)

实战 | OpenCV两种不同方法实现粘连大米分割计数(步骤 + 代码)

作者头像
Color Space
发布2024-01-18 14:33:28
2920
发布2024-01-18 14:33:28
举报

视觉/图像重磅干货,第一时间送达

导 读

本文主要介绍基于OpenCV的两种不同方法实现粘连大米分割计数,并给详细步骤和代码。

背景介绍

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

方法一:基于分水岭算法

基于分水岭算法分割步骤如下:

【1】高斯滤波 + 二值化 + 开运算

代码语言:javascript
复制
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】距离变换 + 提取前景

代码语言:javascript
复制
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】标记位置区域

代码语言:javascript
复制
# 未知区域标记为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】分水岭算法分割

代码语言:javascript
复制
markers = cv2.watershed(img, markers=markers)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(markers)

【5】轮廓查找和标记

代码语言:javascript
复制
contours,hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    for cnt in contours:
        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】高斯滤波 + 二值化 + 开运算

代码语言:javascript
复制
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】轮廓遍历 + 筛选轮廓含有凸包缺陷的轮廓

代码语言:javascript
复制
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最大的两个凸包缺陷点连起来,将二值图中对应的粘连区域分割开,红色圆标注为分割开的部分

代码语言:javascript
复制
    if len(pt_list) > 0:
        cv2.line(binary,pt_list[0],pt_list[1],0,2)  
cv2.imshow('binary2',binary)

【4】重新查找轮廓并标记结果

代码语言:javascript
复制
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

—THE END—

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-01-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV与AI深度学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • —THE END—
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档