# coding : utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt
'''
第16章:图像平滑
2D卷积:对2D图像实施低通滤波(LPF,Low Pass Filter),可以去除噪音,模糊图像
高通滤波(HPF)可以找到图像的边缘
cv.filter2D()对图像进行卷积操作。
卷积:是一种运算,将两个函数f和g生成第三个函数的数学算子(一个函数空间到另一个函数空间的映射,例如微分算子),
表征函数f与经过翻转和平移的g的重叠部分的累积
参见文章:http://blog.sina.com.cn/s/blog_881535bf0101fqib.html
函数f 与g 的卷积记作f * g,它是其中一个函数翻转并平移后与另一个函数的乘积的积分,是一个对平移量的函数。
(f * g )(t) = 积分f(x) g(t - x)dx
图解卷积:
1将两个函数都用x表示
2对其中一个函数做水平翻转:g(x)->g(-x)
3加上一个事件偏移量,让g(t-x)随着x轴移动
4让t从负无穷滑动到正无穷,两个函数交会时
下面使用平均滤波器,5*5
1 1 1 1 1
1 1 1 1 1
K=1/25 1 1 1 1 1
1 1 1 1 1
将核放在图像的像素A上,求与核对应的图像上25(5*5)个像素的和,再取平均数
用平均数代替像素A的值,重复以上操作直到将图像的每一个像素值都更新一遍
'''
def convolution():
img = cv2.imread("opencv_logo.png")
'''
numpy.ones(shape,dtype=None):
shape是(行数,列数),即(高度,宽度)
dtype:数据类型,例如 np.float32
'''
kernel = np.ones((5,5) , np.float32) / 25
'''
cv2.filter2D(src,ddepth , kernel)
ddepth:要求的目标图像的深度,如果为-1,表示与原图像深度相同
kernel:卷积核,实质是一个矩阵。卷积时使用到的权用一个矩阵表示,该矩阵与使用的图像区域大小相同,行列都是奇数,是一个矩阵
'''
dst = cv2.filter2D(img , -1 , kernel)
plt.subplot(121),plt.imshow(img),plt.title("Original Image")
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(dst),plt.title("Average Convolution")
plt.xticks([]),plt.yticks([])
plt.show()
'''
图像模糊(图像平滑)
低通滤波器可以模糊图像,去除噪音(高频成分,边界会被模糊)
平均:归一化卷积框完成。用卷积框覆盖区域所有像素的平均值来代替中心元素,使用函数cv2.blur()
cv2.boxFilter(),需要设定卷积框的宽和高
下面是3*3的归一化卷积框
1 1 1
K=1/9 1 1 1
1 1 1
如果不想使用归一化卷积框,应该使用cv2.boxFilter(),传入参数normalize=False
'''
def averageConvolution():
img = cv2.imread("opencv_logo.png")
'''
cv2.blur(src,ksize[,dst[,anchor[,borderTyppe]]])->dst
作用:使用核来平滑(模糊)图像
ksize:是包含宽度和高度的二元组。例如(3,3)
anchor:锚点,中心点,默认为(-1,-1)则会选取核的中心点
borderType:边界模式用于推断图像外的像素
K=/(ksize.width * ksize.height)[1 1 ...1]
[1 1 ...1]
[1 1 ...1]
'''
blur = cv2.blur(img , (5,5))
plt.subplot(121),plt.imshow(img),plt.title("Original Image")
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title("Blured Image")
plt.xticks([]),plt.yticks([])
plt.show()
'''
高斯模糊
把卷积和换成高斯核(自我认为是高斯核一个加权矩阵,主要用于乘以原来图像中的像素的值然后求和)
实现的函数是cv2.GaussianBlur(),需要指定高斯核的宽和高,都是奇数,
以及高斯函数沿着x轴和y轴的标准差,也可以使用cv2.getGaussianKernel()自己构建一个高斯核
'''
def GaussianBlur_test():
img = cv2.imread("opencv_logo.png")
#img = cv2.imread("bilateralFilter.jpg")
'''
cv2.GaussianBlur(src,ksize,sigmaX)
kSize:核大小,sigmaX:高斯核在x轴的标准差,如果为0会根据核的宽和高重新计算
'''
blur = cv2.GaussianBlur(img , (5,5) , 0)
plt.subplot(121),plt.imshow(img),plt.title("Original Image")
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title("GaussianBlured Image")
plt.xticks([]),plt.yticks([])
plt.show()
'''
双边滤波:
能保持边界清晰的情况下有效去除噪音,比其他滤波器慢
双边滤波同时使用空间高斯权重和灰度值相似性高斯权重。
空间高斯函数确保只有邻近区域的像素对中心点有影响,灰度值相似性高斯
函数确保只有与中心像素灰度值相近的才会被用来做模糊运算。
cv2.bilateralFilter()
'''
def BilateralFilter_test():
img = cv2.imread("bilateralFilter.jpg")
'''
cv2.bilateralFilter(src,d,sigmaColor,sigmaSpace)
d:过滤中使用的每个像素邻域的直径
sigmaColor:用于颜色过滤,sigmaSpace:用于空间过滤
'''
#9是邻域直径,两个75分别是空间高斯函数标准差,灰度值相似标准差
blur = cv2.bilateralFilter(img , 9 , 75 ,75)
plt.subplot(121),plt.imshow(img),plt.title("Original Image")
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title("BilateralFilter Image")
plt.xticks([]),plt.yticks([])
plt.show()
'''
中值模糊:用卷积框对应像素的中值代替中心像素的值,用于去除椒盐噪声(黑白相间的亮暗点噪声)
'''
def MedianBlur_test():
img = cv2.imread("opencv_logo_noise.jpg")
'''
cv2.GaussianBlur(src,ksize)
kSize:核大小,是一个大于1的奇数
'''
median = cv2.medianBlur(img , 5)
plt.subplot(121),plt.imshow(img),plt.title("Original Image")
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(median),plt.title("MedianBlured Image")
plt.xticks([]),plt.yticks([])
plt.show()
if __name__ == "__main__":
#convolution()
#averageConvolution()
GaussianBlur_test()
#MedianBlur_test()
#BilateralFilter_test()