一、简介
OpenCV是一个强大且流行的计算机视觉库,广泛应用于各种领域,如机器人、安防、自动驾驶、医疗等。OpenCV提供了许多函数和算法来处理图像和视频的问题,而轮廓检测是其中之一。轮廓是由图像中的连续点组成的曲线,其表示了这个物体的边界。轮廓检测可以在计算机视觉领域中起到非常重要的作用,例如图像分割、物体识别、运动跟踪、手势识别等。
二、基本函数
OpenCV提供了许多轮廓检测的函数,其中最常用的函数是findContours()。该函数可用于在二进制图像中找到所有的轮廓。该函数返回的结果是一组点的列表,每个列表代表一个轮廓。在使用findContours()函数之前,我们需要将图像转换为二进制图像,即使得背景为黑色,物体为白色的图像。接下来是 findContours()函数的基本使用:
import cv2 img = cv2.imread('image.tif') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(img, contours, -1, (0,0,255), 3) cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows()
以上代码展示了如何使用findContours()函数来检测图像的轮廓。首先读入一张图像,将其转换为灰度图像,然后将灰度图像转换为二进制图像。接着使用findContours()函数找到图像中所有的轮廓,绘制出所有轮廓,并将结果打印出来。
三、检测模式
1. RETR_EXTERNAL
该模式只检测最外层的轮廓,忽略不在外部的轮廓。
img = cv2.imread('image.tif') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(img, contours, -1, (0,0,255), 3) cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows()
2. RETR_TREE
该模式会检测所有的轮廓,并且将其组合成一个树形结构,每个轮廓都有一个父轮廓和子轮廓。
img = cv2.imread('image.tif') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for i in range(len(contours)): if hierarchy[0][i][3] == -1: cv2.drawContours(img, contours, i, (0, 255, 0), 2) cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows()
以上代码展示了如何使用RETR_TREE模式检测图像的轮廓,并展示了如何访问轮廓的层次结构。
四、逼近方法
逼近方法是指我们可以用一条直线或一个多边形来逼近一个轮廓。这对于降低计算量和压缩数据是非常有用的。OpenCV提供了多种逼近方法,包括:
- cv2.CHAIN_APPROX_NONE:存储所有的边界点
- cv2.CHAIN_APPROX_SIMPLE:只存储拐角点
- cv2.CHAIN_APPROX_TC89_L1
- cv2.CHAIN_APPROX_TC89_KCOS
1. cv2.CHAIN_APPROX_NONE
使用cv2.CHAIN_APPROX_NONE模式,可以检测出图像的所有轮廓点。下面是代码示例:
img = cv2.imread('image.tif') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) for cnt in contours: cv2.drawContours(img, [cnt], 0, (0,255,0), 3) cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows()
2. cv2.CHAIN_APPROX_SIMPLE
使用cv2.CHAIN_APPROX_SIMPLE模式,只保存重要的拐角点,可以大大减小存储空间。下面是代码示例:
img = cv2.imread('image.tif') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: cv2.drawContours(img, [cnt], 0, (0,255,0), 3) cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows()
3. cv2.approxPolyDP()
除了cv2.CHAIN_APPROX_SIMPLE以外,我们还可以使用cv2.approxPolyDP()函数对轮廓进行逼近。该函数会将轮廓逼近为一条直线或一组多边形。下面是代码示例:
img = cv2.imread('image.tif') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) for cnt in contours: epsilon = 0.01 * cv2.arcLength(cnt, True) approx = cv2.approxPolyDP(cnt, epsilon, True) cv2.drawContours(img, [approx], 0, (0,255,0), 3) cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows()
五、结论
本文详细介绍了OpenCV轮廓检测的基本函数、检测模式和逼近方法。轮廓检测是计算机视觉中常用的技术之一,可以用于图像分割、物体识别、运动跟踪、手势识别等。通过本文的介绍,读者可以掌握OpenCV轮廓检测的基本原理和常用方法,为计算机视觉的研究和应用提供帮助。