opencv图像处理—python(一)
目录
一、综述
提到图像处理,首先你会想到什么?对我来说,首先我会关注的是图像增强,图像增强的目的是强调图像的整体或局部特性,将原来不清晰的图像变得清晰或强调某些感兴趣的特征,扩大图像中不同物体特征之间的差别,抑制不感兴趣的特征,使之改善图像质量、丰富信息量,加强图像判读和识别效果,满足某些特殊分析的需要。我始终相信学图像的目的是为了解决图像上面的问题,例如去雾,去雨,去模糊等解决图像的疑难杂症问题。图像增强用到的方法很多,其中就包括利用图像平滑处理、图像形态学运算、漫水填充算法、图像的尺寸大小调整、以及图像融合常用到的图像金字塔、阈值化等操作,这些都是我们会经常使用的图像处理方法。
二、平滑处理
“平滑处理”也称作是“模糊处理”,是一项简单并且使用率很高的图像处理方法。平滑处理的用途有很多,但是最常见的是用来减少图像上的噪声或者是失真现象,降低图像分辨率是,平滑处理时很重要的。这里介绍的有2D滤波器、均值滤波、高斯滤波、中值滤波、双边滤波。
1、2D滤波器cv2.filter2D( )
使用自定义内核对图像进行卷积。该功能将任意线性滤波器应用于图像。支持就地操作。当光圈部分位于图像外部时,该功能会根据指定的边框模式插入异常像素值。
cv2.filter2D(src,dst,kernel,auchor=(-1,-1))函数:
#输出图像与输入图像大小相同
#中间的数为-1,输出数值格式的相同
code:
import cv2
import numpy as np
def main():
I=cv2.imread('E:\\car\\lena.jpg')
if I is None:
return -1
kernel = np.array((
[0.0625, 0.125, 0.0625],
[0.125, 0.25, 0.125],
[0.0625, 0.125, 0.0625]), dtype="float32")
I1=cv2.filter2D(I,-1,kernel)
cv2.imshow('I1',I1)
cv2.waitKey(0)
return 0
if __name__=="__main__":
main()
左原图右结果图
2、均值滤波cv2.blur()
均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标像素为中心的周围8个像素,构成一个滤波模板,即包括目标像素本身),再用模板中的全体像素的平均值来代替原来像素值。缺陷:均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。特别是椒盐噪声。
I1 = cv2.blur(img, 模板大小)
code:
import cv2
import numpy as np
def main():
img=cv2.imread('E:\\car\\lena.jpg')
if I is None:
return -1
I1 = cv2.blur(img, (5,5))
cv2.imshow('I1',I1)
cv2.waitKey(0)
return 0
if __name__=="__main__":
main()
左原图右结果图
均值滤波的模板越大图像越模糊。
3、高斯滤波cv2.GaussianBlur()
高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。 通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。
I1 = cv2.GaussianBlur(img,模板尺寸,高斯核)
code:
import cv2
import numpy as np
def main():
img=cv2.imread('E:\\car\\lena.jpg')
if I is None:
return -1
I1 = cv2.GaussianBlur(img,(5,5),10)
cv2.imshow('I1',I1)
cv2.waitKey(0)
return 0
if __name__=="__main__":
main()
左原图右结果图
4、中值滤波cv2.medianBlur()
中值滤波是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。
I1 = cv2.medianBlur(noise_img,5)
code:
import cv2
import numpy as np
import random
def salt_and_pepper_noise(img, proportion=0.05):
noise_img =img
height,width =noise_img.shape[0],noise_img.shape[1]
num = int(height*width*proportion)#多少个像素点添加椒盐噪声
for i in range(num):
w = random.randint(0,width-1)
h = random.randint(0,height-1)
if random.randint(0,1) ==0:
noise_img[h,w] =0
else:
noise_img[h,w] = 255
return noise_img
def main():
img=cv2.imread('E:\\car\\lena.jpg')
if I is None:
return -1
noise_img = salt_and_pepper_noise(img)
cv2.imshow('noise_img',noise_img)
I1 = cv2.medianBlur(noise_img,5)
cv2.imshow('I1',I1)
cv2.waitKey(0)
return 0
if __name__=="__main__":
main()
噪声图像核中值滤波后图像
中值滤波对解决椒盐噪声的图像效果较好。
5、双边滤波cv2.bilateralFilter()
双边滤波是非常常用的一种滤波,在前面我们已经实现了三种滤波:均值滤波、高斯滤波与中值滤波。这三种滤波都能够在一定程度上消除噪声,但是其作用范围有限,只能针对特定种类的噪声。例如高斯滤波针对高斯噪声效果较好,而中值滤波针对椒盐噪声的效果较好。而且,这三种滤波对图像的边缘信息都会有不同程度的损坏,究其原因是没有考虑到图像边缘的信息。因而,我们引入双边滤波,其在利用高斯滤波去噪的同时,能够较好地保存图片的边缘信息。
dst = cv2.bilateralFilter(src=image, d=0, sigmaColor=100, sigmaSpace=15)
其中各参数所表达的意义:
src:原图像;
d:像素的邻域直径,可有sigmaColor和sigmaSpace计算可得;
sigmaColor:颜色空间的标准方差,一般尽可能大;
sigmaSpace:坐标空间的标准方差(像素单位),一般尽可能小。
一般而言,区分图像是否为边缘部分的方法如下:
- 在图像的边缘部分,像素值的变化较为剧烈。
- 在图像的非边缘区域,像素值的变换较为平坦。
首先看双边滤波的公式:
其中,Wp为:
首先我们要知道,双边滤波中有两个衡量图像信息的核心变量,如上式中的Gσs为空间域核,Gσr为图像像素域核。空间域核其实就是二维高斯函数,可以把它视作高斯滤波,像素域核就是衡量像素变化剧烈程度的量。将这两个变量相乘,就可以得到他们俩共同作用的结果:在图像的平坦区域,像素值变化很小,对应的像素范围域权重接近于1,此时空间域权重起主要作用,相当于进行高斯模糊;在图像的边缘区域,像素值变化很大,像素范围域权重变大,从而保持了边缘的信息。
那么具体怎么求解图像的双边滤波呢?首先我们需要知道空间域核计算方法:
以及像素域核的计算方法:
在上面两个式子中,σs与σr都是已知的,或者说是自己输入的预设值,而其他的i,j,m,n都是需要我们在遍历中确定的值。其中(i,j)代表是窗口中心值,(m,n)代表的是滑动窗口中的某个值。
code:
import cv2
import numpy as np
def main():
img=cv2.imread('E:\\car\\lena.jpg')
if I is None:
return -1
cv2.imshow('img',img)
I1 = cv2.bilateralFilter(img,9,75,75)
cv2.imshow('I1',I1)
cv2.waitKey(0)
return 0
if __name__=="__main__":
main()
原图和双边滤波后图像