您的位置:

Opencv轮廓提取

一、轮廓提取的概念

图像轮廓是连接具有相同颜色和强度的所有连续点(边缘)的曲线。通过轮廓提取,可以找到图像中的物体边缘或者边缘之间的空隙,从而进行图像分割等一些列操作。

二、轮廓提取基本流程

在Opencv中,轮廓提取的基本流程包括以下几个步骤:

  1. 读入原始图像并进行灰度化处理。
  2. 对灰度图像进行二值化处理。
  3. 进行轮廓发现,得到轮廓点集。
  4. 绘制轮廓线。

下面是一个完整的示例代码:

import cv2

img = cv2.imread('example.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 0, 255), 2)
cv2.imshow('contours', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

三、轮廓的性质

轮廓除了可以用于图像分割,还可以提供很多其他有用的信息,比如:轮廓面积、周长、质心、边界框、最小矩形等。

以下是示例代码:

import cv2

img = cv2.imread('example.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

for i in range(len(contours)):
    area = cv2.contourArea(contours[i])
    arclen = cv2.arcLength(contours[i], True)
    moments = cv2.moments(contours[i])
    cx = int(moments['m10']/moments['m00'])
    cy = int(moments['m01']/moments['m00'])
    rect = cv2.boundingRect(contours[i])
    minRect = cv2.minAreaRect(contours[i])
    box = cv2.boxPoints(minRect)
    box = np.int0(box)

    cv2.drawContours(img, [box], 0, (0, 255, 0), 2)
    cv2.circle(img, (cx, cy), 2, (0, 0, 255), -1)
    cv2.rectangle(img, (rect[0], rect[1]), (rect[0]+rect[2], rect[1]+rect[3]), (255, 0, 0), 2)
    cv2.putText(img, str(i), (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

cv2.imshow('contours', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

四、轮廓的近似

在实际应用中,为了降低轮廓点数,可以对轮廓进行近似处理,得到更加简化的轮廓曲线。常用的方法有:Douglas-Peucker算法和Ramirez-Schafer算法。

openCV提供了approxPolyDP函数进行轮廓近似,函数基本语法如下:

epsilon = cv2.approxPolyDP(curve, epsilon, closed)

其中,curve表示输入轮廓,epsilon为近似精度,closed为一个布尔值,表示曲线是否闭合。

以下是示例代码:

import cv2

img = cv2.imread('example.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

for i in range(len(contours)):
    epsilon = 0.01 * cv2.arcLength(contours[i], True)
    approx = cv2.approxPolyDP(contours[i], epsilon, True)
    cv2.drawContours(img, [approx], 0, (0, 0, 255), 2)

cv2.imshow('contours', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

五、总结

通过本文的介绍,我们可以看到轮廓提取在图像处理中的重要性。在实际应用中,我们可以根据轮廓的性质对物体进行检测、分割、识别等操作。同时,轮廓的近似处理也可以大大减少轮廓点数,提高图像处理效率。