如何在 OpenCV Python 中查找和绘制图像轮廓的凸包?
凸包看起来类似于轮廓近似,但它并不完全是轮廓近似。凸包是物体周围的凸曲线。凸曲线总是凸起的,或者至少是平坦的。凸包会找到凸性缺陷并进行纠正。
语法
要找到凸包,我们使用以下函数 -
hull = cv2.convexHull(cnt, hull, clock, returnPoints)
参数
cnt 是轮廓点。它表示为轮廓点数组。
hull 是输出,通常我们会避免使用它。
chronological − 方向标志。如果为 True,则输出凸包为顺时针方向,否则为逆时针方向。
returnPoints − 默认设置为 True。
输出 − 当 returnPoints 设置为 True 时,它会返回 hull 点的坐标。如果设置为 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)
在输入图像上绘制凸包,并将 hull 点传递给以下函数。
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
我们得到以下输出窗口,显示图像中检测到的轮廓和凸包-
凸包显示在红色表示轮廓,绿色表示轮廓。注意轮廓和凸包之间的区别。