图像金字塔
图像金字塔是图像中多尺度表达的一种,最主要用于图像的分割,是一种以多分辨率来解释图像的有效但概念简单的结构。图像金字塔最初用于机器视觉和图像压缩,一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低,且来源于同一张原始图的图像集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。我们将一层一层的图像比喻成金字塔,层级越高,则图像越小,分辨率越低。
高斯金字塔
高斯金字塔用来向下降采样图像,注意降采样其实是由金字塔底部向上采样,分辨率降低,它和我们理解的金字塔概念相反(注意)
对图像的向下取样操作,即缩小图像
down_up = cv.pyrUp(cv.pyrDown(img)) show('res', np.hstack((img, down_up)))
拉普拉斯金字塔
拉普拉斯金字塔是通过源图像减去先缩小后再放大的图像的一系列图像构成的。保留的是残差!为图像还原做准备!
down_up = cv.pyrUp(cv.pyrDown(img)) show('res', img - down_up)
注意:上采样和下采样是非线性处理,不可逆,有损的处理!
轮廓检测
调用流程和方法
载入图像
灰度化
二值化
轮廓检测
contours, hierarchy = cv2.findContours(image, mode, method)
返回的参数
contours:检测到的轮廓,每个轮廓是由一些点构成的向量组成
hierarchy:记录轮廓之间的关系,四个维度分别代表:同级后一个轮廓的序号、同级上一个轮廓的序号、第一个孩子序号,父亲序号
第二个数参数mode是检测轮廓的层级关系排列规则:
RETR_EXTERNAL:仅仅检测外圈轮廓
RETR_LIST:检测所有轮廓,但没有层级关系
RETR_CCOMP:仅仅两层包含关系,即只有外层和内层。假设有夹层,那么夹层也算外层,只要某个轮廓还包含有轮廓,都算外部轮廓
RETR_TREE:检测所有的轮廓,并建立完整的层级关系(常用)
第三个参数method是轮廓点的存储方式:
CHAIN_APPROX_NONE:相邻的轮廓点坐标只相差一个像素,所以是连续轮廓点
CHAIN_APPROX_SIMPLE:横、竖、对角线段只保存断点数据,比如矩形就只保存四个顶点。
画图函数
image = cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType …]] )
输入参数:
contours:是list类型的数组,里面存储了很多array数组去代表各个轮廓
contourIdx:从上面的轮廓list中取出哪一个画出来,-1代表全部
color:线条颜色
thickness:线条粗细,-1代表填充式画轮廓,整个轮廓内部被指定颜色填充
lineType:线条类型,虚线、实线之类的
注意:如果将原图传入画图函数,这个原图会被画上轮廓。
img = cv.imread(name + '_1.jpg') gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) ret, thresh = cv.threshold(gray, 127, 255, cv.THRESH_BINARY) contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) img1 = img.copy() res = cv.drawContours(img1, contours, -1, (0, 0, 255), 1) show('res', res)
轮廓特征
面积
cv2.contourArea()
求出指定轮廓的面积
cv.contourArea(contours[1])
周长
cv2.arcLength()
求出指定轮廓的周长,第二个参数指示当前输入为闭合轮廓(True)还是非闭合曲线(False)
cv.arcLength(contours[1], True)
轮廓近似
多边形
cnt = contours[100] epsilon = 0.1 * cv.arcLength(cnt, True) # 新的轮廓的周长和原始轮廓周长的误差范围在原周长的十分之一以内 approx = cv.approxPolyDP(cnt, epsilon, True) img1 = img.copy() res = cv.drawContours(img1, [approx], -1, (0, 0, 255), 2) show('res', res)
边界矩形
x,y,w,h = cv.boundingRect(cnt) img = cv.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) show('img', img)
外接圆
(x, y), radius = cv.minEnclosingCircle(cnt) center = (int(x), int(y)) radius = int(radius) show('img', cv.circle(img.copy(), center, radius, (0, 255, 0), 2))