OpenCV视频学习笔记(7)-图像金字塔与轮廓检测

七、图像金字塔与轮廓检测

图像金字塔 应用:可以对金字塔中的每一次都进行特征提取,再进行总结
(1)高斯金字塔
(2)拉普拉斯金字塔

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline

def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()

img=cv2.imread(‘D:/graduate/AM.png’)
cv_show(img,‘img’)
print(img.shape)
显示:
shape值:(442, 340, 3)

#高斯金字塔:向上采样法
up=cv2.pyrUp(img)
cv_show(up,‘up’)
print(up.shape)
显示:
shape值:(884, 680, 3)
图像在原图像的基础上变大一倍

#高斯金字塔:向下采样法
down=cv2.pyrDown(img)
cv_show(down,‘down’)
print(down.shape)
显示:
shape值:(221, 170, 3)
图像在原图像的基础上变小一倍

#在第一次上采样的基础上,再执行一次上采样
up2=cv2.pyrUp(up)
cv_show(up2,‘up2’)
print(up2.shape)
显示:
shape值:(1768, 1360, 3)
图像又变大一倍

#先执行上采样再执行下采样,看是否和原始图像一样大
up=cv2.pyrUp(img)
up_down=cv2.pyrDown(up)
cv_show(up_down,‘up_down’)

cv_show(np.hstack((img,up_down)),‘up_down’)

根据图像对比可以发现,图像变得模糊,所以不会变成原来的图像,因为上采样和下采样都会损失一些信息。
可以根据减法运算看一下差异:
up=cv2.pyrUp(img)
up_down=cv2.pyrDown(up)
cv_show(img-up_down,‘img-up_down’)

拉普拉斯金字塔:原始图像(img)减去先执行down再执行up的结果。

down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
l_1=img-down_up
cv_show(l_1,‘l_1’)
显示:

报错:
File “”, line 3 1_1=img-down_up
^ SyntaxError: can’t assign to literal
原因:
Python中变量的命名不能以数字开头,把1_1改为l_1
· 标示符可以由 字母、下划线 和 数字 组成
· 不能以数字开头
· 不能与关键字重名
图像轮廓
轮廓检测函数:cv2.findContours(img,mode,method)
mode:轮廓检索模式
RETR_EXTERNAL:只检索最外面的轮廓;
RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中;
RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次;(√)通常用这个
method:轮廓逼近方法
CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列);
CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分;
做轮廓检测,为了更高的准确率,使用二值图像。
步骤:(1)首先先把图像读进来
(2)把图像数据转换成灰度图
(3)对图像数据进行二值处理(用之前学的阈值)
(4)显示图像
img=cv2.imread(‘D:/graduate/car.png’)
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
cv_show(thresh,‘thresh’)
显示:

对图像做二值处理的目的就是为了更好的进行边缘检测
数据处理完成,接下来进行检测操作:
#检测操作
binary,contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
binary:二值处理后的结果
contours:保存轮廓的信息
hierarchy:层级
thresh:传入二值处理后的图像
cv2.RETR_TREE:mode
cv2.CHAIN_APPROX_NONE:method

绘制轮廓
#传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
#注意需要copy,要不原图会变
draw_img=img.copy()
res=cv2.drawContours(draw_img,contours,-1,(0,0,255),2)
cv_show(res,‘res’)

draw_img:要绘制轮廓的原图像
contours:轮廓是什么,contours中保存了轮廓信息
-1:画第几个轮廓,默认为1,意为把所有轮廓画出来
(0,0,255):(B,G,R),这里表示用红色的颜色画
2:线条的宽度

换个图像,看看传入的第三个参数变化,绘制的轮廓会有什么变化:
img=cv2.imread(‘D:/graduate/contours.png’)
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
cv_show(thresh,‘thresh’)

#检测操作
binary,contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
#注意需要copy,要不原图会变
draw_img=img.copy()
res=cv2.drawContours(draw_img,contours,-1,(0,0,255),2)
cv_show(res,‘res’)

draw_img=img.copy()
res=cv2.drawContours(draw_img,contours,0,(0,0,255),2)
cv_show(res,‘res’)
显示:

绘制三角形的外圈

draw_img=img.copy()
res=cv2.drawContours(draw_img,contours,1,(0,0,255),2)
cv_show(res,‘res’)
显示:

绘制三角形的内圈

draw_img=img.copy()
res=cv2.drawContours(draw_img,contours,2,(0,0,255),2)
cv_show(res,‘res’)
显示:

绘制六边形的外圈

轮廓特征
对轮廓进行特征计算时,首先要把具体的轮廓拿出来,再进行使用
cnt=contours[0]

计算轮廓的面积
#面积
cv2.contourArea(cnt)
显示:8500.5
计算周长
#周长,True表示闭合的
cv2.arcLength(cnt,True)
显示:437.9482651948929
轮廓近似
近似函数:approxPolyDP();
步骤:先读取图像,灰度图,二值处理,找到轮廓,绘制轮廓
img=cv2.imread(‘D:/graduate/test picture/contours2.png’)

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
binary,contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt=contours[0]

draw_img=img.copy()
res=cv2.drawContours(draw_img,[cnt],-1,(0,0,255),2)
cv_show(res,‘res’)

显示:

epsilon=0.1*cv2.arcLength(cnt,True)
approx=cv2.approxPolyDP(cnt,epsilon,True)

draw_img=img.copy()
res=cv2.drawContours(draw_img,[approx],-1,(0,0,255),2)
cv_show(res,‘res’)

approxPolyDP(cnt,epsilon,True)近似函数
cnt:标明做哪个轮廓,这里是其中的一个轮廓cnt=contours[0]
epsilon:阈值,用作比较,一般按照周长的百分比设置

你可能感兴趣的:(OpenCV视频学习笔记(7)-图像金字塔与轮廓检测)