1 什么是图像的轮廓
- 图像的轮廓指的是同一个颜色的连续点曲线。
- 轮廓是分析物体形状和检测识别的重要指标
- 使用Canny等操作对图片进行二值化操作
- 画轮廓是会修改原图
2 查找轮廓
- cv2.findContours(image,mode,method)
- mode查找模式:
?? RETR_EXTERNAL = 0 只检测外轮廓 RETR_LIST = 1 检测所有轮廓,不存在等级关系 RETR_CCOMP = 2 每层最多检测2级,从小到大,从里到外 RETR_TREE = 3 按照树形存储轮廓,从大到小,从右到左 - method轮廓的近似方法:
??CHAIN_APPROX_NONE保存轮廓上的所有点 ??CHAIN_APPROX_SIMPLE:只存储边缘的对角点,存储信息少,比较常用 - 返回值参数:
??返回轮廓和层次。contours,hierarchy
import cv2
import numpy as np
img = cv2.imread('imgs/a.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
max_value, img = cv2.threshold(img, 150,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print(contours)
cv2.imshow('轮廓', img)
cv2.waitKey(0)
cv2.waitKey(0)
3 绘制轮廓
- 通过查找轮廓findContours我们可以得到这个图像返回的轮廓
- 使用cv2.drawContours(image,contours,contourldx,color)画出轮廓
? ? contours:轮廓点 ? ? contourldx:想绘制轮廓图像的标号。 -1 为默认所有图像
cv2.drawContours(img,contours,-1,(0,0,255))
4 轮廓的周长和面积
- 查找轮廓之后,可能得到多个轮廓,通过周长和面积对这些轮廓进行筛选
- 得到图像的轮廓,通过面积和周长来分析这个图像的具体特征
- cv2.contourArea(contours):计算面积
- cv2.arcLength(curve, closed):计算周长
??curve:表示轮廓 ??closed:表示这个轮廓是否闭合
cv2.contourArea(contours[0])
cv2.arcLength(contours[0],True)
5 多边形逼近
- 由于找到的轮廓图像非常多,可能过于复杂不平滑,故意使用**cv2.approxPolyDP()**对轮廓进行近似处理
- 多边形逼近使用Douglas-Peucker算法进行处理
- 首先设置一个阈值,在找到的目标两点之间遭到最远切线之间的距离,如果这个距离小于阈值,即可近似处理
- cv2.approxPolyDP(curve, epsilon, closed)
???curve:多边形的轮廓 ???epsilon:dp算法的阈值 ???closed:是否闭合
import cv2
import numpy as np
img = cv2.imread('imgs/a.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
maxvlues, img = cv2.threshold(img, 150,255,cv2.THRESH_BINARY)
contours,hi = cv2.findContours(img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
approx = cv2.approxPolyDP(contours[1], 20, True)
cv2.drawContours(img,[approx],0,(0,255,0))
cv2.imshow('a',img)
cv2.waitKey(0)
6 凸包
- 为了对轮廓的图像进行改进,使用凸包对轮廓进一步的描述,使得所有连续三个点的角度小于180度
- 得到一个大概的轮廓
- cv2.convexHull(contours[1]) 传入轮廓即可
import cv2
import numpy as np
img = cv2.imread('imgs/a.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
maxvlues, img = cv2.threshold(img, 150,255,cv2.THRESH_BINARY)
contours,hi = cv2.findContours(img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
hull = cv2.convexHull(contours[1])
cv2.drawContours(img,[hull],0,(0,255,0))
cv2.imshow('a',img)
cv2.waitKey(0)
7 外接矩形
- 最小外接矩形:使用最小的框
- rect = cv2.minAreaRect(contours[1])
???传入某一个具体的轮廓 ???得到一个元组:矩阵的起始坐标,长款,矩形的旋转角度 - 还需要计算出矩阵的各个点的坐标: box = cv2.boxPoints(rect)
- 像素都是整型,还需要转化成整型
import cv2
import numpy as np
img = cv2.imread('imgs/a.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
maxvlues, img = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY)
contours, hi = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
rect = cv2.minAreaRect(contours[1])
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img, [box], 0, (255, 0, 0))
cv2.imshow('a', img)
cv2.waitKey(0)
- 最大外接矩形:使用最大的框
- cv2.boundingRect(contours[1])
- 得到的就是4个点的坐标
- 使用rectangle画上矩阵的坐标
import cv2
import numpy as np
img = cv2.imread('imgs/a.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
maxvlues, img = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY)
contours, hi = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
x,y,w,h = cv2.boundingRect(contours[1])
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow('a', img)
cv2.waitKey(0)
8 图像金字塔
?图像金字塔是同一张图片不同分辨率的集合。
- 对于一张高分辨率的图片,通过压缩成分辨率低的图片。
常见的两类图像金字塔
- 高斯金字塔
?? 通过使用高斯平滑和亚采样(subsampling)来获取一系列的下采样图像
G
i
G_i
Gi? =
[
1
4
6
4
1
4
16
24
16
4
6
24
36
24
6
4
16
24
16
4
1
4
6
4
1
]
?
1
16
\begin{bmatrix} 1 &4&6&4&1 \\4 &16&24&16&4\\6 &24&36&24&6 \\4 &16&24&16&4 \\1 &4&6&4&1 \\ \end{bmatrix}*\frac{1}{16}
???????14641?41624164?62436246?41624164?14641?????????161?
- 将
G
i
G_i
Gi?与高斯内核卷积
- 将所有二代偶数行列去掉
- 下采样会减少图片的分辨率:cv2.pyrDown(img)
import cv2
img = cv2.imread('imgs/66.jpg')
dst = cv2.pyrDown(img)
cv2.imshow('a', img)
cv2.imshow('b', dst)
cv2.waitKey(0)
- 向上采样:将图片放大,放大4倍,用0来补充
- 然后使用内卷进行卷积
import cv2
img = cv2.imread('imgs/66.jpg')
dst = cv2.pyrUp(img)
cv2.imshow('a', img)
cv2.imshow('b', dst)
cv2.waitKey(0)
拉普拉斯金字塔
使用高斯金字塔对图片先缩小向下采样,然后向上采样。
- 使用原图减去改变之后的图片即可得到丢失的数据,即拉普拉斯金字塔
import cv2
img = cv2.imread('imgs/66.jpg')
dst = cv2.pyrDown(img)
dst = cv2.pyrUp(dst)
dst = img-dst
cv2.imshow('a', img)
cv2.imshow('b', dst)
cv2.waitKey(0)
|