OpenCV——第二课 图像处理(2)

图像处理

Canny边缘检测

图像的边缘一般指图像局部区域亮度变化显著的部分,而边缘检测主要是图像的灰度变化的检测和定位。Canny边缘检测主要分为以下几步:

  1. 由于图像边缘非常容易收到噪声的干扰,为了避免检测到错误的边缘信息,因此对图像应用高斯滤波以平滑一些非边缘区域,并去除噪声。这里注意,卷积核越大边缘信息对于噪声的敏感度越低,但是定位错误也会随之增加,一般选用5x5的即可
  2. 梯度的方向一般总是与边界垂直,方向被归为四类:垂直、水平和两个对角线。接着需要找到边界的梯度和方向。首先利用sobel算子返回水平方向的Gx和垂直方向的Gy。梯度的幅度 G = ( G x 2 + G y 2 ) G=\sqrt(G_x^2+G_y^2) G=( Gx2+Gy2)和方向 θ = arctan ⁡ ( G y / G x ) θ=\arctan(G_y/G_x) θ=arctan(Gy/Gx),一般就近取方向(上、下、左、右、左上、左下、右上、右下),八个方向取一个。
  3. 遍历图像中的所有点,去除所有非边缘的点,即边缘细化,遍历时,如果该点是正/负梯度方向(梯度方向相反的方向)上的局部最大值,则保留该点,如果不是。则抑制该点(像素值归零)
  4. 对于由于噪声产生的虚边缘必须将其剔除,因此设置两个阈值(maxVal、minVal,这两个值不是固定的,不同的图像阈值不同),根据当前边缘像素的梯度幅度与阈值的关系判断属性,具体判定如下:
    (1)梯度值小于minVal的,直接抛弃
    (2)梯度值在minVal和maxVal之间的,要看该像素所在边缘是否存在大于maxVal的像素点,若有则保留,否则抛弃
    (3)梯度值大于maxVal的,直接保留

Canny函数的基本语法:

edges = cv.Canny( image, minVal, maxVal, apertureSize, L2gradient)

一般只需使用前三个参数:image、minVal、maxVal,对于minVal和maxVal,两者表示的范围更小,获取的元素更仔细更多,当指定值更大时,边界更少,指定值更小时,元素更丰富。

图像金字塔

图像金字塔是同一图像不同分辨率的子图集合,是通过高分辨率的图像产生低分辨率的近似图像

向下采样

最简单的图像金字塔可以通过不断的删除图像的偶数行和偶数列得到的。例如,一幅图像,其大小是NN,删除其偶数行和偶数列后得到一幅(N/2)(N/2)大小的图像,经过上述处理后,图像的大小变为原来的四分之一,以此类推,就可得到该图像的图像金字塔。

典型代表为高斯金字塔,即每一层都是通过高斯滤波和1/2采样得到的,高斯滤波器可以看作一个低通滤波器,那么每经过一次的高斯滤波,图像中仅能保留某个频率值以下的频率部分,所以会丢失很多高频信号。

向下采样使用pyDown函数实现,具体语法如下:

dst = cv2.pyrDown(src [, dstsize [, borderType] ])
  • dst表示输出图像
  • src表示原始图像
  • dstsize表示图像大小
  • borderType表示边界类型

向上采样

和向下采样相反,向上采样是放大,即在结果图像中补充大量的像素点,对新生成的像素点进行赋值,通常是在每列像素点的右侧和每行像素点的下方插入。

典型代表就是拉普拉斯金字塔,可以对图像进行最大程度的还原,恢复高频部分。

向上采样使用pyrUp函数,语法同向下采样一样。

:向上采样和向下采样是相反的两种操作,但是,由于上下采样丢失像素值,所以两种操作并不可逆

图像轮廓

图像轮廓是具有相同颜色或灰度的连续点的曲线,主要用于图形分析和物体的识别与检测。

  • 为了提高准确率,需要先二值化或者canny处理。
  • 画轮廓会修改输入图像,所以为了防止原图被破坏,首先应该拷贝,对拷贝的图像处理。

查找轮廓

使用findContours()函数查找轮廓,基本语法如下:

binary, contours, hierarchy = cv2.findContours(image, mode,method,contours,hierarchy,offset)
  • 返回三个值,binary表示返回的二值图像,contours保存的是获取的轮廓信息,hierarchy表示层级,每一个轮廓保存到不同的层级
  • mode表示查找轮廓的模式,
    • RETR_EXTERNAL,表示只检测外轮廓
    • RETR_LIST,检测所有轮廓,不建立等级关系,并保存到同一条链表中
    • RETR_CCOMP,检测所有轮廓,并分为两层,顶层为各部分的外部边界,第二层是空洞的边界
    • RETR_ TREE,检索所有的轮廓,并重构嵌套轮廓的整个层次
  • method表示轮廓逼近方法
    • CHAIN_APPROX_NONE,以Freeman链码的方式输出轮廓,保存所有轮廓上的点
    • CHAIN_APPROX_SIMPLE,只保存角点,例如四边形的四个顶点
  • contours和hierarchy表示返回的轮廓和层级(也可以直接用返回值接收)

使用drawContours函数绘制图像,基本语法如下:

drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])
  • image 要绘制的轮廓图像

  • contours轮廓点(由findContours查找到的数据)

  • contourIdx 要绘制的轮廓的编号. -1 表示绘制所有轮廓,而其他值则按顺序选择轮框,有内框和外框(0表示第一个内框,1表示第一个外框,以此类推)

  • color 轮廓的颜色, 如 (0, 0, 255)表示红色

  • thickness线宽,即轮廓的宽度, -1 表示全部填充

轮廓特征

轮廓面积是指每个轮廓中所有的像素点围成区域的面积,这里主要通过轮廓面积的大小进一步分析轮廓隐含的信息,例如可以通过面积或者周长过滤细小的轮廓。

  • countourArea(contour),计算轮廓面积,contour表示轮廓列表中一个具体的轮廓
  • arcLength(arc,closed),curve表示轮廓,closed表示是否是闭合的轮廓,True为闭合的轮廓,反之为False

轮廓近似

由于查找轮廓的contours可能过于复杂不平滑,可以用approxPolyDP函数对多边形做近似处理,即轮廓的多边形逼近,采用的是Douglas—Peucks算法,该算法核心就是不断找多边形最远的点加入新的多边形。具体步骤如下:

  1. 在曲线首尾两点A、B之间连接一条直线AB,该直线为曲线的弦
  2. 取曲线上距离AB最远的点C,计算与AB的距离d
  3. 比较d与预先给定的阈值threshold的大小,如果小于该阈值,则直线段作为曲线的近似,则算法执行完毕,如果大于,则将AB分为AC和CB,并分别对两段执行1-3的步骤
  4. 所有曲线处理完后,依次连接各个分割点形成的折线,即可作为近似曲线。

approxPolyDP函数,基本语法如下:

approx = approxPolyDP(curve, epsilon, closed[, approxCurve])
  • approx返回的轮廓
  • curve要近似逼近的轮廓
  • epsilon即DP算法使用的阈值,阈值越小,效果越好
  • closed表示轮廓是否闭合,True或者False

外接图形

针对外接矩形,有最小(minAreaRect(points))和最大(boundingRect(points))两种外接矩形,返回的为元组,内容为矩形的起始坐标x,y和矩形的宽度和高度,和矩形的选择角度,points为输入的轮廓
外接圆使用函数minEnclosingCircle(cnt), cnt为输入轮廓,返回的为元组,分别为圆心坐标x,y和园的半径R

直方图

在OpenCV中,我们可以使用直方图对我们图像的像素点进行统计操作,横坐标表示像素点的大小区间0-255,纵坐标表示对于像素大小的个数,通常使用cv2.calcHist()函数,具体语法如下:

cv2.calcHist(images,channels,mask,histSize,ranges)
  • images表示传入图像,格式只能为uint8或者float32,需加中括号
  • channels,[0]表示传入的为灰度图,[0][1][2]表示彩色图像,对应着BGR
  • mask掩模图像,当统计整幅图像时设为None,如果统计某部分的直方图,则制作一个掩模图像并使用它
  • hisSize,bin的数目,使用中括号,表示横坐标的取值数量
  • ranges像素值范围,用中括号表示

直方图均衡化

均衡化的目的是为了增强局部的对比度而不影响整体的对比度,基本原理为:由于像素点之间的差距比较大,缩小各个像素点之间的值的差距,即扩大图像像素值的分布范围,提高图像对比度,如下图:
在这里插入图片描述
左上表格为原始的像素值,右上表格是均衡化之后的像素值,实现过程为下部分的表格。首先计算出各个灰度值的概率,累积概率即小于等于自身灰度值的像素的总概率,然后根据映射计算调整后的灰度值,结果保留整数四舍五入。均衡化使用函数cv2.equalizeHist(img),img为输入灰度图,返回均衡化吧后的图像。

但是在均衡化途中虽然图片变亮了,但是会丢失一些细节,因此我们可以使用自适应均衡化的操作。自适应均衡化通过计算图像的局部直方图,然后重新分布亮度来改变图像对比度,自适应均衡化是将图像分为多个同样大小的块,对每个块进行均衡化,所有块处理完后即所得图像,使用函数cv2.createCLAHE(clipLimit = 40,titleGridSize = (8,8)),第一个参数表示对比度限制,默认为40,第二个参数为分块大小,默认为8*8,下图分别为原图,均衡化,自适应均衡化:
在这里插入图片描述

模板匹配

模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与(被模板覆盖的区域)的差别,这个差别程度的计算方法在OpenCv里面有6种,然后将每次计算的结果放入一个矩阵里,作为结果输出,假如原图大小为AxB,而模板大小为axb,则输出结果的矩阵是(A-a+1)x(B-b+1)

差别程度计算方法为:

  • cv2.TM_SQDIFF_NORMED: 该方法使用平方差进行匹配,因此最佳的匹配结果在结果为0处,值越大匹配结果越差
  • cv2.TM_CCORR: 计算相关性,计算的值越大,越相关
  • cv2.TM_CCOEFF:计算相关系数,计算出来的值越大,越相关
  • cv2.TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关
  • cv2.TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关
  • cv2.TM_CCOEDD_MORMED:计算归一化相关系数,计算出来的值越接近1,越相关

一般使用函数matchTemplate(img,template,cv2.TM_SQDIFF),参数分别对应(输入图像,模板,匹配方式),返回的为结果矩阵,对返回的矩阵,使用函数cv2.minMaxLoc()可以返回匹配过程中的最小值,最大值,最小值的位置(x,y),最大值的位置(x,y)

傅里叶变换

图像处理一般分为空间域处理和频率域处理,空间域处理是直接对图像内的像素进行处理。空间域处理主要划分为灰度变换和空间滤波两种形式。

  • 灰度变换是对图像内的单个像素进行处理
  • 空间滤波是对图像质量的改变

而频率处理是先将图像变换到频率域,然后在频率域对图像进行处理,最后通过反变换将图像频率变换到空间滤。

在图像处理中,傅里叶变换就是将图像分解为正弦分量和余弦分量两部分,即将图像从空间域转换到频域,而频域的值是复数。因此傅里叶变换的结果需要使用实数图像加虚数图像,或者幅度图像加相位图像的形式。

对图像傅里叶变换后,会得到高频和低频信息,低频信息为图像内变化缓慢的灰度分量,高频信息对应变化快的灰度分量。傅里叶变换可以实现图像增强、图像去噪、边缘检测、特征提取、图像压缩和加密等。

OpenCV中提供了函数cv2.dft()和cv2.idft()实现傅里叶变换
cv2.dft()将图像转换为频率值,基本语法如下:

result=cv2.dft(img,tag)
  • img表示原始图像,首先需要使用np.float32()函数将图像转换成np.float32格式
  • tag表示转换标识,通常为cv2.DFT_COMPLEX_OUTPUT,用来输出一个复数阵列
  • 返回的结果为双通道值,第一个通道为实数部分,第二部分为虚数部分

经过dft()函数后,得到了原始图像的频谱信息,此时需要将零频率分量移到频谱中心,得到位于中心的零频率的频谱图像

dftshift=np.fft.fftshift(dft)

频谱图像还只是一个由实部和虚部构成的值,接着将其显现出来,需要函数cv2.magnitude( )

result=cv2.magnitude(x,y)
  • x表示浮点型x坐标值,也就是实部,y表示浮点型y坐标值,也就是虚部,长度要和x相同
  • 返回值为x和y的平方根

得到频谱信息后,通常还要对幅度值进一步的转换,以便展示出来,即将幅度值映射到灰度图像的灰度空间[0,255]以内,使其以灰度的形式显示出来,公式为:

result=20*numpy.log(cv2.magnitude(x
,y))

在逆变换之前,需要将零频率分量恢复到原来位置,即使用函数numpy.fft.ifftshift(data),接着傅里叶逆变换使用 idft() 函数,语法格式为:

result=cv2.idft(data)

总结来说,首先用傅里叶变换,得到频谱图像,然后,在频域内将高频分量处理为0,实现低通滤波,最后实现逆傅里叶变换,得到恢复的原始图像。经过低通滤波后,图像的信息会被削弱,变得更加模糊了。

总结

到此。图像的基本处理方法到此为止,下面将通过项目实战来检验所学。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zero3_msh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值