如何在OpenCV Python中查找和绘制图像轮廓的凸包?


凸包看起来类似于轮廓逼近,但它并非完全是轮廓逼近。凸包是围绕物体的凸曲线。凸曲线总是凸出的,或者至少是平的。凸包查找凸性缺陷并对其进行修正。

语法

要查找凸包,我们使用以下函数:

hull = cv2.convexHull(cnt, hull, clockwise, returnPoints)

参数

  • cnt是轮廓点。它表示为轮廓点的数组。

  • hull是输出,通常我们避免使用它。

  • clockwise – 方向标志。如果为True,则输出凸包的方向为顺时针方向,否则为逆时针方向。

  • returnPoints – 默认设置为True。

输出 – 当returnPoints设置为True时,它返回凸包点的坐标。如果设置为False,则返回对应于凸包点的轮廓点的索引。

因此,为了获得凸包,我们通常使用以下方法:

hull = cv2.convexHull(cnt)

要绘制凸包点的轮廓,请使用此函数:

cv2.drawContours(img, [hull], -1, (0,255,255), 3)

步骤

您可以使用以下步骤查找并绘制图像轮廓的凸包:

导入所需的库。在所有以下Python示例中,所需的Python库是OpenCV。确保您已经安装了它。

import cv2

使用cv2.imread()读取输入图像并将其转换为灰度图像。

img = cv2.imread('shape.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

对灰度图像应用阈值处理以创建二值图像。

ret,thresh = cv2.threshold(gray,150,255,0)

使用cv2.findContours()函数查找图像中的轮廓。

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

选择轮廓cnt或循环遍历所有轮廓。使用cv2.convexHull(cnt)函数查找轮廓cnt的凸包。

cnt = contours[0]
hull = cv2.convexHull(cnt)

将凸包点传递给以下函数,在输入图像上绘制凸包。

cv2.drawContours(img, [hull], -1, (0,255,255), 3)

显示绘制了凸包的图像。

cv2.imshow("Convex Hull", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

让我们来看一些例子以便更好地理解。

示例1

在下面的Python程序中,我们检测图像中的轮廓并查找第一个轮廓的凸包。我们还在图像上绘制第一个轮廓和凸包。

# import required libraries import cv2 # load the input image img = cv2.imread('six-point-star.png') # convert the input image to grayscale gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # apply thresholding to convert grayscale to binary image ret,thresh = cv2.threshold(img1,150,255,0) # find the contours contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) print("Number of contours detected:", len(contours)) # select the first contour cnt = contours[0] # find the convex hull using the contour hull = cv2.convexHull(cnt) # draw contour and convex hull on the input image img = cv2.drawContours(img,[cnt],0,(255,0,0),2) img = cv2.drawContours(img,[hull],0,(0,255,255),3) # display the image with drawn contour and convex hull cv2.imshow("Convex Hull", img) cv2.waitKey(0) cv2.destroyAllWindows()

我们将在上面的程序代码中使用以下图像作为输入文件

输出

执行上述代码后,将产生以下输出

Number of contours detected: 1

我们将得到以下输出窗口,显示图像中检测到的第一个轮廓和凸包:

轮廓以蓝色绘制,凸包以黄色绘制。注意轮廓和凸包之间的区别。

示例2

在这个例子中,我们检测图像中的轮廓并查找所有轮廓的凸包。我们还在图像上绘制所有轮廓和凸包。

import cv2 img = cv2.imread('convexhull.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(gray,100,255,0) contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) print("Number of contours detected:", len(contours)) # Find the convex hull for all the contours for cnt in contours: hull = cv2.convexHull(cnt) img = cv2.drawContours(img,[cnt],0,(0,255,0),2) img = cv2.drawContours(img,[hull],0,(0,0,255),3) # Display the image with convex hull drawn on it cv2.imshow("Convex Hull", img) cv2.waitKey(0) cv2.destroyAllWindows()

我们将在本程序中使用此图像作为输入文件

输出

执行上述代码后,将产生以下输出

Number of contours detected: 3

我们将得到以下输出窗口,显示图像中检测到的轮廓和凸包:

凸包以红色显示,轮廓以绿色显示。注意轮廓和凸包之间的区别。

更新于:2022年9月28日

4K+ 次浏览

启动您的职业生涯

通过完成课程获得认证

开始学习
广告