您的位置:

OpenCV轮廓检测

一、简介

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轮廓检测的基本原理和常用方法,为计算机视觉的研究和应用提供帮助。