今天,我将使用 OpenCV 和 Python 根据轮廓查找极值点。
在本博客的其余部分,我将演示如何根据轮廓找到极北、极南、极东和极西 (x, y) 坐标,如本博文顶部的图像所示。
虽然这项技能本身并不是很有用,但它通常用作更高级计算机视觉应用程序的预处理步骤。这种应用程序的一个很好的例子是手势识别:
计
算
沿
手
部
轮
廓
的
极
坐
标
计算沿手部轮廓的极坐标
计算沿手部轮廓的极坐标
在上图中,我们从图像中分割了皮肤/手,计算了手轮廓的凸包(蓝色轮廓),然后沿着凸包找到了极值点(红色圆圈)。
我们的示例图像包含一只手。我们将计算沿手部轮廓的极北、极南、极东和极西 (x, y) 坐标。
我们的目标是计算图像中手部轮廓的极值点。
使用 OpenCV 查找轮廓中的极值点
让我们开始吧。打开一个新文件,命名为extreme_points.py
,然后让我们开始编码:
# 导入必要的包
import imutils
import cv2
# 加载图像,将其转换为灰度,并稍微模糊
image = cv2.imread("hand_01.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
# 对图像设置阈值,然后执行一系列腐蚀 + 膨胀以去除任何小的噪声区域
thresh = cv2.threshold(gray, 45, 255, cv2.THRESH_BINARY)[1]
thresh = cv2.erode(thresh, None, iterations=2)
thresh = cv2.dilate(thresh, None, iterations=2)
# 在阈值图像中找到轮廓,然后获取最大的一个
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = max(cnts, key=cv2.contourArea)
导入我们需要的包。然后我们从磁盘加载我们的示例图像,将其转换为灰度,并稍微模糊它。
执行阈值处理,允许我们从图像的其余部分分割手部区域。阈值处理后,我们的二值图像如下所示:
为了检测手的轮廓,我们调用 cv2.findContours
,然后对轮廓进行排序以找到最大的轮廓,我们假设最大的轮廓是手本身。
在我们根据轮廓找到极值点之前,重要的是要了解轮廓只是(x, y) 坐标的 NumPy 数组。因此,我们可以利用 NumPy 函数来帮助我们找到极值坐标。
# 确定轮廓的极值点
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])
例如,通过对x值调用argmin()
找到整个轮廓c中最小的x坐标并获取与argmin()
返回的索引相关联的整个(x, y)坐标(即最西边的坐标点)。
类似地,使用 argmax()
函数在轮廓c中找到最大的 x 坐标(最东边的坐标点)。
仅针对 y 坐标,执行相同的操作(最南边和最北边的坐标点)。
现在我们有了极北、极南、极东和极西坐标,我们可以在图像上绘制它们:
# 画出物体的轮廓,然后画出每个极值点,最左边是红色,最右边是绿色,最上面是蓝色,最下面是青色
cv2.drawContours(image, [c], -1, (0, 255, 255), 2)
cv2.circle(image, extLeft, 8, (0, 0, 255), -1)
cv2.circle(image, extRight, 8, (0, 255, 0), -1)
cv2.circle(image, extTop, 8, (255, 0, 0), -1)
cv2.circle(image, extBot, 8, (255, 255, 0), -1)
# 显示输出图像
cv2.imshow("Image", image)
cv2.waitKey(0)
以黄色绘制手的轮廓,而为每个极值点绘制圆圈,详述如下:最左边是红色,最右边是绿色,最上面是蓝色,最下面是青色。
最后,将结果显示在我们的屏幕上。
总结
在这篇博文中,我详细介绍了如何沿着给定的轮廓找到极北、极南、极东、极西(x, y)坐标。这种方法既可以用于原始轮廓,也可以用于旋转的包围框。
虽然沿着轮廓寻找极值点本身似乎并不有趣,但它实际上是一项非常有用的技能,尤其是作为更高级的计算机视觉和图像处理算法(如手势识别)的预处理步骤。
参考目录
https://www.pyimagesearch.com/2016/04/11/finding-extreme-points-in-contours-with-opencv/