一、几何变换–仿射变换、透射变换
1.仿射变换
(1)概念
图像的仿射变换涉及到图像的形状位置角度的变化,是深度学习预处理中常到的功能,仿射变换主要是对图像的缩放,旋转,翻转和平移等操作的组合。
(2)仿射变换理解:
那什么是图像的仿射变换,如下图所示,图1中的点1, 2 和 3 与图二中三个点一一映射, 仍然形成三角形, 但形状已经大大改变,通过这样两组三点(感兴趣点)求出仿射变换, 接下来我们就能把仿射变换应用到图像中所有的点中,就完成了图像的仿射变换。
代码:
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
# 读取图片
img = cv.imread("./image/yangzi.jpg")
plt.imshow(img[:,:,::-1])
# 仿射变换
rows,cols = img.shape[:2]
# 仿射变换矩阵
# [[50,50],[200,50],[50,200]]:在原图上找三点构成矩阵
# [100,100],[200,50],[100,250]:仿射后的图的三点坐标构成矩阵
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[100,100],[200,50],[100,250]])
# 仿射的矩阵
M = cv.getAffineTransform(pts1,pts2)
# 完成仿射变换
dst = cv.warpAffine(img,M,(cols,rows))
plt.imshow(dst)
2.透射变换
(1)理解:
透射变换是视角变化的结果,是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面(透视面)绕迹线(透视轴)旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换。
代码示例:
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
# 读图
img = cv.imread("./image/yangzi.jpg")
plt.imshow(img[:,:,::-1])
# 透射变换
# 获取行列
rows,cols = img.shape[:2]
# 创建变换矩阵
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[100,165],[300,152],[128,220],[345,233]])
# 创建变换矩阵
T = cv.getPerspectiveTransform(pts1,pts2)
dst = cv.warpPerspective(img,T,(cols,rows))
plt.imshow(dst[:,:,::-1])
3.图像金字塔
(1)理解:
图像金字塔是图像多尺度表达的一种,最主要用于图像的分割,是一种以多分辨率来解释图像的有效但概念简单的结构。
图像金字塔用于机器视觉和图像压缩,一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低,且来源于同一张原始图的图像集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。
金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似,层级越高,图像越小,分辨率越低。
(2)API
cv.pyrUp(img) #对图像进行上采样
cv.pyrDown(img) #对图像进行下采样
代码:
import matplotlib.pyplot as plt
import numpy as np
import cv2 as cv
img = cv.imread("./image/yangzi.jpg")
plt.imshow(img[:,:,::-1])
#对图像进行上采样
up_img = cv.pyrUp(img)
plt.imshow(up_img[:,:,::-1])up_img1 = cv.pyrUp(up_img)
plt.imshow(up_img1[:,:,::-1])#对图像进行下采样
down_img = cv.pyrDown(img)
plt.imshow(down_img[:,:,::-1])down_img1 = cv.pyrDown(down_img)
plt.imshow(down_img1[:,:,::-1])down_img2 = cv.pyrDown(down_img1)
plt.imshow(down_img2[:,:,::-1])
4.总结
图像缩放:对图像进行放大或缩小cv.resize()图像平移:指定平移矩阵后,调用cv.warpAffine()平移图像图像旋转:调用cv.getRotationMatrix2D获取旋转矩阵,然后调用cv.warpAffine()进行旋转仿射变换:调用cv.getAffineTransform将创建变换矩阵,最后该矩阵将传递给cv.warpAffine()进行变换透射变换:通过函数cv.getPerspectiveTransform()找到变换矩阵,将cv.warpPerspective()进行投射变换金字塔图像金字塔是图像多尺度表达的一种,使用的API:cv.pyrUp(): 向上采样cv.pyrDown(): 向下采样
二、形态学操作
1.图像的邻域、连通性
在图像中,最小的单位是像素,每个像素周围有8个邻接像素,常见的邻接关系有3种:4邻接、8邻接和D邻接。分别如下图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201122192845900.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NTk1MTM4,size_16,color_FFFFFF,t_70#pic_center
4邻接:像素p(x,y)的4邻域是:(x+1,y);(x-1,y);(x,y+1);(x,y-1),用N4(p)N_4(p)N?4??(p)表示像素p的4邻接
8邻接:像素p(x,y)的8邻域是: 4邻域的点 + D邻域的点,用N8§N_{8}§N?8??§表示像素p的8邻域
D邻接:像素p(x,y)的D邻域是:对角上的点 (x+1,y+1);(x+1,y-1);(x-1,y+1);(x-1,y-1),用ND§N_D§N?D??§表示像素p的D邻域
连通性是描述区域和边界的重要概念,两个像素连通的两个必要条件是:
两个像素的位置是否相邻
两个像素的灰度值是否满足特定的相 似性准则(或者是否相等
根据连通性的定义,有4联通、8联通和m联通三种。
4联通:对于具有值VVV的像素ppp和qqq,如果qqq在集合N4§N_4§N?4??§中,则称这两个像素是4连通。
8联通:对于具有值VVV的像素ppp和qqq,如果qqq在集 合N8§N_8§N?8??§中,则称这两个像素是8连通。
2、形态学操作
形态学转换是基于图像形状的一些简单操作。它通常在二进制图像上执行。腐蚀和膨胀是两个基本的形态学运算符。然后它的变体形式如开运算,闭运算,礼帽黑帽等。
(1)腐蚀
具体操作是:用一个结构元素扫描图像中的每一个像素,用结构元素中的每一个像素与其覆盖的像素做“与”操作,如果都为1,则该像素为1,否则为0。如下图所示,结构A被结构B腐蚀后:腐蚀过程:
第一次进行计算:
第二次进行计算:
以此类推…
作用:腐蚀的作用是消除物体边界点,使目标缩小,可以消除小于结构元素的噪声点。
API:
cv.erode(img,kernel,iterations)
参数:
img: 要处理的图像
kernel: 核结构
iterations: 腐蚀的次数,默认是1
(2)膨胀
具体操作是:用一个结构元素扫描图像中的每一个像素,用结构元素中的每一个像素与其覆盖的像素做“与”操作,如果都为0,则该像素为0,否则为1。如下图所示,结构A被结构B腐蚀后:
作用是将与物体接触的所有背景点合并到物体中,使目标增大,可添补目标中的孔洞。
API:
cv.dilate(img,kernel,iterations)
参数:
img: 要处理的图像kernel: 核结构
iterations: 腐蚀的次数,默认是1示例
我们使用一个5*5的卷积核实现腐蚀和膨胀的运算:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread("./image/yangzi.jpg")
plt.imshow(img[:,:,::-1])
kernel = np.ones((5,5),np.uint8)
#图像腐蚀
erosion = cv.erode(img,kernel)
plt.imshow(erosion[:,:,::-1])
#膨胀
dilate = cv.dilate(img,kernel)
plt.imshow(dilate[:,:,::-1])
3.开闭运算
(1)开运算
开运算和闭运算是将腐蚀和膨胀按照一定的次序进行处理。 但这两者并不是可逆的,即先开后闭并不能得到原来的图像。
开运算
开运算是先腐蚀后膨胀,其作用是:分离物体,消除小区域。特点:消除噪点,去除小的干扰块,而不影响原来的图像。
(2)闭运算
闭运算与开运算相反,是先膨胀后腐蚀,作用是消除/“闭合”物体里面的孔洞,特点:可以填充闭合区域。
API
cv.morphologyEx(img, op, kernel)
参数:
img: 要处理的图像
op: 处理方式:若进行开运算,则设为cv.MORPH_OPEN,若进行闭运算,则设为cv.MORPH_CLOSE
Kernel: 核结构
示例
使用10*10的核结构对卷积进行开闭运算的实现。
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread("./image/yangzi.jpg")
plt.imshow(img[:,:,::-1])
# 创建核结构
kernel = np.ones((10,10),np.uint8)
# 开运算
cvOpen = cv.morphologyEx(img,cv.MORPH_OPEN,kernel)
# 闭运算
cvClose = cv.morphologyEx(img,cv.MORPH_CLOSE,kernel)
# 展示对比
fig,axes = plt.subplots(nrows=2,ncols=2,figsize=(10,8))
axes[0,0].imshow(img[:,:,::-1])
axes[0,0].set_title("原因")
axes[0,1].imshow(cvOpen[:,:,::-1])
axes[0,1].set_title("开运算结果")
axes[1,0].imshow(img[:,:,::-1])
axes[1,0].set_title("原因")
axes[1,1].imshow(cvClose[:,:,::-1])
axes[1,1].set_title("闭运算结构")
plt.show()
运行结果:
4.礼貌和黑帽
(1)礼帽运算
礼帽运算
原图像与“开运算“的结果图之差,如下式计算:
因为开运算带来的结果是放大了裂缝或者局部低亮度的区域,因此,从原图中减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且这一操作和选择的核的大小相关。
礼帽运算用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。
(2)黑帽运算
为”闭运算“的结果图与原图像之差。数学表达式为:
黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。
黑帽运算用来分离比邻近点暗一些的斑块。
参数:
img: 要处理的图像op: 处理方式:
代码:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 读取图像
img = cv.imread("./image/yangzi.jpg")
plt.imshow(img[:,:,::-1])
kernel = np.ones((10,10),np.uint8)
cvOpen = cv.morphologyEx(img,cv.MORPH_TOPHAT,kernel)
cvClose = cv.morphologyEx(img,cv.MORPH_BLACKHAT,kernel)
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,8))
axes[0,0].imshow(img[:,:,::-1])
axes[0,0].set_title("原图")
axes[0,1].imshow(cvOpen[:,:,::-1])
axes[0,1].set_title("礼帽运算结果")
axes[1,0].imshow(img[:,:,::-1])
axes[1,0].set_title("原图")
axes[1,1].imshow(cvClose[:,:,::-1])
axes[1,1].set_title("黑帽运算结果")
plt.show()
5.形态学操作总结
连通性 邻接关系:4邻接,8邻接和D邻接
连通性:4连通,8连通和m连通
形态学操作
腐蚀和膨胀:
腐蚀:求局部最大值
膨胀:求局部最小值
开闭运算:
开:先腐蚀后膨胀
闭:先膨胀后腐蚀
礼帽和黑帽:
礼帽:原图像与开运算之差
黑帽:闭运算与原图像之差
三、图像平滑
1.图像噪声
概念:由于图像采集、处理、传输等过程不可避免的会受到噪声的污染,妨碍人们对图像理解及分析处理。
分类:图像噪声有高斯噪声、椒盐噪声等。
(1)椒盐噪声
概念:亮的区域有黑色像素或是在暗的区域有白色像素(或是两者皆有)。
成因:可能是影像讯号受到突如其来的强烈干扰而产生、类比数位转换器或位元传输错误等。例如失效的感应器导致像素值为最小值,饱和的感应器导致像素值为最大值。
(2)高斯噪音
概念:高斯噪声是指噪声密度函数服从高斯分布的一类噪声。
理解:由于高斯噪声在空间和频域中数学上的易处理性,这种噪声(也称为正态噪声)模型经常被用于实践中。高斯随机变量z的概率密度函数由下式给出:
z:表示灰度值
μ:表示z的平均值或期望值
σ:表示z的标准差
σ^2??:标准差的平方??称为z的方差
高斯函数的曲线如图所示。
高斯噪声的图
2.图像平滑
概念:图像平滑从信号处理的角度看就是去除其中的高频信息,保留低频信息。因此我们可以对图像实施低通滤波。低通滤波可以去除图像中的噪声,对图像进行平滑。
分类:根据滤波器的不同可分为均值滤波,高斯滤波,中值滤波, 双边滤波。
(1)均值滤波
**原理:**采用均值滤波板对图像噪声进行滤除,令S_{x y} 表示中心在(x, y)点,尺寸为m×n 的矩形子图像窗口的坐标组,均值滤波器可表示为:
由一个归一化卷积框完成的。它只是用卷积框覆盖区域所有像素的平均值来代替中心元素。
例如,3x3标准化的平均过滤器如下所示:
均值滤波的优点是算法简单,计算速度较快,缺点是在去噪的同时去除了很多细节部分,将图像变得模糊。
API
cv.blur(src, ksize, anchor, borderType)
参数:
src:输入图像
ksize:卷积核的大小
anchor:默认值 (-1,-1) ,表示核中心
borderType:边界类型
代码演示:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread("./image/dogsp.jpeg")
plt.imshow(img[:,:,::-1])
blur = cv.blur(img,(5,5))
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1]),plt.title("原图")
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(blur[:,:,::-1]),plt.title("均值滤波后的结果")
plt.xticks([]),plt.yticks([])
plt.show()
(2)高斯滤波
二维高斯是构建高斯滤波器的基础,其概率分布函数如下所示:
G(x,y)的分布是一个突起的帽子的形状。这里的σ可以看作两个值,一个是x方向的标准差σx,另一个是y方向的标准差σy??。
当σx\sigma_xσ?x??和σy\sigma_yσ?y??取值越大,整个形状趋近于扁平;当σx\sigma_xσ?x??和σy\sigma_yσ?y??,整个形状越突起。
正态分布是一种钟形曲线,越接近中心,取值越大,越远离中心,取值越小。计算平滑结果时,只需要将"中心点"作为原点,其他点按照其在正态曲线上的位置,分配权重,就可以得到一个加权平均值。
高斯平滑在从图像中去除高斯噪声方面非常有效。
高斯平滑的流程:
1.首先确定权重矩阵
假定中心点的坐标是(0,0),那么距离它最近的8个点的坐标如下:
更远的点以此类推。
为了计算权重矩阵,需要设定σ的值。假定σ=1.5,则模糊半径为1的权重矩阵如下:
这9个点的权重总和等于0.4787147,如果只计算这9个点的加权平均,还必须让它们的权重之和等于1,因此上面9个值还要分别除以0.4787147,得到最终的权重矩阵。
2.计算高斯模糊
有了权重矩阵,就可以计算高斯模糊的值了。
假设现有9个像素点,灰度值(0-255)如下:
每个点乘以对应的权重值:
每个点乘以对应的权重值:
得到
将这9个值加起来,就是中心点的高斯模糊的值。
对所有点重复这个过程,就得到了高斯模糊后的图像。如果原图是彩色图片,可以对RGB三个通道分别做高斯平滑。
API
cv2.GaussianBlur(src,ksize,sigmaX,sigmay,borderType)
参数:
src: 输入图像
ksize:高斯卷积核的大小,注意 : 卷积核的宽度和高度都应为奇数,且可以不同
sigmaX: 水平方向的标准差
sigmaY: 垂直方向的标准差,默认值为0,表示与sigmaX相同
borderType:填充边界类型
代码演示:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread("./image/dogGauss.jpeg")
plt.imshow(img[:,:,::-1])
# 高斯滤波
blur = cv.GaussianBlur(img,(3,3),1)
# 图像显示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1]),plt.title("原图")
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(img[:,:,::-1]),plt.title("高斯滤波后的图")
plt.xticks([]),plt.yticks([])
plt.show()
(3)中值滤波
概念:中值滤波是一种典型的非线性滤波技术,基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值。
中值滤波对椒盐噪声(salt-and-pepper noise)来说尤其有用,因为它不依赖于邻域内那些与典型值差别很大的值。
API:
cv.medianBlur(src, ksize )
参数:
src:输入图像
ksize:卷积核的大小
代码演示:
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
img = cv.imread("./image/dogsp.jpeg")
plt.imshow(img[:,:,::-1])
# 中值滤波
blur = cv.medianBlur(img,5)
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1]),plt.title("原图")
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(blur[:,:,::-1]),plt.title("中值滤波后的图")
plt.xticks([]),plt.yticks([])
plt.show()
3.图像平滑总结
图像噪声
椒盐噪声:图像中随机出现的白点或者黑点
高斯噪声:噪声的概率密度分布是正态分布
图像平滑
均值滤波:算法简单,计算速度快,在去噪的同时去除了很多细节部分,将图像变得模糊
cv.blur()
高斯滤波: 去除高斯噪声
cv.GaussianBlur()
中值滤波: 去除椒盐噪声
cv.medianBlur()
四、直方图
1.灰度直方图
原理:
2.直方图均衡化
3.直方图总结:
灰度直方图:直方图是图像中像素强度分布的图形表达方式。 它统计了每一个强度值所具有的像素个数。
不同的图像的直方图可能是相同的
cv.calcHist(images,channels,mask,histSize,ranges [,hist [,accumulate]])
掩膜
创建蒙版,透过mask进行传递,可获取感兴趣区域的直方图
直方图均衡化:增强图像对比度的一种方法
cv.equalizeHist(): 输入是灰度图像,输出是直方图均衡图像
自适应的直方图均衡
将整幅图像分成很多小块,然后再对每一个小块分别进行直方图均衡化,最后进行拼接
clahe = cv.createCLAHE(clipLimit, tileGridSize)