PIL提供了通用的图像处理功能,以及大量的基本图像操作,如图像缩放、裁剪、旋转、颜色转换等。
Matplotlib提供了强大的绘图功能,其下的pylab/pyplot接口包含很多方便用户创建图像的函数。
为了观察和进一步处理图像数据,首先需要加载图像文件,并且为了查看图像数据,我们需要将其绘制出来。
from PIL import Image import matplotlib.pyplot as plt import numpy as np # 加载图像 img = Image.open("tmp.jpg") # 转为数组 img_data = np.array(img) # 可视化 plt.imshow(img_data) plt.show()对于图像,我们常见的操作有调整图像尺寸,旋转图像以及灰度变换
from PIL import Image import matplotlib.pyplot as plt img = Image.open("girl.jpg") plt.figure() # 子图 plt.subplot(221) # 原图 plt.imshow(img) plt.subplot(222) # 将图像缩放至 256 * 256 plt.imshow(img.resize((256, 256))) plt.subplot(223) # 将图像转为灰度图 plt.imshow(img.convert('L')) plt.subplot(224) # 旋转图像 plt.imshow(img.rotate(45)) # 保存图像 plt.savefig("tmp.jpg") plt.show()效果演示 :
在平常的使用中,绘制图像的轮廓也经常被使用,因为绘制轮廓需要对每个坐标(x, y)的像数值施加同一个阙值,所以需要将图像灰度化
from PIL import Image import matplotlib.pyplot as plt import numpy as np img = Image.open("girl.jpg") gray_img = np.array(img.convert('L')) plt.figure() # 绘制图像灰度化 plt.gray() # 关闭坐标轴 plt.axis('off') # 绘制灰度图像 plt.contour(gray_img, origin='image') plt.figure() # 绘制直方图,flatten()表示将数组展平 plt.hist(gray_img.flatten(), 128) plt.show()轮廓图及直方图:
图像的直方图用来表征该图像的像素值的分布情况。用一定数目的小区间来指定表征像素值的范围,每个小区间会得到落入该小区间表示范围的像素数目。hist()函数用于绘制图像的直方图,其只接受一维数组作为第一个参数输入,其第二个参数用于指定小区间的数目。
有时用户需要和应用进行交互,如在一幅图像中标记一些点。Pylab/pyplot库中的ginput()函数就可以实现交互式标注
from PIL import Image import matplotlib.pyplot as plt img = Image.open(r"girl.jpg") plt.imshow(img) x = plt.ginput(3) print("clicked point: ", x)注:该交互在集成编译环境(pyCharm)中如果不能调出交互窗口则无法进行点击,可以在命令窗口下成功执行。
以上我们通过numpy的array()函数将Image对象转换成了数组,以下将展示如何从数组转换成Image对象
from PIL import Image import numpy as np img = Image.open(r"girl.jpg") img_array = np.array(img) img = Image.fromarray(img_array)在图像灰度变换中有一个非常有用的例子就是直方图均衡化。直方图均衡化是指将一幅图像的灰度直方图变平,使变换后的图像中每个灰度值的分布概率都相同。直方图均衡化通常是对图像灰度值进行归一化的一个非常好的方法,并且可以增强图像的对比度。
直方图均衡化的变换函数是图像中像素值的累积分布函数(cumulative distribution function,将像素值的范围映射到目标范围的归一化操作)。
from PIL import Image import matplotlib.pyplot as plt import numpy as np def histogram_equalization(img: np, nbr_bins=256): imhist, bins = np.histogram(img.flatten()) cdf = imhist.cumsum() # 累计分布函数 # 归一化 cdf = 255 * cdf / cdf[-1] # 使用累积分布函数进行线性插值,计算新的像素值 img2 = np.interp(img.flatten(), bins[:-1], cdf) return img2.reshape(img.shape), cdf img = Image.open(r"girl.jpg").convert('L') img2, cdf = histogram_equalization(np.array(img)) plt.figure() plt.gray() # 绘制子图 plt.subplot(232) # 变换函数 plt.plot(cdf) plt.subplot(231) plt.hist(np.array(img).flatten(), 256) # 关闭坐标轴,对上一个子图有效 plt.axis('off') plt.subplot(233) plt.hist(np.array(img2).flatten(), 256) plt.axis('off') plt.subplot(234) plt.imshow(img) plt.axis('off') plt.subplot(236) plt.imshow(img2) plt.axis('off') # 保存绘制图像 plt.savefig("tmp.jpg") plt.show()处理结果