Python-OpenCV分割图像查枸杞的个数

AI浩 发表于 2022/02/11 09:31:13 2022/02/11
【摘要】 ​ 图像分割算法有分水岭算法、斑点计数算法、霍夫圆/椭圆算法、轮廓检测算法等。在本文中,本例使用了轮廓检测和分水岭算法。​第一步导入依赖from __future__ import print_functionimport numpy as npimport cv2import matplotlib.pyplot as pltfrom skimage import iofrom skimag...

 图像分割算法有分水岭算法、斑点计数算法、霍夫圆/椭圆算法、轮廓检测算法等。在本文中,本例使用了轮廓检测和分水岭算法。


第一步导入依赖

from __future__ import print_function
import numpy as np
import cv2
import matplotlib.pyplot as plt
from skimage import io
from skimage.morphology import watershed
from skimage.feature import peak_local_max
from scipy import ndimage

创建可视化图像函数:

def show(img):

    plt.imshow(img)

    plt.show()

读取图像

#load

fp = "1.jpg"

img = cv2.imread(fp)

show(img)

print(img.shape)

对图像进行预处理。步骤包括:

  • HSV,这是人眼感知的颜色模型。
  • 阈值技术,通过选定的阈值像素强度将图像转换为二值图像(即只有2个像素值(0或255))。
  • 模糊图像,以删除图像中不必要的斑点。

#preprocessing the image
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
show(hsv)


h, s, v = cv2.split(hsv)
show(s)


_, thr = cv2.threshold(s, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
show(thr)


blur = cv2.medianBlur(thr, 5)
show(blur)


现在我们使用轮廓检测,在我们“模糊”的图像中找到枸杞。为了去除小的和无关紧要的轮廓,我们只选择那些面积大于2000的轮廓(任意值,是超参数)。

contours, hierarchy = cv2.findContours(blur,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
copy2 = img.copy()
count = []
for x in contours:
   
area = cv2.contourArea(x)
   
if area > 2000 :
       
count.append(x)
cv2.drawContours(copy2, count, -1, (255,0,0), 3)
show(copy2)
print("number of lemons found via contour detection = ", len(count))


现在我们使用分水岭算法来分离相互接触的枸杞(如果有的话)。

copy3 = img.copy()
D = ndimage.distance_transform_edt(thr)
localMax = peak_local_max(D, indices=False, min_distance=300,
  
labels=thr)
markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]
labels = watershed(-D, markers, mask=thr)
ws = len(np.unique(labels)) -1
copy3[labels == -1] = [255,0,0]
print("no. of lemons found via watershed algorithm = ", ws)

计算两种方法的平均值:

ans = int((len(count) + len(np.unique(labels)) -1) / 2)
print("number of lemon segments detected = ", ans)
show(copy2)


完整代码:

from __future__ import print_function
import numpy as np
import cv2
import matplotlib.pyplot as plt
from skimage import io
from skimage.morphology import watershed
from skimage.feature import peak_local_max
from scipy import ndimage

def show(img):
   
plt.imshow(img)
   
plt.show()
#load
fp = "1.jpg"
img = cv2.imread(fp)
show(img)
print(img.shape)
#preprocessing the image
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
show(hsv)
h, s, v = cv2.split(hsv)
show(s)
_, thr = cv2.threshold(s, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
show(thr)
blur = cv2.medianBlur(thr, 5)
show(blur)
contours, hierarchy = cv2.findContours(blur,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
copy2 = img.copy()
count = []
for x in contours:
   
area = cv2.contourArea(x)
   
if area > 2000 :
       
count.append(x)
cv2.drawContours(copy2, count, -1, (255,0,0), 3)
show(copy2)
print("number of lemons found via contour detection = ", len(count))
copy3 = img.copy()
D = ndimage.distance_transform_edt(thr)
localMax = peak_local_max(D, indices=False, min_distance=300,
  
labels=thr)
markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]
labels = watershed(-D, markers, mask=thr)
ws = len(np.unique(labels)) -1
copy3[labels == -1] = [255,0,0]
print("no. of lemons found via watershed algorithm = ", ws)
ans = int((len(count) + len(np.unique(labels)) -1) / 2)
print("number of lemon segments detected = ", ans)
show(copy2)

输出的结果如下:


参照:今日头条

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。