如何在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 cv2
#加载输入图像
img = cv2.imread('six-point-star.png')
#将输入图像转换为灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#应用阈值处理将灰度转换为二进制图像
ret,thresh = cv2.threshold(img1,150,255,0)
#查找轮廓
contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print("检测到的轮廓数:", len(contours))
#选择第一个轮廓
cnt = contours[0]
#使用轮廓查找凸包
hull = cv2.convexHull(cnt)
#在输入图像上绘制轮廓和凸包
img = cv2.drawContours(img,[cnt],0,(255,0,0),2)
img = cv2.drawContours(img,[hull],0,(0,255,255),3)
#显示绘制了轮廓和凸包的图像
cv2.imshow("凸包", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
我们将使用以下图像作为 输入文件 在上面的程序代码中。
输出
当执行上述代码时,将会产生以下输出 **** −
检测到的轮廓数: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("检测到的轮廓数量:", len(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)
# 在图像上显示凸包
cv2.imshow("凸包", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
我们将使用这张图片作为 输入文件 在这个程序中 −
输出
当你运行上述代码时,它会产生下面的 输出 −
检测到的轮廓数量: 3
我们得到以下的 输出窗口 ,显示在图像中检测到的轮廓和凸包 −
凸包用红色表示,轮廓用绿色表示。注意轮廓和凸包之间的差异。