OpenCV 形状分析(上):计算轮廓中心
admin
2023-07-31 00:45:56
0

5

今天,我们将开始由3部分构成的形状检测分析系列教程。

通过此系列教程,我们将学到如何:

  1. 计算轮廓/形状的中心;
  2. 仅使用轮廓特征识别出不同的形状,如:圆、正方形、长方形、三角形和五角形。
  3. 标记形状颜色

尽管今天的内容比较基础(相对于最近 PyImageSearch 博客讨论的更加高级的概念来说),但是也经常有人问我下边这个问题:

如何用 Python 和 OpenCV 计算轮廓的中心?

在今天的教程中,我将会回答这个问题。

在以后的教程中,我们将在轮廓知识的基础上进行图像的形状识别。

使用 OpenCV 计算轮廓中心

包含不同形状的待计算轮廓中心的示例图

图1:包含不同形状的待计算轮廓中心的示例图像

从上图中,你能看见几种不同的由图画纸裁出的形状。注意,这些形状并不完美——矩形不够方,圆形不够圆。它们都是先经手工描画然后再裁出来的,这意味着每种形状都存在着偏差。

明确了这一点之后,今天教程的目标是:(1)检测出图像中的每一种形状的轮廓(2)计算轮廓的中心——也叫形心。

为了达成以上目标,我们需要对图像进行以下预处理:

  • 转换成灰度图;
  • 滤波以减少高频噪声,使轮廓检测更加精确;
  • 图像二值化。边缘检测和阈值化经常被用于此过程,本教程采用阈值化。

开始写代码之前,请确保你的系统已经安装了 imutils Python 包[ 译注:该包为作者开发的一系列用 OpenCV 执行基本图像处理操作的简便函数]。

1 $ pip install imutils

让我们继续!

新建一个文件,命名为 center_of_shape.py,然后开始写代码吧:

1234567891011121314151617 # import the necessary packagesimport argparseimport imutilsimport cv2 # construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument(\”-i\”, \”–image\”, required=True,    help=\”path to the input image\”)args = vars(ap.parse_args()) # load the image, convert it to grayscale, blur it slightly,# and threshold itimage = cv2.imread(args[\”image\”])gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)blurred = cv2.GaussianBlur(gray, (5, 5), 0)thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1]

第2-4行代码导入必需的包,第7-10行代码解析命令行参数。此处只需要一个 --image 参数: 磁盘中待处理图像的路径。

随后程序从磁盘加载图像,然后进行预处理,执行灰度变换,5×5 内核的高斯平滑,最后阈值化(14-17行)。

阈值化操作后的输出如下图所示

图2:阈值化图像操作返回二值图像,其中形状被表示为黑色背景上的白块

图2:图像阈值化返回二值图像,其中形状被表示为黑色背景上的白块

注意阈值化后形状被表示成黑色背景上的白色前景。

下一步是使用轮廓检测去定位这些白色区域。

12345678910111213141516171819202122 # import the necessary packagesimport argparseimport imutilsimport cv2 # construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument(\”-i\”, \”–image\”, required=True, help=\”path to the input image\”)args = vars(ap.parse_args()) # load the image, convert it to grayscale, blur it slightly,# and threshold itimage = cv2.imread(args[\”image\”])gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)blurred = cv2.GaussianBlur(gray, (5, 5), 0)thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1] # find contours in the thresholded imagecnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cnts = cnts[0] if imutils.is_cv2() else cnts[1]

第 20-21 行代码调用 cv2.findContours 函数,该函数返回图像上每一个白块对应的边界点集合(即轮廓)。第22行基于我们使用 OpenCV 2.4 版本还是3.0 版本而取不同的元组值。获取更多 cv2.findContours 函数返回签名在不同 OpenCV 版本间的改变,请移步此文。[译注:OpenCV 2.4 版本的 cv2.findContours 函数返回的是一个二元元组,元组的第一个元素(索引 0)是轮廓列表。而在 OpenCV 3.0 版本中,该函数返回的是一个三元元组,元组的第二个元素(索引 1)才是轮廓列表]

我们已经准备去处理每一条轮廓:

123456789101112131415161718192021222324252627282930313233343536373839 # import the necessary packagesimport argparseimport imutilsimport cv2 # construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument(\”-i\”, \”–image\”, required=True, help=\”path to the input image\”)args = vars(ap.parse_args()) # load the image, convert it to grayscale, blur it slightly,# and threshold itimage = cv2.imread(args[\”image\”])gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)blurred = cv2.GaussianBlur(gray, (5, 5), 0)thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1] # find contours in the thresholded imagecnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cnts = cnts[0] if imutils.is_cv2() else cnts[1] # loop over the contoursfor c in cnts: # compute the center of the contour M = cv2.moments(c) cX = int(M[\”m10\”] / M[\”m00\”]) cY = int(M[\”m01\”] / M[\”m00\”])  # draw the contour and center of the shape on the image cv2.drawContours(image, [c], 1, (0, 255, 0), 2) cv2.circle(image, (cX, cY), 7, (255, 255, 255), 1) cv2.putText(image, \”center\”, (cX 20, cY 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)  # show the image cv2.imshow(\”Image\”, image) cv2.waitKey(0)

第25行开始遍历轮廓,然后在第27行计算轮廓区域图像的矩。

在计算机视觉和图像处理领域,图像的矩经常被用来描述图像中某个对象的形状。这些矩描述了形状的基本统计特征,包括对象的面积、形心(即对象的中心坐标 (x, y))、取向连同其他有用的特征。

我们只对图像的中心感兴趣,所以在第28-29行计算轮廓的中心。

随后,第32-34行完成以下任务:

  • 调用 cv2.drawContours 函数绘制包围当前形状的轮廓;
  • 在形状的中心 (cX, cY) 处绘制一个白色的小圆;
  • 在白色小圆的附近写上文字 center

要执行脚本,打开终端然后执行以下命令:

1 $ python center_of_shape.py image shapes_and_colors.png

运行结果如下图所示:

图3:

图3:分别遍历每一个形状并计算每一个形状的中心 (x, y)。(点击图片有惊醒)

注意每一个形状都被成功地检测到,然后计算出轮廓中心并绘制在图像上。

总结

在这次教程中,我们学习了如何使用 OpenCV 和 Python 去计算轮廓的中心。

此教程是由三部分构成的形状分析系列教程的第一部分。

在下周的教程中,我们将学习如何识别图像中的形状

然后,在两周以后,我们将学习如何分析每一个形状的颜色并将其标记在形状上(即标记“红”、“绿”、“蓝”等等)。

为了确保这些教程写成的时候您能被通知到,请按照以下形式输入您的邮箱地址![译注:原博客提供代码下载和邮件提醒功能。戳我访问原文。]

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...