Python-Opencv学习总结(七):Canny边缘检测、图像金字塔、图像轮廓

1、Canny边缘检测

一般步骤:
1.去噪:通常采用高斯滤波器去除噪声。
2.梯度:对平滑后的图像采用sobel算子计算梯度和方向。
方向计算:角度=tan^-1(垂直梯度\水平梯度)
梯度的方向一般总是与边界垂直。
梯度方向被归为四类:垂直,水平,和两个对角线。
3.非极大值抑制:在获得了梯度和方向后,遍历图像,去除所有不是边界的点。
实现方法:逐个遍历像素点,判断当前像素点是否是周围像素点中具有相同方向梯度的最大值。
保留相同方向的最大值被保留
4.滞后阈值:滞后阈值1:minVal,滞后阈值2:maxVal
如下图
在这里插入图片描述
如上图:
1.梯度值大于最大阈值,保留,如A
2.梯度值小于最小阈值,舍弃,如D
3.maxVal>梯度值> minVal,与边界相连,保留,如C;与边界不相连,抛弃,如B。
Canny边缘检测函数及使用
函数:

edges = cv2.Canny( image, threshold1, threshold2 )
edges:处理后的边界图像
image:原始图像
threshold1:阈值1,minVal
threshold2:阈值2,maxVal
阈值越小,得到的边界信息越多,反之一样。
调整阈值,可 以控制边缘细节。
maxVal、minVal变小,有更多的细节信息。


import cv2
import numpy as np
o=cv2.imread(r'D:\image\lena.bmp',cv2.IMREAD_UNCHANGED)
r=cv2.Canny(o,100,200)
r1=cv2.Canny(o,64,128)
r2=cv2.Canny(o,30,80)  #阈值越小,轮廓越多
cv2.imshow('o',o)
cv2.imshow('r',r)
cv2.imshow('r1',r1)
cv2.imshow('r2',r2)
cv2.waitKey()
cv2.destroyAllWindows()

2、图像金字塔

金字塔的底部是待处理图像的高分辨率的表示,而顶部是低分辨率的表示当金字塔向上层移动的时候,尺寸和分辨率都会降低。
假设基础级(也就是最底层)的尺寸为 2J×2J
金字塔中间任意一级j的尺寸大小为:2j×2j ,所以说,一个完整的图像金字塔可以由J+1个分辨率集所组成。
在这里插入图片描述
构造金字塔的过程
在这里插入图片描述
拿到第j级的图像后,先通过一个低通滤波,这个滤波可以选取任何一个低通滤波。比如理想低通,巴特沃斯,高斯低通。然后在进行以2为步长的下采样。就得到了j-1级的近似图像。一次循环,等到顶层。
高斯金字塔:开始时选取高斯低通滤波器,生成图像金字塔。
高斯低通滤波器:
在这里插入图片描述
D(u,v)表示的是(u,v)距离傅里叶变换原点的距离。
高斯滤波器宽度(决定着平滑程度)是由参数σ表征的,而且σ和平滑程度的关系是非常简单的。σ越大,高斯滤波器的频带就越宽,平滑程度就越好。
高斯金字塔:
第一步的滤波必须选用高斯低通滤波器。
通过使用不同的σ来调节滤波器的频带宽度,得到经过不同滤波器同尺寸的同一组octave。
其中的每个octave可以看做是一组图像,这一组图像中的所有图像的分辨率相同,但是采用了不同频带的高斯滤波函数,从模糊的程度上看是有区别的。不同组(octave)之间的图像具有不同的分辨率,在尺度上的差别就更大了。
在这里插入图片描述
拉普拉斯金字塔:
拉普拉斯金字塔可以认为是残差金字塔,用来存储下采样后图片与原始图片的差异。
在这里插入图片描述
如果高斯金字塔中任意一张图G,先进行下采样得到图Down(G),再进行上采样得到图Up(Down(G)),得到的Up(Down(G))与Gi是存在差异的,因为下采样过程丢失的信息不能通过上采样来完全恢复,也就是说下采样是不可逆的。
原始图片下采样后得到的小尺寸图片虽然保留了视觉效果,但是将该小尺寸图像再次上采样也不能完整的恢复出原始图像。为了能够从下采样图像Down(G)中还原原始图像G,我们需要记录再次上采样得到Up(Down(G))与原始图片G之间的差异,这就是拉普拉斯金字塔的核心思想。
总结:
图像金字塔:同一图像的不同分辨率的子图集合
生成金字塔方式:
向下取样:不是方位的向下,而是分辨率从高到底,进行取样,缩小4倍
向上取样:不是方位的向上,而是分辨率从低到高,进行取样,放大4倍

在这里插入图片描述
向下取样:缩小图像,不断获取低分辨率图像
从第i层获取第i+1层 Gi到Gi+1
1.对图像Gi进行高斯核卷积。
2.删除所有的偶数行和列。

Octave:原始图像MN ——处理结果M/2 N/2;每次处理后,结果图像是原来的1/4.
重复Octave,边构造了图像金字塔

向上取样:放大图像,不断获取高分辨率图像
1.在每个方向上扩大为原来的2倍,新增的行和列以0填充。原来两行两列会变成四行四列。
2.使用与“向下采用”同样的卷积核乘以4,获取“新增像素”的新值。
向上采样、向下采样不是互逆操作。会变模糊
经过两种操作后,无法恢复原有图像。

向下取样函数及使用(pyrDown函数)

dst=cv2.pyrDown(src)
dst:向下取样结果
src:原始图像
r=cv2.pyrDown(0)

可进行多次向下取样
r1=cv2.pyrDown(o)
r2=cv2.pyrDown(r1)
r3=cv2.pyrDown(r2)```

**向上取样函数及使用(pyrUp函数**

```python
dst=cv2.pyrUp(srC)
dst:向上取样结果
src:原始图像
r=cv2.pyrUp(0)

可进行多次向上取样
r1=cv2.pyrUp(o)
r2=cv2.pyrUp(r1)
r3=cv2.pyrUp(r2)

向下取样与向上取样的可逆性研究
可逆性:能不能恢复
原始图像——向下取样——向上取样——结果能不能恢复原图像

先向下,再向上
down=cv2.pyrDown(o)
up=cv2.pyrUp(down)
清晰度会降低,采样过程中信息会丢失

先向上,在向下
up=cv2.pyrUp(o)
down=cv2.pyrDown(up)
依旧有差距
拉普拉斯金字塔

Li= Gi- PyrUp(PyrDown(Gi)) 
Gi:原始图像
Li:拉普拉斯金字塔图像

在这里插入图片描述
如上图:
拉普拉斯金字塔0层=原始图像O-向下采用1次再向上采样1次的Odu
拉普拉斯金字塔1层=向下采样1次的Od-向下采样2次再向上采样1次的O2du

o=cv2.imread("image\\lena.bmp")
od=cv2.pyrDown(0)
odu=cv2.pyrUp(od)
lapPyr=o-odu
o1=od
o1d=cv2.pyrDown(o1)
o1du=cv2.pyrUp(o1d)
lapPyr1=o1-o1du

3、图像轮廓

图像轮廓:将没有连接在一起的边缘连接在一起,边缘检测不等于图像轮廓。
边缘检测能够测出边缘,但是边缘是不连续的。将边缘连接为一个整体,构成轮廓。

注意问题
注意问题:
1.对象必须是二值图像。所以需要预先进行阈值分割或者边缘检测处理。将彩色或灰度图像调为二值图像
2.查找轮廓需要更改原始图像。因此,通常使用原始图像的一份拷贝操作。
3.在OpenCV中,是从黑色背景中查找白色对象。因此,对象必须是白色的,背景必须是黑色的。
如遇到白色背景,要进行处理。
函数
cv2.findContours( ):查找图像轮廓,返回一个变量
cv2.drawContours( ):将查找到的轮廓绘制到图像上

cv2.findContours( )  
contours, hierarchy = cv2.findContours( image, mode, method)
image:原始图像
contours:轮廓                              mode:轮廓检索模式
hierarchy:图像的拓扑信息(轮廓层次)         method:轮廓的近似方法

mode:轮廓检索模式
cv2.RETR_EXTERNAL:表示只检测外轮廓
cv2.RETR_LIST:检测的轮廓不建立等级关系
cv2.RETR_CCOMP:建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。
    如果内孔内还有一个连通物体,这个物体的边界也在顶层。
CV2.RETR_TREE:建立一个等级树结构的轮廓。(一般使用这个模式)

method:轮廓的近似方法(一般使用前两种)
cv2.CHAIN_APPROX_NONE : 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,max (abs (x1-x2)abs (y2-y1) ) ==1
cv2.CHAIN_APPROX_SIMPLE:压缩水平方向,垂直方向,对角线方向的元素,
    只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
cv2.CHAIN_APPROX_TC89_L1:使用teh-Chinl chain近似算法
cv2.CHAIN_APPROX_TC89_KCOS:使用teh-Chinl chain近似算法
cv2.drawContours( )
r=cv2.drawContours(o,contours,contourldx,color,[thickness])
r:目标图像,直接修改目标的像素点,实现绘制。
o:原始图像
contours:需要绘制的边缘数组。
contourldx:需要绘制的边缘索引,如果全部绘制则为-1。
color:绘制的颜色,为BGR格式的Scalar。
thickness:可选,绘制的密度,即描绘轮廓时所用的画笔粗细。```

```python
import cv2
o=cv2.imread(r'D:\image\content.png')
#转换成灰度图像
gray=cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
#将灰度转换成二值图像
ret,binary=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
#查找轮廓
contours,hierarchy=cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#绘制轮廓,改变了原图像
#r=cv2.drawContours(o,contours,-1,(2,255,0),6)  #修改第三个参数可以指定绘制图像中的一个图像轮廓,把-1改成5,便只绘制圆

#绘制轮廓,不改变原始图像
co=o.copy()  #将原始图像复制一份,则绘制的时候便是绘制在复制的轮廓上
r=cv2.drawContours(co,contours,-1,(255,0,0),2)   #第四个参数修改颜色,(0,255,0)是绿色,(255,0,0)蓝色,(0,0,255)红色
#第五个参数是修改轮廓大小,
cv2.imshow('o',o)
cv2.imshow('r',r)
cv2.waitKey()
cv2.destroyAllWindows()
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值