处理OpenCV 2.4中的轮廓和边界矩形 - python 2.7

Gia*_*fra 19 opencv image-processing python-2.7 opencv-contour

我正在使用openCv和python,我正在处理结构分析和形状描述符.我找到了这个博客:http://opencvpython.blogspot.it/2012/06/contours-2-brotherhood.html 这是非常有帮助的,我尝试用黑白图像绘制一个边界矩形,它的工作原理.但是现在从我提取的图像,例如,黄色和我想要绘制一个边界矩形.问题是黑白图像不均匀,有一些噪音,而且代码不能识别整个形状.

原始图像

黑白图像

最终形象

这是代码:

import numpy as np
import cv2

im = cv2.imread('shot.bmp')
hsv_img = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
COLOR_MIN = np.array([20, 80, 80],np.uint8)
COLOR_MAX = np.array([40, 255, 255],np.uint8)
frame_threshed = cv2.inRange(hsv_img, COLOR_MIN, COLOR_MAX)
imgray = frame_threshed
ret,thresh = cv2.threshold(frame_threshed,127,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnt=contours[0]
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("Show",im)
cv2.waitKey()
cv2.destroyAllWindows()
Run Code Online (Sandbox Code Playgroud)

Aur*_*ius 38

由于您的原始图像相当嘈杂,因此使用cv2.medianBlur()此功能可以消除原始图像中的小噪声区域,并且只留下一个轮廓.代码的前几行如下所示:

im = cv2.imread('shot.bmp')
im = cv2.medianBlur(im,5)    # 5 is a fairly small kernel size
hsv_img = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
Run Code Online (Sandbox Code Playgroud)

但是,此方法并不是最强大的,因为您必须手动指定内核大小,并且cnt=contours[0]代码中的行假定感兴趣的轮廓是轮廓列表中的第1个,只有在只有一个轮廓时才会出现这种情况.更稳健的方法是假设您对最大轮廓感兴趣,这将允许您补偿甚至适度的噪音.

为此,请添加以下行:

# Find the index of the largest contour
areas = [cv2.contourArea(c) for c in contours]
max_index = np.argmax(areas)
cnt=contours[max_index]
Run Code Online (Sandbox Code Playgroud)

行后:

contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
Run Code Online (Sandbox Code Playgroud)

导致此代码:

import numpy as np
import cv2

im = cv2.imread('shot.bmp')
hsv_img = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
COLOR_MIN = np.array([20, 80, 80],np.uint8)
COLOR_MAX = np.array([40, 255, 255],np.uint8)
frame_threshed = cv2.inRange(hsv_img, COLOR_MIN, COLOR_MAX)
imgray = frame_threshed
ret,thresh = cv2.threshold(frame_threshed,127,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

# Find the index of the largest contour
areas = [cv2.contourArea(c) for c in contours]
max_index = np.argmax(areas)
cnt=contours[max_index]

x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("Show",im)
cv2.waitKey()
cv2.destroyAllWindows()
Run Code Online (Sandbox Code Playgroud)

这两种方法都给出了一个带有正确边界框的结果:

边界框结果

NB
作为OpenCV3.X的findContours()方法返回3个结果(可以看出这里),因此额外的返回值应该抓住这样的:

_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPL??E)
Run Code Online (Sandbox Code Playgroud)

  • `_,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)`应该是新的语法,万一有人遇到报告的错误:`如果你使用opencv 3,那么解压的值太多了`和python 3.参见参考:/sf/ask/1785347511/ (2认同)
  • 我认为 @Puriney 的评论非常重要,因为 SO 中还有其他几个问题源于这个问题。应该编辑问题以包括这样 (2认同)