cv2-轮廓检测
轮廓检测
轮廓检测的作用
- 可以检测图图像或者视频中物体的轮廓
- 计算多边形边界,形状逼近和计算感兴趣区域
为了更精确地提取轮廓,请使用二值图。也就是说,在使用轮廓提取函数前,请将源图片运用阈值进行二值化cv2.threshold()
或者采用Canny边缘检测。
findContours 函数会修改源图片,如果希望在轮廓检测后继续使用源图片,务必提前保存在另一个变量中。
在OpenCV中,轮廓检测视作从黑色背景中提取白色的物体,所以,在结果中,白色表示物体,黑色表示背景。
cv2.findContours
查找并得到物体的轮廓
输入的是图像的二值图
contours,hierarchy=cv2.findContours(image, mode, method, contours=None, hierarchy=None, offset=None)
输入参数
- image=img 输入的是二值化图(黑白)
- mode 轮廓搜索模式
- method 轮廓近似方法
- contours
返回参数
- contours 轮廓本身 shape=(len,points,1,2) 四个维度列表
- hierarchy 每条轮廓对应的属性
mode 参数:
cv2.RETR_EXTERNAL 表示只检测外轮廓
cv2.RETR_LIST 检测的轮廓不建立等级关系
cv2.RETR_CCOMP 建立两个等级的轮廓
cv2.RETR_TREE 建立一个等级树结构的轮廓
method:
cv2.CHAIN_APPROX_NONE 存储所有的轮廓点
cv2.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标
image = cv2.imread('math.jpg')
grayIma = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 将图像二值化,提高准确率
ret, image1 = cv2.threshold(grayIma, 127, 255, cv2.THRESH_BINARY)
ShowImage('image1', image1)
contours, hierarchy = cv2.findContours(iamge, mode, method)
特征矩
特征矩可以帮助您计算一些特征,例如物体的质心,物体的面积等。请查看特征矩上的维基百科页面。函数cv.moments()提供了所有计算出的矩值的字典
import numpy as np
import cv2 as cv
img = cv.imread('star.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
contours,hierarchy = cv.findContours(thresh, 1, 2)
cnt = contours[0]
M = cv.moments(cnt)
print( M )
\[C_x = \frac{M_{10}}{M_{00}} \;\; C_y = \frac{M_{01}}{M_{00}}
\]
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
cv2.drawContours
根据findcontours
得到的轮廓,对轮廓进行绘制
img=drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
输入参数
image 幕布图像,目标图像
contours 轮廓本身 shape=(len,points,1,2)
contourIdx 轮廓索引 指示要绘制的轮廓的参数 -1代表所有
color 绘图颜色 BGR
thickness 线宽 -1表示填充
lineType 线的连通性
返回参数
img
drawimage = image.copy()
result1 = cv2.drawContours(drawimage, contours, -1, (0,255,0), 1) # 绘制所有轮廓
完整案例
import cv2
import numpy as np
src = cv2.imread("main.jpg")
# Canny处理得到二值化图像
src = cv2.GaussianBlur(src, (5, 5), 5)
canny = cv2.Canny(src, 0,30)
# 轮廓检测
contours, hierarchy = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 注意这里第一个参数输入的是原始图像
cv2.drawContours(src, contours, -1, (0,0,255), 1)
cv2.imshow("src", src)
cv2.imshow("canny", canny)
cv2.waitKey()
cv2.destroyAllWindows()
轮廓特征
计算轮廓面积
cv2.contourArea(contour,oriented)
输入参数
contour 单个轮廓(points,1,2) >>> contours[0]
oriented 有方向的区间标识,默认false
返回参数
面积
计算轮廓周长
计算轮廓的周长
cv2.arcLength(curve, closed)
输入参数
curve 单个轮廓(points,1,2) >>> contours[0]
closed 指定对象的形状是闭合还是打开的(曲线) true false
接受的参数为二值图,检索模式,有四种,method为轮廓的近似办法
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
img = cv2.drawContours(img,contours,-1,(0,0,255),3)
"""
计算轮廓的周长
cv2.arcLength(curve, closed)
输入参数
curve 单个轮廓(points,1,2) >>> contours[0]
closed 指定对象的形状是闭合还是打开的(曲线) true false
"""
res = cv2.contourArea(contours[0])
length= cv2.arcLength(contours[0],True)
轮廓近似和凸包
???
边界矩形 >>> 正矩形框
"""
x, y, w, h = cv2.boundingRect(array)
输入参数
array 单个轮廓(points,1,2) >>> contours[0]
返回参数
x,y,w,h x,y是矩阵左上点的坐标,w,h是矩阵的宽和高
"""
# 示例:
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 画出contours
cv2.drawContours(bgr_img, contours, -1, (0, 0, 255), 3)
# 将所有的 contours 绘制正矩形框,并画出
bounding_boxes = [cv2.boundingRect(cnt) for cnt in contours]
for bbox in bounding_boxes:
[x , y, w, h] = bbox
cv2.rectangle(bgr_img, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("name", bgr_img)
cv2.waitKey(0)
最小边界矩形 >>> 斜矩形框
"""
cv2.minAreaRect(points)
输入参数
points 单个轮廓(points,1,2) >>> contours[0]
返回参数
rect=((x,y)(w,h),D) Box2D结构rect (最小外接矩形的中心(x,y),(宽度w,高度h),旋转角度--水平x方向逆时针,与之遇到的第一条边为宽,w,h不是以长短定义的)
"""
min_boundingbox = cv2.minAreaRect(contours[0])
min_boundingbox = ((x,y)(w,h),D)
# 获得最下外接矩形的四个顶点
"""
box = cv2.boxPoints(box)
输入参数
box (中心(x,y), (宽,高), 旋转角度)
返回参数
boxpoint 矩形的四个顶点 boxpoint.shape=(4,2)type(point)=float
"""
boxpoint = cv2.boxPoints(min_boundingbox)
box = np.int0(box) # 数据取整
img_box=cv2.drawContours(img, [box], 0, (0, 0, 255), 5) # 画图
参考资料
https://blog.csdn.net/weixin_43229348/article/details/125980463