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

时间:2013-05-14 08:49:21

标签: python-2.7 opencv image-processing opencv-contour

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

origianl image

black and white image

final image

这是代码:

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

1 个答案:

答案 0 :(得分:37)

由于原始图像相当嘈杂,因此使用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)

但是,此方法不是最强大的,因为您必须手动指定内核大小,并且代码中的行cnt=contours[0]假定感兴趣的轮廓是轮廓列表中的第1个,这仅是如果只有一个轮廓,则为true。一种更健壮的方法是假设您对最大轮廓感兴趣,这样可以补偿均匀的中等噪声。

为此,请添加以下行:

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

行后:

contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

导致此代码:

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

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

Bounding Box Result

<强> N.B。
OpenCV 3.x开始,findContours()方法返回3个结果(可以看到here),因此应该捕获额外的返回值,如:

_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPL‌​E)