目录
一、轮廓的检测与绘制
轮廓检测(Contour Detection)用于检测图像中的边缘或物体的轮廓。轮廓是图像中连续的、具有相同颜色或灰度值的像素点所组成的曲线。通过轮廓检测,可以提取出图像中的对象的形状和结构信息。
1.1 cv2.findContours()函数
cv2.findContours() 函数是用于查找图像中的轮廓的。它的输入参数是一个二值化图像,其中白色像素表示前景,黑色像素表示背景。函数返回的是一个包含轮廓的列表,每个轮廓都是一个由点组成的边界。
函数的语法如下:
contours, hierarchy = cv2.findContours(image, mode, method, offset)
参数说明:
- image:输入的二值图像,通常为灰度图像或二值化图像。图像需要为8位无符号整型。
- mode:轮廓检索模式。有四种模式可选:
- cv2.RETR_EXTERNAL:只检测外部的轮廓。
- cv2.RETR_LIST:检测所有的轮廓,不建立轮廓间的层级关系。
- cv2.RETR_CCOMP:检测所有的轮廓,并将其组织为两层的层级关系。
- cv2.RETR_TREE:检测所有的轮廓,并将其组织为树状的层级关系。
- method:轮廓近似方法。有三种方法可选:
- cv2.CHAIN_APPROX_NONE:保存所有的轮廓点。
- cv2.CHAIN_APPROX_SIMPLE:只保存轮廓的端点。
- cv2.CHAIN_APPROX_TC89_L1和cv2.CHAIN_APPROX_TC89_KCOS:通过Teh-Chin链码逼近算法进行轮廓近似。
- offset:可选参数,用于指定轮廓点的偏移量。
函数返回两个值:
- contours:返回的轮廓信息,是一个由多个轮廓组成的列表。
- hierarchy:返回的轮廓层级信息,与轮廓列表对应。每个轮廓对应一个四元组(hierarchy[0], hierarchy[1], hierarchy[2], hierarchy[3]),分别为后一个轮廓、前一个轮廓、父轮廓、子轮廓的索引。如果没有则为-1。
1.2 cv2.drawContours()函数
cv2.drawContours()函数是OpenCV中用于绘制轮廓的函数。
函数的语法为:
image = cv2.drawContours(image, contours, contourIdx, color, thickness)
参数说明:
- image:输入的图像,可以是灰度图像或彩色图像。
- contours:轮廓信息,可以是通过cv2.findContours()函数得到的轮廓列表。
- contourIdx:轮廓的索引,指定要绘制的轮廓。如果为负数(例如-1),则绘制所有的轮廓。
- color:绘制轮廓的颜色,可以是指定的颜色(例如(0,255,0)表示绿色)或者是使用-1用于绘制填充轮廓。
- thickness:轮廓线的宽度。如果为负数(例如-1),则绘制填充轮廓。默认值为1。
函数的返回值为绘制轮廓后的图像。
1.3 轮廓检测示例代码
一般cv2.findContours()函数和cv2.drawContours()函数配合使用。
使用OpenCV库进行轮廓检测的示例代码:
import cv2
# 读取图片
image = cv2.imread('image.jpg')
# 转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 阈值化处理
ret, thresh = cv2.threshold(gray, 127, 255, 0)
# 轮廓检测
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv2.drawContours(image, contours, -1, (0, 255, 0), 3)
# 显示结果
cv2.imshow('Contours', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
首先读取一张图片,然后将其转换为灰度图像。接下来,对灰度图像进行阈值化处理,将图像转换为二值图像。然后,使用cv2.findContours()
函数进行轮廓检测,该函数返回检测到的轮廓以及它们的层级关系。最后,使用cv2.drawContours()
函数在原始图像上绘制检测到的轮廓。结果图像将显示出带有轮廓的物体。
二、显示边界框
2.1 cv2.boundingRect()函数
cv2.boundingRect()函数是OpenCV中一个用于计算轮廓的边界框的函数。它接受一个轮廓作为输入,并返回一个表示该轮廓的最小外接矩形的边界框。
函数的语法如下:
x, y, width, height = cv2.boundingRect(contour)
参数说明:
- contour:要计算边界框的轮廓,可以通过cv2.findContours()函数找到。
返回值说明:
- x, y:边界框的左上角坐标。
- width, height:边界框的宽度和高度。
该函数返回的边界框是一个矩形,可以用于识别轮廓的位置和大小。
2.2 cv2.rectangle()函数
cv2.rectangle()函数是OpenCV中的一个函数,用于在图像上绘制矩形。
函数原型为:
cv2.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]])
参数说明:
- img:要绘制矩形的图像。
- pt1:矩形的左上角顶点的坐标。
- pt2:矩形的右下角顶点的坐标。
- color:矩形的颜色,可以是BGR格式的颜色值,也可以是灰度值。
- thickness:矩形线条的宽度。如果thickness为正数,则表示线条宽度。如果thickness为负数或者等于-1,则表示矩形内部被填充。
- lineType:线条类型,默认为cv2.LINE_8。可以设置为cv2.LINE_4、cv2.LINE_8、cv2.LINE_AA等。
- shift:坐标点的小数位数。
2.3 显示绘制边界框
使用cv2.boundingRect()来显示边界框,首先将边界框计算出来,然后使用cv2.rectangle()在图像上绘制边界框。
下面是一个简单的示例代码,它显示如何使用cv2.boundingRect()显示边界框:
import cv2
# 读取图像
image = cv2.imread('image.jpg')
# 将图像转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 对灰度图像应用Canny边缘检测
edges = cv2.Canny(gray, 100, 200)
# 查找轮廓
contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 绘制边界框
for contour in contours:
# 计算边界框
x, y, w, h = cv2.boundingRect(contour)
# 在图像上绘制边界框
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
# 显示图像
cv2.imshow('Bounding Rect', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
示例中,首先读取图像并将其转换为灰度图像。然后,应用Canny边缘检测来检测图像的边缘。接下来,使用cv2.findContours()函数查找图像的轮廓。然后,对每个轮廓,使用cv2.boundingRect()函数计算边界框的坐标和尺寸。最后,使用cv2.rectangle()在图像上绘制边界框,并显示结果图像。
2.4 个人笔记和进阶版显示边框
2.4.1 个人笔记
"""
轮廓层次
函数原型: contours, hierarchy = cv2.findContours(image, mode, method)
hierarchy 为四个值的数值: [Next, Previous, First_Child, Parent]
Next 表示下一个相同轮廓等级的轮廓
Previous 表示上一个相同轮廓级別的轮廓
First_Child 表示其第一个子轮廓
Parent 表示其父代轮廓的索引
contours 返回一个列表,列表中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示
image 参数是寻找轮廓的图像
mode 参数表示轮廓的检索模式
cv2.RETR_EXTERNAL 表示只检测外轮廓
cv2.RETR_LIST 检测的轮廓不建立等级关系
cv2.RETR_CCOMP 建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息
cv2.RETR_TREE 建立一个等级树结构的轮廓
method 轮廓的近似办法
cv2.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1
cv2.CHAIN_APPROX_SIMPLE 压缩水平、垂直和对角线方向的元素,只保留该方向的终点坐标
绘制轮廓
函数原型: cv2.drawContours(img, contours, 10, color, thickness)
img: 输入图片
contours: 轮廓信息 (cv2.findContours()得到的结果)
10: 轮廓序号
color: 轮廓颜色
thinkness: 轮廓粗细
拟合直角矩形
函数原型: x,y,w,h = cv.boundingRect(contours)
(x,y): 轮廓左上角点坐标
w: 轮廓宽
h: 轮廓高
contours: 绘制的轮廓信息
拟合旋转矩形
函数原型: Rect = cv2.minAreaRect(contour) (RECT有三个值)
Rect[0]: 矩形中心点坐标
Rect[1]: 矩形的长、宽
Rect[2]: 矩形的旋转角度 (x轴逆时针到 w(宽)的角度)
contour: 轮廓信息
函数原型: cv.boxPoints(rect)
作用: 将 cv2.minAreaRect(contour)得到的结果转化成四个点的坐标
绘画矩形:
cv.rectangle(img, ps, pe, color, thickness)
img: 要绘制形状的图片
ps: 起点位置坐标
pe: 终点位置坐标
color: 绘制的颜色
thickness: 线宽,默认为 1;对于矩形或者圆之类的封闭形状而言,传入 -1表示填充形状
"""
"""
range()函数 可创建一个整数列表,一般应用在 for循环中,增量默认为 1
range(stop): 生成一个从 0开始到 stop的整数数列 ( 0 <= n < stop )
range(start,stop): 生成一个从 start到 stop的整数数列 ( start <= n<stop )
range(start,stop,step):
生成一个增量为 step,且从start到stop的整数数列(start,start + step, ... ,n - step, n)
"""
2.4.2 进阶版显示边框
import cv2 as cv
import numpy as np
def boundingBOX(img,contours,i): # 创建函数
x,y,w,h=cv.boundingRect(contours[i]) # 拟合直角矩形
cv.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) # 绘制矩形
def minAreaBOX(img,contours,i):
rect = cv.minAreaRect(contours[i]) # 拟合旋转矩形
box = cv.boxPoints(rect)
box = np.int0(box)
cv.drawContours(img,[box],0,(0,255,0),2)
if __name__=="__main__":
img = cv.imread("D:/Open_CV/OpenCV_demo/Pictures/1.jpg")
image = cv.imread("D:/Open_CV/OpenCV_demo/Pictures/1.jpg")
imgG = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,B = cv.threshold(imgG,60,255,cv.THRESH_BINARY)
contours,hierarchy = cv.findContours(B,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
# 轮廓检测
cv.drawContours(img,contours,-1,(0,255,0),2)
for i in range(len(contours)): # len(): 返回对象(字符、列表、元组等)长度或项目个数
minAreaBOX(img,contours,i)
boundingBOX(img,contours,i)
cv.imshow("img",img)
cv.imshow("image",image) # 显示原图
cv.waitKey(0)
运行结果: