OpenCV入门(二十二)快速学会OpenCV 21 图像轮廓

作者:Xiou

边缘检测虽然能够检测出边缘,但边缘是不连续的,检测到的边缘并不是一个整体。图像轮廓是指将边缘连接起来形成的一个整体,用于后续的计算。

1.图像轮廓

边缘检测虽然能够检测出边缘,但边缘是不连续的,检测到的边缘并不是一个整体。图像轮廓是指将边缘连接起来形成的一个整体,用于后续的计算。

OpenCV提供了查找图像轮廓的函数cv2.findContours(),该函数能够查找图像内的轮廓信息,而函数cv2.drawContours()能够将轮廓绘制出来。图像轮廓是图像中非常重要的一个特征信息,通过对图像轮廓的操作,我们能够获取目标图像的大小、位置、方向等信息。

cv2.findContours可以帮助我们查找轮廓。

cv2.findContours(image, mode, method, contours=None, hierarchy=None, offset=None)

参数:

image: 需要查找轮廓的图片;
mode: 模式;
RETR_EXTERNAL: 只检测最外面的轮廓;
RETR_LIST: 检测所有的轮廓, 并将其保存到一条链表中;
RETR_CCOMP: 检索所有的轮廓, 将他们组织为两层: 顶部是各分部法外部边界, 第二层是空洞的边界;
RRTR_TREE: 检索所有的轮廓, 并重构嵌套轮廓的整个层次;
method: 轮廓逼近的方法;
CHAIN_APPROX_NONE: 以 Freeman 链码的方式输出轮廓, 所有其他方法输出多边形 (定点的序列);
CHAIN_APPROX_SIMPLE: 压缩水平的, 垂直的和斜的部分, 只保留他们的终点部分;

返回值:

contours:轮廓本身;
hierarchy: 轮廓的对应编号。

测试原图:
OpenCV入门(二十二)快速学会OpenCV 21 图像轮廓-LMLPHP

2.绘制轮廓

cv2.drawContours可以实现轮廓绘制。

格式:

cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None): 

参数:

image: 需要绘制轮廓的图片;
contours: 轮廓;
color: 颜色;
thickness: 轮廓粗细。

代码实例:

import cv2
#读取图像
img = cv2.imread("12.png")

# 转换成灰度图
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)

# 绘制轮廓
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)

# 图片展示
cv2.imshow("res", res)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果:

OpenCV入门(二十二)快速学会OpenCV 21 图像轮廓-LMLPHP

绘制单个轮廓代码实例:

import cv2
# 读取图片
img = cv2.imread("12.png")

# 转换成灰度图
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)

# 绘制轮廓 (单一)
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, 1, (0, 0, 255), 2)

# 图片展示
cv2.imshow("res", res)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果:

OpenCV入门(二十二)快速学会OpenCV 21 图像轮廓-LMLPHP

3.轮廓特征

获取轮廓特征,代码实例:

import cv2
import numpy as np

o = cv2.imread('12.png')
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
image, contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
cv2.imshow("original", o)
n = len(contours)
contoursImg = []
for i in range(n):
    print("contours[" + str(i) + "]面积=", cv2.contourArea(contours[i]))
    temp = np.zeros(o.shape, np.uint8)
    contoursImg.append(temp)
    contoursImg[i] = cv2.drawContours(contoursImg[i],
                                      contours,
                                      i,
                                      (255, 255, 255),
                                      3)
    cv2.imshow("contours[" + str(i) + "]", contoursImg[i])
cv2.waitKey()
cv2.destroyAllWindows()

输出结果:

        contours[0]面积= 13108.0
        contours[1]面积= 19535.0
        contours[2]面积= 12058.0

OpenCV入门(二十二)快速学会OpenCV 21 图像轮廓-LMLPHP

4.边界矩形

cv2.boundingRect可以帮助我们得到边界矩形的位置和长宽。

代码实例:

import cv2
# 读取图片
img = cv2.imread("12.png")

# 转换成灰度图
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)

# 获取第2个轮廓
cnt = contours[1]

# 获取正方形坐标长宽
x, y, w, h = cv2.boundingRect(cnt)

# 图片展示
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 轮廓面积
area = cv2.contourArea(cnt)

# 边界矩形面积
rect_area = w * h

# 占比
extent = area / rect_area
print('轮廓面积与边界矩形比:', extent)

输出结果:

OpenCV入门(二十二)快速学会OpenCV 21 图像轮廓-LMLPHP

OpenCV入门(二十二)快速学会OpenCV 21 图像轮廓-LMLPHP

5.外接圆

cv2.minEnclosingCircle可以帮助我们得到外接圆的位置和半径。

代码实例:

import cv2
# 读取图片
img = cv2.imread("12.png")

# 转换成灰度图
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)

# 获取第2个轮廓
cnt = contours[1]

# 获取外接圆
(x, y), radius = cv2.minEnclosingCircle(cnt)

# 获取图片
img = cv2.circle(img, (int(x), int(y)), int(radius), (0, 255, 0), 2)

# 图片展示
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果:
OpenCV入门(二十二)快速学会OpenCV 21 图像轮廓-LMLPHP

03-26 14:55