Python计算机视觉编程之图像基础处理(灰度图)
前言:
在上学期的数字图像的课程中我们已经初步接触过了数字图像处理这门课程,不同之处在于上学期使用matlab来实现图像的基础处理,
而本门课程中我们使用python+opencv来实现图像处理。使用Pycharm平台进行编程。参考书籍资料:Python计算机视觉编程
灰度图( Gray Scale Image):
把白色与黑色之间按对数关系分为若干等级,称为灰度。灰度分为256阶。
用灰度表示的图像称作灰度图。
任何颜色都由红、绿、蓝三原色(RGB)组成,而灰度图只有一个通道,有256个灰度等级,255代表全白,0表示全黑。
除了常见的卫星图像、航空照片外,许多地球物理观测数据也以灰度表示。
原理介绍:
使用了convert()方法实现图像的颜色转换
PIL中convert('L')函数原理:
-
img = img.convert()
PIL有九种不同模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F。
-
img.convert('1')
为二值图像,非黑即白。每个像素用8个bit表示,0表示黑,255表示白。
-
img.convert('L') #上述代码中用到的即为此
为灰度图像,每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。
转换公式:L = R * 299/1000 + G * 587/1000+ B * 114/1000。
代码展示:
1 # -*- codeing =utf-8 -*- 2 # @Time : 2021/3/7 15:16 3 # @Author : ArLin 4 # @File : demo1灰度图.py 5 # @Software: PyCharm 6 # -*- coding: utf-8 -*- 7 from PIL import Image 8 from pylab import * 9 10 11 # 添加中文字体支持 12 from matplotlib.font_manager import FontProperties 13 font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14) 14 figure() 15 16 17 pil_im = Image.open('data/001.jpg') 18 gray()# 不使用颜色信息 19 subplot(121) 20 title(u'原图',fontproperties=font) 21 axis('off') 22 imshow(pil_im) 23 24 25 pil_im = Image.open('data/001.jpg').convert('L') 26 subplot(122) 27 title(u'灰度图',fontproperties=font) 28 axis('off') 29 imshow(pil_im) 30 31 32 show()
结果展示:
图像轮廓和直方图:
图像轮廓:
轮廓是一系列相连的点组成的曲线,代表了物体的基本外形,相对于边缘,轮廓是连续的,边缘并不全部连续。
寻找轮廓的操作一般用于二值化图,所以通常会使用阈值分割或Canny边缘检测先得到二值图
直方图:
直方图是可以对整幅图的灰度分布进行整体了解的图示,通过直方图我们可以对图像的对比度、亮度和灰度分布等有一个直观了解。
图像的直方图用来表征该图像像素值的分布情况。用一定数目的小区间(bin)来指定表征像素值的范围,每个小区间会得到落入该小区间表示范围的像素数目
原理介绍:
绘制轮廓:
因为绘制轮廓需要对每个坐标[x,y]的像素值设置一个阈值,因此要先将图像灰度化。
绘制直方图:
使用Matplotlib自带的绘制工具plt.hist()绘制。
代码展示:
1 # -*- codeing =utf-8 -*- 2 # @Time : 2021/3/8 15:09 3 # @Author : ArLin 4 # @File : demo4图像轮廓和直方图.py 5 # @Software: PyCharm 6 # -*- coding: utf-8 -*- 7 from PIL import Image 8 from pylab import * 9 10 11 # 添加中文字体支持 12 from matplotlib.font_manager import FontProperties 13 font = FontProperties(fname=r"d:\JsVison\font\SimSun.ttc", size=14) 14 im = array(Image.open('data/001.jpg').convert('L')) # 打开图像,并转成灰度图像,读取图像到数组中 15 16 #图像轮廓 17 figure() 18 subplot(121) 19 gray()# 不使用颜色信息 20 contour(im, origin='image')# 在原点的左上角显示轮廓图像 21 axis('equal') 22 axis('off') 23 title(u'图像轮廓', fontproperties=font) 24 25 #图像直方图 26 subplot(122) 27 hist(im.flatten(), 128) 28 title(u'图像直方图', fontproperties=font) 29 plt.xlim([0,260]) 30 plt.ylim([0,11000]) 31 32 33 show()
结果展示:
直方图均衡化:
一副效果好的图像通常在直方图上的分布比较均匀,直方图均衡化就是用来改善图像的全局亮度和对比度。
直方图均衡化是指将一幅图像的灰度直方图变平,使变换后的图像中每个灰度值的分布概率都相同。在对图像做进一步处理之前,直方图均衡化通常是对图像灰度值进行归一化的一个非常好的方法,并且可以增强图像的对比度。
原理介绍:
直方图均衡化的变换函数是图像中像素值的累积分布函数(cumulative distribution function,简写为 cdf,将像素值的范围映射到目标范围的归一化操作)。
直方图均衡化的具体实现(imtools中的函数):
该函数中有两个输入参数,一个是灰度图像,一个是直方图中使用小区间的数目。
函数返回直方图均衡化后的图像,以及用来做像素值映射的累积分布函数。
注意,函数中使用到累积分布函数的最后一个元素(下标为 -1),目的是将其归一化到 0...1 范围。
def histeq(im,nbr_bins=256): """ 对一幅灰度图像进行直方图均衡化""" # 计算图像的直方图 imhist,bins = histogram(im.flatten(),nbr_bins,normed=True) cdf = imhist.cumsum() # cumulative distribution function cdf = 255 * cdf / cdf[-1] # 归一化 # 使用累积分布函数的线性插值,计算新的像素值 im2 = interp(im.flatten(),bins[:-1],cdf) return im2.reshape(im.shape), cdf
代码展示:
1 # -*- codeing =utf-8 -*- 2 # @Time : 2021/3/8 15:17 3 # @Author : ArLin 4 # @File : demo8直方图均衡化.py 5 # @Software: PyCharm 6 # -*- coding: utf-8 -*- 7 from PIL import Image 8 from pylab import * 9 from PCV.tools import imtools 10 11 12 # 添加中文字体支持 13 from matplotlib.font_manager import FontProperties 14 font = FontProperties(fname=r"d:\JsVison\font\SimSun.ttc", size=14) 15 16 17 im = array(Image.open('data/001.jpg').convert('L')) # 打开图像,并转成灰度图像 18 im2, cdf = imtools.histeq(im) #上述详解imtools.histeq函数 19 20 21 figure() 22 subplot(2, 2, 1) 23 axis('off') 24 gray() 25 title(u'原始图像', fontproperties=font) 26 imshow(im) 27 28 29 subplot(2, 2, 2) 30 axis('off') 31 title(u'直方图均衡化后的图像', fontproperties=font) 32 imshow(im2) 33 34 35 subplot(2, 2, 3) 36 axis('off') 37 title(u'原始直方图', fontproperties=font) 38 hist(im.flatten(), 128, density=True) 39 40 41 subplot(2, 2, 4) 42 axis('off') 43 title(u'均衡化后的直方图', fontproperties=font) 44 hist(im2.flatten(), 128, density=True) 45 46 47 show()
结果展示:
如图所示,直方图均衡化后图像的对比度增强了,原先图像灰色区域的细节变得清晰。
遇到的问题:
在运用学习Python计算机视觉编程这本书的课程中所示的源码中出现了一个错误
VisibleDeprecationWarning: Passing `normed=True` on non-uniform bins has always been broken, and computes neither the probability density function nor the probability mass function. The result is only correct if the bins are uniform, when density=True will produce the same result anyway. The argument will be removed in a future version of numpy.
hist, _ = np.histogram(lbp, normed=True, bins=max_bins, range=(0, max_bins))
解决方法:将normed替换成density 即可
normed这个关键字在Numpy 1.6中是不赞成的,因为它会导致混乱/有bug的行为。它将在Numpy 2.0中被删除。而是使用density关键字替换。
高斯滤波:
高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。
通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。
原理介绍:
高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。
滤波是对输入信号进行卷积处理的一个过程,写成一个函数的形式是这样的:
滤波 = 卷积( 输入信号 ,卷积模板 ) 卷积模板/掩膜 的不同决定了不同的滤波方式,也因此产生了高通、低通、带通、带阻等基本的滤波方式。
针对低通滤波,就是保留将信号中的低频部分,抑制高频部分。要达到这个目的,可以利用均值掩膜、高斯掩膜等对输入信号进行处理。
采用均值掩膜对输入信号进行卷积的滤波方式叫均值滤波;
采用高斯掩膜对输入信号进行卷积的滤波方式叫高斯滤波;
高斯滤波和高斯模糊
一样。不加“高斯”这个限定词时,滤波的范畴要远远大于模糊,后者只是前者的一个子集。当加上“高斯”限定以后,所指代的卷积操作就是同一个操作了,因为根据方程 滤波 = 卷积( 输入信号 ,卷积模板 ),当两个操作的输入信号和卷积模板都一样时,这两个操作就是一个操作了
那是因为这个滤波的效果看起来像是把图像给弄模糊了,所以又有了“高斯模糊”的叫法。
SciPy(http://scipy.org/) 是建立在 NumPy 基础上,用于数值运算的开源工具包。SciPy 提供很多高效的操作,可以实现数值积分、优化、统计、信号处理,以及对我们来说最重要的图像处理功能。接下来,本节会介绍 SciPy 中大量有用的模块。SciPy 是个开源工具包,可以从 http://scipy.org/Download 下载。
代码展示:
1 # -*- codeing =utf-8 -*- 2 # @Time : 2021/3/8 15:29 3 # @Author : ArLin 4 # @File : demo10高斯模糊.py 5 # @Software: PyCharm 6 # -*- coding: utf-8 -*- 7 from PIL import Image 8 from pylab import * 9 from scipy.ndimage import filters 10 11 12 # 添加中文字体支持 13 from matplotlib.font_manager import FontProperties 14 font = FontProperties(fname=r"d:\JsVison\font\SimSun.ttc", size=14) 15 16 17 #im = array(Image.open('board.jpeg')) 18 im = array(Image.open('data/004.jpg').convert('L')) 19 20 21 figure() 22 gray() 23 axis('off') 24 subplot(1, 4, 1) 25 axis('off') 26 title(u'原图', fontproperties=font) 27 imshow(im) 28 29 30 for bi, blur in enumerate([2, 5, 10]): 31 im2 = zeros(im.shape) 32 im2 = filters.gaussian_filter(im, blur) 33 im2 = np.uint8(im2) 34 imNum=str(blur) 35 subplot(1, 4, 2 + bi) 36 axis('off') 37 title(u'标准差为'+imNum, fontproperties=font) 38 imshow(im2) 39 40 41 #如果是彩色图像,则分别对三个通道进行模糊 42 #for bi, blur in enumerate([2, 5, 10]): 43 # im2 = zeros(im.shape) 44 # for i in range(3): 45 # im2[:, :, i] = filters.gaussian_filter(im[:, :, i], blur) 46 # im2 = np.uint8(im2) 47 # subplot(1, 4, 2 + bi) 48 # axis('off') 49 # imshow(im2) 50 51 52 show() 53
结果展示:
图像显示随着 σ 的增加,一幅图像被模糊的程度。σ 越大,处理后的图像细节丢失越多。