三个OpenCV目标分割计数实例(附源码)

点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

下面实例核心步骤或者算法:

  1.  二值化+形态学预处理

  2. 距离变换

  3. 分水岭算法

实例一:硬币分割计数

d330ea269e09a42b10bda0225da51e39.jpeg

7bb97deb15ce8e58f16c4c4f84526668.jpeg

上代码:

# import the necessary packages
from skimage.feature import peak_local_max
from skimage.morphology import watershed
from scipy import ndimage
import numpy as np
import argparse
import imutils
import cv2
 
# load the image and perform pyramid mean shift filtering
# to aid the thresholding step
image = cv2.imread("1.jpg")
shifted = cv2.pyrMeanShiftFiltering(image, 21, 51)
cv2.imshow("Input", image)
 
# convert the mean shift image to grayscale, then apply
# Otsu's thresholding
gray = cv2.cvtColor(shifted, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,
  cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv2.imshow("Thresh", thresh)


# compute the exact Euclidean distance from every binary
# pixel to the nearest zero pixel, then find peaks in this
# distance map
D = ndimage.distance_transform_edt(thresh)
localMax = peak_local_max(D, indices=False, min_distance=10,
  labels=thresh)
 
# perform a connected component analysis on the local peaks,
# using 8-connectivity, then appy the Watershed algorithm
markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]
labels = watershed(-D, markers, mask=thresh)
print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1))


# loop over the unique labels returned by the Watershed
# algorithm
for label in np.unique(labels):
  # if the label is zero, we are examining the 'background'
  # so simply ignore it
  if label == 0:
    continue
 
  # otherwise, allocate memory for the label region and draw
  # it on the mask
  mask = np.zeros(gray.shape, dtype="uint8")
  mask[labels == label] = 255
 
  # detect contours in the mask and grab the largest one
  cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
    cv2.CHAIN_APPROX_SIMPLE)
  cnts = imutils.grab_contours(cnts)
  c = max(cnts, key=cv2.contourArea)
 
  # draw a circle enclosing the object
  ((x, y), r) = cv2.minEnclosingCircle(c)
  cv2.circle(image, (int(x), int(y)), int(r), (0, 255, 0), 2)
  cv2.putText(image, "{}".format(label), (int(x) - 10, int(y)),
    cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
 
# show the output image
cv2.imshow("Output", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

分割计数结果:

4852bd1ee688cf6e79bd8ccef16a37e9.jpeg

53bc1cbc34b99b88f7fa4e3113bb5767.jpeg

实例二:药片分割计数

代码同上,可能参数需略微调整,上效果:

0303314a2cf92e091630d45754036085.jpeg

961488af1c70b30f93a7555bf9462645.jpeg

实例三:玉米粒分割计数

53c7cb9a746244cdac5ee243f4cb4366.jpeg

上代码:

import numpy as np
import cv2
from matplotlib import pyplot as plt
font=cv2.FONT_HERSHEY_SIMPLEX


img = cv2.imread('5.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,245,255,cv2.THRESH_BINARY)
cv2.imshow("threshold", thresh)


k = cv2.getStructuringElement(cv2.MORPH_RECT,(13,13))
dilate = cv2.dilate(thresh,k,iterations=3)
cv2.imshow("dilate", dilate)


cv2.bitwise_not(dilate, dilate)
dist_transform = cv2.distanceTransform(dilate,cv2.DIST_L2,3)
dist = cv2.normalize(dist_transform,dist_transform,0,1.0,cv2.NORM_MINMAX)
cv2.imshow("distance", dist)
cv2.imwrite("dis.jpg", dist)


#dist = np.uint8(dist)
dist = cv2.convertScaleAbs(dist)
ret2,morph = cv2.threshold(dist,0.99,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
#ret2, morph = cv2.threshold(dist,0,255,cv2.THRESH_BINARY_INV)
cv2.imshow("morph", morph)


k2 = cv2.getStructuringElement(cv2.MORPH_RECT,(11,5))
sure_fg = cv2.morphologyEx(morph,cv2.MORPH_OPEN,k2, iterations = 1) # 形态开运算


cv2.imshow("result", sure_fg)
 


thresh,contours,hierarchy = cv2.findContours(sure_fg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for i in range(0,len(contours)):
  (x, y, w, h) = cv2.boundingRect(contours[i])
  #cv2.drawContours(img,contours,i,(0,255,0),5)
  cv2.circle(img,(x+int(w/2),y+int(h/2)),20,(0,0,255),-1, cv2.LINE_AA)
  cv2.putText(img,str(i+1),(x+int(w/2)-15,y+int(h/2)+5),font,0.8,(0,255,0),2)  
  
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

分割计数效果:

59bfcef81ab9ce4282178e4de15e6bbc.jpeg

中间执行结果略去,大家可以复制源码和图片自己运行,查看中间结果,简单来做个总结:

  1. 预处理---基本就是二值化和形态学操作

  2. 粘连分割---距离变换少不了

  3. 分水岭算法---根据实际情况使用,有时候分割不太可控,慎用

参考资料:

https://www.pyimagesearch.com/2015/11/02/watershed-opencv/

https://www.itread01.com/content/1545201032.html

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程,即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。


下载2:Python视觉实战项目52讲
在「小白学视觉」公众号后台回复:Python视觉实战项目,即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。


下载3:OpenCV实战项目20讲
在「小白学视觉」公众号后台回复:OpenCV实战项目20讲,即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。


交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值