OpenCV-35 查找轮廓
一、 什么是图像轮廓
图像轮廓是具有相同颜色或灰度的连续点的曲线,轮廓在形状分析和物体的检测识别中很有用。
- 用于图形分析
- 物体的识别和检测
注意点:
- 为了检测的准确性,需要先对图像进行二值化或Canny操作。
- 画轮廓时会修改输入的图像,如果之后想继续使用原始图像,应该将原始图像储存到其他变量中。(即画轮廓是在原图上进行修改)
二、 查找轮廓
通过使用API --- findContours(img, mode, method[, contours[, hierarchy[, offset]]]])
- mode 查找轮廓的模式
- 其中RETR_EXTERNAL = 0,表示只检测外围轮廓
- RETR_LIST = 1 , 检测的轮廓不建立等级关系,即检测所有轮廓,较为常用。
- RETR_CCOMP = 2,每层最多两级,从小到大,从里到外。
- RETR_TREE = 3, 按照树型存储轮廓,从小到大,从左到右 (最常用)
method :轮廓近似方法,也叫ApproximationMode
- 其中:CHAIN_APPROX_NONE 保存所有轮廓上的点
- CHAIN_APPROX_SIMPLE,只保存角点,比如四边形,只保留四边形的4个角,存储信息少,比较常用。
返回值 contours和hierachy是轮廓和层级
其中轮廓的类型为元组(旧版本为列表)
层级的类型为np的ndarray形式
示例代码如下:
import cv2
import numpy as np
# 导入图片
img = cv2.imread("black.png")
# 变为单通道的黑白照片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化操作 --- 返回两个值:阈值和结果
ret, new_img = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# 查找轮廓
contours, hierarchy = cv2.findContours(new_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 打印轮廓
print(type(contours))
print(type(hierarchy))
print(contours)
print(hierarchy)
cv2.waitKey(0)
cv2.destroyAllWindows()
输出结果如下:
三、 绘制轮廓
通过API --- drawContours(image, contours, contourldx[, thickness[,lineTupe[, hierachy[, maxlevel[,offset]]]])
- image:要绘制的图象
- conyours: 轮廓点
- contourldx:要绘制的轮廓的编号。-1表示绘制所有的轮廓
- color:轮廓的颜色,如(0,0,255)表示红色
- thickness:线宽,-1表示全部填充
示例代码如下:
import cv2
import numpy as np
# 导入图片
img = cv2.imread("black.png")
# 变为单通道的黑白照片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化操作 --- 返回两个值:阈值和结果
ret, new_img = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# 查找轮廓
contours, hierarchy = cv2.findContours(new_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
img_copy = img.copy()
# 直接在img_copy上面操作
cv2.drawContours(img_copy, contours, -1, (0, 0, 255), 2)
cv2.imshow("img", np.hstack((img, img_copy)))
cv2.waitKey(0)
cv2.destroyAllWindows()
输出结果如下:
四、轮廓的面积和周长
轮廓的面积指的是每个轮廓中所有的像素点围成的区域的面积,单位为像素。
轮廓面积是轮廓重要的统计特征之一,通过轮廓面积的大小可以进一步分析每个轮廓隐含的信息, 例如通过轮廓面积区分物体大小识别不同的物体。
在查找到轮廓之后,可能会有很多细小的轮廓,我们可以通过轮廓的面积进行过滤。
计算轮廓面积:contourArea (contour)
计算轮廓周长:arcLength (curve, closed)
- curve : 轮廓
- closed:判断是否为闭合的轮廓
示例代码如下:
import cv2
import numpy as np
# 导入图片
img = cv2.imread("black.png")
# 变为单通道的黑白照片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化操作 --- 返回两个值:阈值和结果
ret, new_img = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# 查找轮廓
contours, hierarchy = cv2.findContours(new_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
img_copy = img.copy()
# 直接在img_copy上面操作
cv2.drawContours(img_copy, contours, -1, (0, 0, 255), 2)
cv2.imshow("img", np.hstack((img, img_copy)))
# 计算轮廓的周长和面积
Area = cv2.contourArea(contours[0])
perimeter = cv2.arcLength(contours[1], closed=True)
print(Area)
print(perimeter)
cv2.waitKey(0)
cv2.destroyAllWindows()
输出结果如下:
其中第一个为面积,第二个为周长。