OpenCV:在二进制图像中绘制对象的轮廓

4

我使用Spyder环境中的Python代码来绘制二进制图像中检测到的组件的轮廓,参考了http://docs.opencv.org/trunk/d4/d73/tutorial_py_contours_begin.html提供的示例。以下是我的代码:

im = cv2.imread('test.jpg') #raw RGB image
im2 = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) #gray scale image
plt.imshow(im2,cmap = 'gray')

The image is shown as follows:

enter image description here

Then,

thresh, im_bw = cv2.threshold(im2, 127, 255, cv2.THRESH_BINARY) #im_bw: binary image
im3, contours, hierarchy = cv2.findContours(im_bw,cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(im2, contours, -1, (0,255,0), 3)
plt.imshow(im2,cmap='gray')  #without the code, only an array displayed in the console

这些代码出于某种原因无法给出轮廓图。但如果我将代码的最后两行更改如下:
cv2.drawContours(im, contours, -1, (0,255,0), 3)
plt.imshow(im,cmap='gray')

这段代码产生了一个带轮廓的图形:

enter image description here

我对这些代码如何工作感到困惑?cv2.drawContours只适用于GRB图像吗?希望不是。 此外,需要注意的是contours[0]会产生一个3D数组:

idx = contours[0]
print idx.shape

(392L, 1L, 2L)

idx应该存储所有轮廓点的像素坐标。但是如何解释每个维度表示什么,并从中获取每个轮廓点的像素坐标?然后我就可以使用这些坐标绘制轮廓,而不必使用cv2.drawContours。

2个回答

5
混淆源于这个事实:cv2.findContours仅适用于二进制图像,而cv2.drawContours适用于RGB图像。这就是为什么要绘制轮廓,需要将im2转换为RGB,然后绘制轮廓,再将im2重新转换为二进制(GRAY)。但真正令人困惑的是,结果看起来不像你期望的那样:轮廓像灰色而不是白色(这意味着它们的值在150-170区域内,而不是255)。很容易解决:im2[im2!=0]=255。
im_gray = cv2.imread('test.jpg',0)
im_color=cv2.imread('test.jpg',1)
im3, contours, hierarchy = 
cv2.findContours(im_gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cv2.drawContours(im_color, contours, -1, (0,255,0), 3)
im = cv2.cvtColor(im_color, cv2.COLOR_BGR2GRAY)
# if you plot im now you will see grey contours not white
im[im!=0]=255
# all contours are white now!

3

cv2.findContours和cv2.drawContours都是破坏性方法,它们会修改原始输入图像。后者仅适用于RGB图像进行绘制,这解释了为什么在绘制灰度图像时不显示可见轮廓。

除了cv2.drawContours之外,通过使用存储在“contours”(上面的代码中)中的边界像素的索引,也可以轻松地绘制轮廓。这些索引是通过cv2.findContours获得的。


自OpenCV 3.2版本开始,findContours()不再修改源图像,而是将修改后的图像作为三个返回参数中的第一个返回。 - mluerig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接