这是对于 OpenCV 官方文档中 图像处理 的学习笔记。学习笔记中会记录官方给出的例子,也会给出自己根据官方的例子完成的更改代码,同样彩蛋的实现也会结合多个知识点一起实现一些小功能,来帮助我们对学会的知识点进行结合应用。
如果有喜欢我笔记的请麻烦帮我关注、点赞、评论。谢谢诸位。
学习笔记:
学习笔记目录里面会收录我关于OpenCV系列学习笔记博文,大家如果有什么不懂的可以通过阅读我的学习笔记进行学习。
【OpenCV学习笔记】- 学习笔记目录
内容
- 了解什么是轮廓。
- 学习寻找轮廓、绘制轮廓等
- 您将看到这些函数:cv2.findContours() 、cv2.drawContours()
什么是轮廓?
轮廓可以简单地解释为连接所有连续点(沿着边界)的曲线,具有相同的颜色或强度。轮廓是形状分析以及物体检测和识别的有用工具。
- 为了获得更高的准确性,请使用二值图像。因此,在找到轮廓之前,请应用阈值或精明的边缘检测。
- 从 OpenCV 3.2 开始,findContours()不再修改源图像。
- 在 OpenCV 中,寻找轮廓就像从黑色背景中寻找白色物体。所以请记住,要找到的对象应该是白色的,背景应该是黑色的。
让我们看看如何找到二值图像的轮廓:
示例代码:
# OpenCV中的轮廓
# 轮廓:开始
# 什么是轮廓?
import cv2
im = cv2.imread('')
assert im is not None, "file could not be read, check with os.path.exists()"
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
我们可以看到 *cv2.findContours()* 函数中有三个参数,第一个是源图像,第二个是轮廓检索模式,第三个是轮廓近似方法。它输出轮廓和层次结构。Contours 是图像中所有轮廓的 Python 列表。每个单独的轮廓都是对象边界点的 (x,y) 坐标的 Numpy 数组。
笔记
稍后我们将详细讨论第二个和第三个参数以及层次结构。在那之前,代码示例中赋予它们的值将适用于所有图像。
如何绘制轮廓?
要绘制轮廓,使用 cv2.drawContours 函数。只要有边界点,它也可用于绘制任何形状。它的第一个参数是源图像,第二个参数是作为 Python 列表传递的轮廓,第三个参数是轮廓索引(在绘制单个轮廓时很有用。要绘制所有轮廓,请传递 -1),其余参数是颜色、厚度ETC。
- 要绘制图像中的所有轮廓:
cv2.drawContours(img, contours, -1, (0,255,0), 3)
- 要绘制单个轮廓,请说第四个轮廓:
cv2.drawContours(img, contours, 3, (0,255,0), 3)
- 但大多数时候,下面的方法会很有用:
cnt = contours[4]
cv2.drawContours(img, [cnt], 0, (0,255,0), 3)
笔记
最后两种方法是相同的,但是当你继续前进时,你会发现最后一种更有用。
轮廓近似法
这是 cv2.findContours 函数中的第三个参数。它实际上代表什么?
上面我们说过,轮廓是具有相同强度的形状的边界。它存储形状边界的 (x,y) 坐标。但它存储了所有坐标吗?这是由该轮廓近似方法指定的。
如果传递 cv2.CHAIN_APPROX_NONE ,则存储所有边界点。但实际上我们需要所有的点吗?例如,您找到了一条直线的轮廓。您需要直线上的所有点来表示该直线吗?不,我们只需要该线的两个端点。这就是 cv2.CHAIN_APPROX_SIMPLE 的作用。它删除所有冗余点并压缩轮廓,从而节省内存。
下面的矩形图像演示了这种技术。只需在轮廓数组中的所有坐标上画一个圆(以蓝色绘制)。第一张图显示了我使用 cv2.CHAIN_APPROX_NONE 得到的点(734 点),第二张图显示了我使用 cv2.CHAIN_APPROX_SIMPLE 得到的点(仅 4 点)。看看,它节省了多少内存!
示例代码:
# OpenCV中的轮廓
# 轮廓:开始
# 轮廓近似法
import cv2
im = cv2.imread('../image/3.9.1.png')
assert im is not None, "file could not be read, check with os.path.exists()"
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
contours1, hierarchy1 = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
contours2, hierarchy2 = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
im2 = im.copy()
for contour in contours1[0]:
cv2.circle(im, contour[0], 1, (255, 0, 0), -1)
for contour in contours2[0]:
cv2.circle(im2, contour[0], 2, (255, 0, 0), -1)
cv2.imshow("im", im)
cv2.waitKey(0)
cv2.imshow("im2", im2)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果图: