Detecting a can or bottle in opencv
我刚接触OpenCV,有几个问题。我需要根据瓶子或罐子的形状来检测它们。为此,我使用树莓圆板和圆周率照相机。背景总是黑色的,不会改变。我试过许多可能的解决办法,但都没有得到满意的结果。我尝试过的内容包括边缘检测、形态转换、matchshapes()、matchtemplate()。请告诉我,如果我能有效地和最大的准确性完成这项任务。
样本图像:
我想出了一个可能有帮助的办法!如果你知道更多关于罐子的事情,例如宽高比,通过调整矩形的大小,它可以更强大!
途径
- 将图像转换为hsv颜色空间。将
V 增加2倍,以便有更多可见的东西。 - 在
x 和y 方向找到sobel衍生物。计算两个方向的等重量级。 - 使用otsu方法设置图像阈值。
- 对图像应用关闭。
- 使用Canny边缘探测器。
- 找到霍夫线变换。
- 找到线条图像的边框。
- 把它叠加到你的图像上。(最后完成:p)
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 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() |
注意:您可以取消对显示每个步骤结果的行的注释!我只是为了可读性而评论它们。
结果
注:如果你知道你的长宽比,你可以更好地修复它!
我希望这会有所帮助。祝你好运: