【问题标题】:How to segment a batch of beans for neural network如何为神经网络分割一批豆子
【发布时间】:2021-06-25 07:40:54
【问题描述】:

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

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

我尝试使用 openCV 中的距离变换和分水岭算法,如前所述,这仅适用于单个 bean 和 bean 之间的一些小重叠(就像在this example 中一样)。下图为结果:results of single layer segmentation

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

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()

但是当有这样的图片时问题就开始了(这是一个真实的情况):multi layer segmentation harder multi layer segmentation

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

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

【问题讨论】:

  • 欢迎来到 Stackoverflow。据我了解您的问题,该代码不会产生任何错误。相反,它的性能不如您预期。如果是这种情况,我建议您阅读有关图像分割算法的信息。如果您有大型标记数据集,您可能想尝试一些机器学习。
  • @Molitoris 感谢您的回复。实际上,代码对于排列良好的 bean 是正确的,但在有多个未排序的 bean 层时就不行了。我用当前代码尝试了所有不同类型的设置,但到目前为止还没有成功。这就是为什么我认为会有不同的方法,我不知道。我已经尝试了来自 scikit 的大多数监督分割问题。不幸的是,没有时间(阅读:值得投资)注释 1000 张照片以使用机器学习进行自动分割。
  • 我了解到您已经尝试了很多传统的图像分割算法。我不确定我能否在这个方向上为您提供帮助。你有没有想过迁移学习。有很多用于图像分割的预训练模型。他们可能没有接受过豆类方面的培训。但是,一小部分分段的 bean 图像可能足以针对您的问题训练其中一个模型。
  • 在将难以分割的图像传递给您的 NN 时,您是否识别出任何 bean?你在用这种困难的图像训练神经网络吗?您使用的是哪种 NN 架构?有监督还是无监督?
  • @AmoRobb 感谢您的回复。我在单个 bean 上训练了我的 NN,在这种情况下,这不是问题。我使用豆类的第一张图片作为收集数据的方法。通过在 bean 周围绘制和切片边界框并将其用作我的 NN 的数据。问题是我也想在更难分割的图像上这样做。也可以裁剪图像,使其适合其中的一颗豆子。但到目前为止,分割仍然是问题......

标签: python opencv vision watershed


【解决方案1】:

如果我理解正确,您只需要一些图像分割方法将豆子从一张大图片中分离成许多小图片,其中只有一个豆子,这样您就可以将它们提供给您的 NN 进行训练/测试。

对于你展示的那种图片,分割本身几乎就是一种识别。我的意思是,你几乎需要一个训练有素的神经网络来识别图片中的豆子,然后将它们分开并将它们输入你的非训练神经网络。

对于这类问题,我相信有一些 NN 架构(无监督)经过训练可以为您提取相关特征。我认为自动编码器是其中一种选择,但我现在不确定。

另一种方法是使用某种更通用的模式识别:

a) 基于形状:他们尝试在梯度图像上匹配轮廓模型

b) Correlation-Based: 他们尝试使用灰度相关性在原始图像上匹配示例图像

这些方法使用金字塔搜索来提高速度,但您可能还想为要分析的图像的每个金字塔级别尝试模型的不同金字塔级别,以应对颗粒的不同缩放,这相当于一个匹配方法缩放。您还需要多个 bean 模型(单个 bean 的不同视角)来增加每个图像的结果数量。

您也可以尝试c)区域扩展方法在某些条件下基于颜色平滑度将种子区域扩展到相邻像素,或d)结合一些边界查找器轮廓闭合算法;但我担心它们会根据您的图像可变性给您带来很多问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 2015-07-10
    • 2019-08-17
    • 2019-07-17
    • 2018-07-05
    • 2016-05-01
    • 1970-01-01
    相关资源
    最近更新 更多