首页 > 编程问答 >如何为神经网络分割一批豆子

如何为神经网络分割一批豆子

时间:2024-07-27 04:45:24浏览次数:7  
标签:python opencv computer-vision watershed

我遇到了一个问题,我想识别混合中的不同咖啡豆。 我创建了一个神经网络,它能够单独识别不同的豆子。但在实践中,我想开发一种算法,可以批量检测这些豆子。没有必要识别图片中的所有豆子,但是当我能够识别较大批次中的 10-15 个豆子时,这就足够了。

现在的问题是我能够分割豆子当只有一层具有对比背景的 beans 时,但是当第一层下面有多层 beans 时,它会变得非常困难。

我尝试使用距离变换和来自 openCV 的分水岭算法,如上所述,这仅适用于单个 bean 和 bean 之间的一些小重叠(就像 这个示例 一样)。下图显示了结果: 单层分割的结果

我使用的代码是基于前面提到的示例:

import cv2 
import numpy as np
from matplotlib import pyplot as plt
from scipy.ndimage import label
from scipy.ndimage import morphology

# load the image as normal and grayscale 
img_path = "FINAL/segmentation/IMG_6699.JPG"
img= cv.imread(img_path,0)
img0 = cv.imread(img_path)

#preprocess the image
img= cv.medianBlur(img,5)
ret,th1 = cv.threshold(img,80,255,cv.THRESH_BINARY_INV)
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(th1, cv2.MORPH_OPEN, kernel)
dilation = cv2.dilate(opening, None, iterations=2)
erosion = cv2.erode(dilation,kernel,iterations = 50)
border_nonseg = dilation - cv2.erode(dilation, None, iterations = 1)


#distance transform 
#dt = morphology.distance_transform_bf(dilation, metric='chessboard')
dt = cv2.distanceTransform(dilation, 2, 5)   
dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(np.uint8)
hier, dt1 = cv2.threshold(dt, 170, 255, cv2.THRESH_BINARY)

# label the centers found by the distance transform 
lbl, ncc = label(dt1)
lbl = lbl * (255/ncc)      
# Completing the markers now. 
lbl[border_nonseg == 255] = 255
lbl = lbl.astype(np.int32)

# Watershed algorithm 
cv2.watershed(img0, lbl)

lbl[lbl == -1] = 0
lbl = lbl.astype(np.uint8)
result = 255 - lbl
lbl_cont = result

# Draw the borders 
result[result != 255] = 0
result = cv2.dilate(result, None, iterations=1)
img0[result == 255] = (255, 0, 0)
cv2.imwrite("output.png", img0)
contours, _ = cv.findContours(result, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

titles = ['Original Image', 'dilation',
            'gradient morph', 'erode']
images = [ border_nonseg, dt, lbl_cont, img0]
plt.figure(figsize=(20,20))
for i in range(4):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

但是当出现这样的图片时(这是真实情况),问题就开始了: 多层分割 更难的多层分割

我不认为我能够重用前面提到的代码,并且我需要一种不同的方法。因为第一层和第二层之间的对比度太小,因为豆子的尺寸很小,所以它们不会产生很大的阴影,这会产生很好的对比度,而且豆子的颜色也很暗,这使得并没有让它变得更容易。
那么您对解决这个问题的不同方法有什么建议,或者调整当前的代码来解决我的问题吗?

我很好奇听到对此的不同意见!


你绝对说对了,当咖啡豆堆叠在一起,并且底层咖啡豆与背景的对比度很低时,分割咖啡豆就会变得更加困难。你的初始方法适用于单层,但你需要更强大的技术来处理这些复杂的情况。

以下是一些可以探索的想法来改进你的咖啡豆分割:

1. 改进预处理

  • 多尺度处理: 由于某些咖啡豆很小,并且由于遮挡而对比度较低,因此尝试使用不同大小的核进行多尺度处理(例如,高斯模糊或拉普拉斯算子)。这可以帮助你增强不同尺度的特征,并可能使那些隐藏的咖啡豆更加突出。
  • 直方图均衡化: 尝试对图像的特定区域(其中咖啡豆较暗)应用局部直方图均衡化,以改善对比度。
  • 颜色空间: 尝试在 RGB 以外的不同颜色空间(例如 HSV 或 LAB)中工作。某些颜色空间可能可以更好地分离咖啡豆和背景,具体取决于咖啡豆和照明条件。

2. 分割

  • 基于边缘的分割: 由于你的分水岭方法在一定程度上有效,因此尝试改进边缘检测。调查更先进的边缘检测算法,例如 Canny 边缘检测,或使用机器学习方法训练边缘检测器,专门针对你的咖啡豆图像。
  • 基于区域的分割: 探索区域生长或区域合并等技术。这些算法可以根据颜色、纹理或相似性的标准对像素进行分组,这可能有助于分离重叠的咖啡豆。
  • 基于机器学习的分割: 对于更强大的解决方案,请考虑训练分割模型,例如 U-Net 或 Mask R-CNN。这些模型需要大量带注释的数据(分割后的咖啡豆图像),但可以学习识别复杂模式并处理遮挡。

3. 后处理

  • 形态学运算: 在分割后,使用形态学运算(例如腐蚀、膨胀或开运算)来细化分割后的区域并消除噪声或小伪影。
  • 基于形状的过滤: 如果你的咖啡豆具有独特的形状特征,则使用基于形状的标准(例如,面积、圆度或纵横比)过滤分割后的区域。这可以帮助你消除与典型咖啡豆形状不符的误报。
  • 重叠分析: 识别并处理重叠的咖啡豆。你可以根据分割后的区域的大小、形状或其他特征来分析重叠程度,并可能应用算法来分离它们。

实现提示:

  • 逐步改进: 逐步处理你的分割管道,并评估每个步骤的影响。
  • 数据增强: 如果选择机器学习方法,则使用数据增强技术(例如翻转、旋转和缩放)来增加训练数据集的大小和多样性。
  • 实验: 不要害怕尝试不同的技术、参数和组合,以找到最适合你的特定数据的技术。

请记住,没有一种通用的解决方案可以完美地分割所有情况下的咖啡豆。你需要根据图像的具体特征和所面对的挑战来试验和调整你的方法。

标签:python,opencv,computer-vision,watershed
From: 66851460

相关文章

  • 使用类型提示将 Python 转换为 Cython
    类型提示现在在Python3.5版本中可用。在规范(PEP484)中,目标(和非目标)被明确暴露:#RationaleandGoals此PEP旨在为类型注释提供标准语法,开放Python代码更容易静态分析和重构、潜在的运行时类型检查以及(也许在某些情况下)利用类型信息生成代码。......
  • 在 Python 类型提示中区分 PySpark 和 Pandas DataFrame (PyCharm)
    在PyCharm中,如果使用apyspark.sql.DataFrame代替pandas.DataFrame,类型提示似乎不会触发警告,反之亦然。例如以下代码根本不会生成任何警告:frompyspark.sqlimportDataFrameasSparkDataFramefrompandasimportDataFrameasPandasDataFramedef......
  • 如何在Python中继承类型提示?
    所以我的问题是,当我有一个A类型的类来做事情并且我使用这些函数作为subclass(B)时,它们仍然是类A的类型,并且不接受我的类B对象作为参数或作为函数签名。我的问题简化了:fromtypingimportTypeVar,Generic,CallableT=TypeVar('T'......
  • Python - 如何传递类对象的函数参数类型(打字)
    我想python3.7附带了(不确定),不仅可以将变量名传递给函数,还可以传递变量的类型。我想知道的是是否有可能传递特定类的类型。以同样的方式传递:deffoo_func(i:int)->None:pass如果我有一个类,让我们说:classfoo_class(object):pass我如何转换fo......
  • Opencv学习项目4——手部跟踪
    主要是使用opencv和mediapipe库来实现手部跟踪,首先我们先介绍一下mediapipe库mediapipe库介绍MediaPipe是一个由Google开发的开源框架,用于构建基于机器学习的应用程序,特别是涉及实时数据处理和传感的应用。它提供了一套工具和库,使开发者可以轻松地构建复杂的多媒体处理......
  • 使用 Python 构建简单 REST API
    使用Python构建简单RESTAPI1.概述本技术文档旨在指导开发者使用Python框架Flask构建一个基本的RESTAPI。通过学习本指南,您将掌握创建、读取、更新和删除(CRUD)操作的基本知识,并能够使用Python构建自己的API。2.安装依赖首先,您需要确保已安装Python和Flask......
  • Python——Pandas(第二讲)
    文章目录变量类型的转换Pandas支持的数据类型在不同数据类型间转换建立索引新建数据框时建立索引读入数据时建立索引指定某列为索引列将索引还原变量列引用和修改索引引用索引修改索引修改索引名修改索引值更新索引Series的索引和切片DataFrame的索引和切片选择列按......
  • 基于Python+Django的红色文化研学网站设计与实现
    ......
  • 【python】对网站进行请求-初识
    python实现对网站进行请求代码如下importrequestsdefget_data(url,headers=None,params=None,timeout=10):try:res=requests.get(url,headers=headers,params=params,timeout=timeout)res.raise_for_status()returnres.text......
  • 【python】Django初识-从未有如此美妙的开局
    Django初识python、Django安装与验证python安装Python官网https://www.python.org/Django安装pipinstallDjango验证python是否安装成功python--version验证Django是否安装成功python3-mdjango--version创建第一个Django项目项目创建与服务器启动打开cmd,输......