在opencv中检测罐子或瓶子

Posted

技术标签:

【中文标题】在opencv中检测罐子或瓶子【英文标题】:Detecting a can or bottle in opencv 【发布时间】:2014-06-04 08:21:06 【问题描述】:

我是 OpenCV 新手,有几个问题。我需要根据形状检测瓶子或罐子。为此,我正在使用树莓派板和 pi 相机。背景总是黑色的,不会改变。我已经尝试了许多可能的解决方案来解决这个问题,但都没有得到令人满意的结果。我尝试过的东西包括边缘检测、形态变换、matchShapes()、matchTemplate()。请让我知道我是否可以高效且准确地完成这项任务。

示例图片:

【问题讨论】:

那么场景中不会有任何物体,除了瓶子? 在给定时间除了瓶子或罐子之外不会有任何物体。 然后申请低值binary invert threshold,获取前景。 如何确定阈值?如何将其与标准罐头尺寸和形状进行比较? 您可以将阈值设置得非常低,因为您的背景始终为黑色,另请参阅答案here 和here,了解如何将其与标准罐的尺寸和形状进行比较。 【参考方案1】:

我想出了一个可能有帮助的方法!如果您对罐子有更多了解,即宽高比,则可以通过调整矩形大小来使其更健壮!

接近

将图像转换为HSV 色彩空间。将 V 增加 2 倍,以获得更多可见的东西。 在xy 方向查找Sobel 导数。计算两个方向的权重相等的幅度。 使用Otsu 方法对图像设置阈值。 将Closing 应用于您的图像。 应用Canny边缘检测器。 找到Hough Line Transform。 查找线条图像的边界矩形。 将其叠加到您的图像上。(终于完成了:P)

代码

image = cv2.imread('image3.jpg', cv2.IMREAD_COLOR)
original = np.copy(image)
if image is None:
    print 'Can not read/find the image.'
    exit(-1)

hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
H,S,V = hsv_image[:,:,0], hsv_image[:,:,1], hsv_image[:,:,2]
V = V * 2

hsv_image = cv2.merge([H,S,V])
image = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2RGB)
image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
# plt.figure(), plt.imshow(image)

Dx = cv2.Sobel(image,cv2.CV_8UC1,1,0)
Dy = cv2.Sobel(image,cv2.CV_8UC1,0,1)
M = cv2.addWeighted(Dx, 1, Dy,1,0)

# plt.subplot(1,3,1), plt.imshow(Dx, 'gray'), plt.title('Dx')
# plt.subplot(1,3,2), plt.imshow(Dy, 'gray'), plt.title('Dy')
# plt.subplot(1,3,3), plt.imshow(M, 'gray'), plt.title('Magnitude')

ret, binary = cv2.threshold(M,10,255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# plt.figure(), plt.imshow(binary, 'gray')

binary = binary.astype(np.uint8)
binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (20, 20)))
edges = cv2.Canny(binary, 50, 100)
# plt.figure(), plt.imshow(edges, 'gray')

lines = cv2.HoughLinesP(edges,1,3.14/180,50,20,10)[0]
output = np.zeros_like(M, dtype=np.uint8)
for line in lines:
    cv2.line(output,(line[0],line[1]), (line[2], line[3]), (100,200,50), thickness=2)
# plt.figure(), plt.imshow(output, 'gray')

points = np.array([np.transpose(np.where(output != 0))], dtype=np.float32)
rect = cv2.boundingRect(points)
cv2.rectangle(original,(rect[1],rect[0]), (rect[1]+rect[3], rect[0]+rect[2]),(255,255,255),thickness=2)
original = cv2.cvtColor(original,cv2.COLOR_BGR2RGB)
plt.figure(), plt.imshow(original,'gray')


plt.show()

注意:您可以取消注释显示每个步骤的结果的行!为了可读性,我只是对它们进行评论。

结果

注意:如果您知道罐子的纵横比,您可以更好地解决它!

我希望这会有所帮助。祝你好运:)

【讨论】:

非常感谢您的评论。我想我可以计算出罐子或瓶子的纵横比。我应该将矩形的高度和宽度与标准罐头尺寸进行比较。

以上是关于在opencv中检测罐子或瓶子的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV - 检测矩形或五边形

使用 OpenCV 和 Keras 进行人脸比较(不是识别或检测)?

OpenCV基础(11)基于OpenCV的边缘检测

使用 OpenCV 检测手

zbar+opencv检测图片中的二维码或条形码

从一组图像中检测明显不同的图像,例如使用 OpenCV 或 SimpleCV