openCV实战-系列教程6:图像金字塔与轮廓检测(图像金字塔/高斯金字塔/拉普拉斯金字塔/图像上采样/图像下采样/轮廓检测/轮廓特征与近似/模版匹配)、原理解析、源码解读

打印一个图片可以做出一个函数:

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

1、图像金字塔定义

图像金字塔就是将图像组合成像金字塔一样的形状,比如原来的图像是1600*900,现在将它变换为1200*750的图像,在金字塔越上面就会越小。那么一张图像就会有多种形式,在以后如果做特征提取,可能不知有一种方法进行特征提取,可能需要对金字塔图像都要做特征提取。 

  • 高斯金字塔
  • 拉普拉斯金字塔

openCV实战-系列教程6:图像金字塔与轮廓检测(图像金字塔/高斯金字塔/拉普拉斯金字塔/图像上采样/图像下采样/轮廓检测/轮廓特征与近似/模版匹配)、原理解析、源码解读_第1张图片

1.1 高斯金字塔

高斯金字塔,向下采样法,缩小:

openCV实战-系列教程6:图像金字塔与轮廓检测(图像金字塔/高斯金字塔/拉普拉斯金字塔/图像上采样/图像下采样/轮廓检测/轮廓特征与近似/模版匹配)、原理解析、源码解读_第2张图片

如图所示,这是一个高斯卷积核,还有一个归一化的操作(1/16)。

将图像与高斯内核近图像卷积,然后将偶数行列都去掉,这就是使用了高斯金字塔方法进行了下采样。

高斯金字塔,向上采样法,放大:

openCV实战-系列教程6:图像金字塔与轮廓检测(图像金字塔/高斯金字塔/拉普拉斯金字塔/图像上采样/图像下采样/轮廓检测/轮廓特征与近似/模版匹配)、原理解析、源码解读_第3张图片

上采样,比如一个像素点加上三个0由1*1变成了2*2,然后再进行高斯内核的图像卷积,完成了上采样,补充值就是拿0填充。

2、金字塔制作方法

 如何在OpenCV中执行第一节中的操作呢?

首先读进来一张图像:

img=cv2.imread("AM.png")
cv_show(img,'img')
print (img.shape)

 打印结果:(442, 340, 3)

openCV实战-系列教程6:图像金字塔与轮廓检测(图像金字塔/高斯金字塔/拉普拉斯金字塔/图像上采样/图像下采样/轮廓检测/轮廓特征与近似/模版匹配)、原理解析、源码解读_第4张图片

进行上采样操作:

up=cv2.pyrUp(img)
cv_show(up,'up')
print (up.shape)

pyr就是金字塔的所写,pyrUp顾名思义就是金字塔上采样,打印结果:(884, 680, 3)。图像变大了一些,这里就不展示了

下采样:

down=cv2.pyrDown(img)
cv_show(down,'down')
print (down.shape)

 打印结果:(221, 170, 3)

 如果先进行上采样在进行下采样,会和原始图片一样吗?

应该是不一样的,因为上采样是拿0进行填充的,代码:

up=cv2.pyrUp(img)
up_down=cv2.pyrDown(up)
cv_show(img-up_down,'img-up_down')

 结果就不展示了,大家可以自己跑一下

2.1 拉普拉斯金字塔

拉普拉斯金字塔的制作方法稍微有点特别:

openCV实战-系列教程6:图像金字塔与轮廓检测(图像金字塔/高斯金字塔/拉普拉斯金字塔/图像上采样/图像下采样/轮廓检测/轮廓特征与近似/模版匹配)、原理解析、源码解读_第5张图片

这里的Gi表示的是输入,后面的表示先进行下采样再进行上采样的结果,Gi减去这个结果,然后每一层都是这样做的。

如图,G0是第一层的原始图像,先经过低通滤波和下采样,然后经过上采样,原始图像再减去上采样的结果,第二层也是同样的做法,只不过第二层的原始输入是第一层的输出,后面以此类推。

当然在OpenCV实现:

down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
l_1=img-down_up
cv_show(l_1,'l_1')

 打印结果:

openCV实战-系列教程6:图像金字塔与轮廓检测(图像金字塔/高斯金字塔/拉普拉斯金字塔/图像上采样/图像下采样/轮廓检测/轮廓特征与近似/模版匹配)、原理解析、源码解读_第6张图片

3、图像轮廓检测

 函数:cv2.findContours(img,mode,method),model和method参数

mode:轮廓检索模式

  • RETR_EXTERNAL :只检索最外面的轮廓;
  • RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中;
  • RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
  • RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次;

method:轮廓逼近方法

  • CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
  • CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。

实际上在轮廓检索模式中,我们就使用最后一个就可以了。 

怎样进行轮廓检测:

为了更高的准确率,使用二值图像:

img = cv2.imread('contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show(thresh,'thresh')
  1. 读取图像
  2. 灰度处理
  3. 二值处理(大于127的全部为255,小于127的全部为0,在前面已经讲过二值处理)
  4. 打印

打印结果:

openCV实战-系列教程6:图像金字塔与轮廓检测(图像金字塔/高斯金字塔/拉普拉斯金字塔/图像上采样/图像下采样/轮廓检测/轮廓特征与近似/模版匹配)、原理解析、源码解读_第7张图片

计算轮廓信息:

contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

contours:轮廓点,轮廓信息 

hierarchy:层级信息

绘制轮廓:

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

将原始图像进行深度复制的原因是,因为drawContours会将原始图像上进行更改。

解释一下drawContours参数意思,draw_img是需要画轮廓的原始图,contours是原始图包含的轮廓信息,-1第几个轮廓,-1就是表示所有的轮廓都画出来,(0,0,255)分别表示bgr,就是画轮廓用什么颜色,这里就是用的纯红色,最后一个2是轮廓的线条宽度。

执行完后得到的结果:

openCV实战-系列教程6:图像金字塔与轮廓检测(图像金字塔/高斯金字塔/拉普拉斯金字塔/图像上采样/图像下采样/轮廓检测/轮廓特征与近似/模版匹配)、原理解析、源码解读_第8张图片

换一张图片:

img = cv2.imread('car.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show(thresh,'thresh')
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cv_show(img,'img')
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
cv_show(res,'res')

执行结果:

openCV实战-系列教程6:图像金字塔与轮廓检测(图像金字塔/高斯金字塔/拉普拉斯金字塔/图像上采样/图像下采样/轮廓检测/轮廓特征与近似/模版匹配)、原理解析、源码解读_第9张图片 

把这些车的代码注释掉,再接着话前面那张图片的轮廓,这次我们把第几个轮廓那个参数改一下: 

img = cv2.imread('contours.png')
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, 0, (0, 0, 255), 2)
cv_show(res,'res')

运行结果:

openCV实战-系列教程6:图像金字塔与轮廓检测(图像金字塔/高斯金字塔/拉普拉斯金字塔/图像上采样/图像下采样/轮廓检测/轮廓特征与近似/模版匹配)、原理解析、源码解读_第10张图片

只画出了一个轮廓,如果你指定1就会是三角形的内圈,这里你可以多试几下。此外,如果不加.copy(),当你再次执行img数据的打印时,就会出现轮廓的图,不会出现原始图,copy是python的深度复制。

你可能感兴趣的:(openCV实战,源码解读,计算机视觉,计算机视觉,opencv,python)