问题描述
我遇到了一个问题,我想识别混合中的不同咖啡豆。 我创建了一个能够单独识别不同 bean 的神经网络。但在实践中,我想开发一种算法,我可以在更大的批次中检测这些 bean。没有必要识别图片中的所有豆子,但是当我能够识别出更大批次的 10-15 个豆子时,这就足够了。
现在的问题是,当只有一层具有对比背景的豆子时,我能够分割豆子,但是当第一层下面有多层豆子时,这变得非常困难。
我尝试使用距离变换和 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,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,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,iterations=1)
img0[result == 255] = (255,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,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
但是当出现这样的图片时问题就开始了(这是真实情况):multi layer segmentation 和 harder multi layer segmentation
我认为我无法重用前面提到的代码,我需要一种不同的方法。因为第一层和第二层之间的对比度很小,因为豆子很小,所以它们不会产生很大的阴影,这会产生很好的对比,而且豆子的颜色也很暗并没有让它变得更容易。
那么您对解决这个问题的不同方法有什么建议,或者可能调整当前代码来解决我的问题?
我很想听听不同的意见!
解决方法
如果我理解正确,您只需要一些图像分割方法即可将大图片中的豆子分成许多只有一个豆子的小图片,这样您就可以将它们提供给您的神经网络进行训练/测试。
对于你展示的那种图片,分割本身几乎就是一种识别。我的意思是,您几乎需要一个训练有素的神经网络来识别图片中的豆子,然后将它们分开并将它们输入到您未训练的神经网络中。
对于这类问题,我相信有一些 NN 架构(非监督)经过训练可以为您提取相关特征。我认为自动编码器是其中一种选择,但我现在不确定。
另一种方法是使用某种更通用的模式识别:
a) 基于形状:他们尝试在梯度图像上匹配轮廓模型
b) Correlation-Based:他们尝试使用灰度相关性将样本图像与原始图像相匹配
这些方法使用金字塔搜索来提高速度,但您可能还想为图像的每个金字塔级别尝试模型的不同金字塔级别来分析以应对不同缩放的颗粒,这相当于匹配方法缩放。您还需要多个 bean 模型(单个 bean 的不同视角)以增加每个图像的结果数量。
您也可以尝试c) 区域扩展方法,在某些条件下基于颜色平滑度将种子区域扩展到相邻像素,或者 d) 边界查找器结合一些轮廓闭合算法;但我担心它们会根据您的图像可变性给您带来许多问题。