用Python来处理图像的原因
《图像与视频处理》这门课程的实验都是用Matlab去实现的,不过鉴于我自己对Python更熟悉一些,而且Python中也有专门对图像操作的库,所以我希望我能用Python也能实现相同的功能。
PIL库
PIL(Python Imaging Library)是Python平台最常用的图像处理第三方库,支持多种图片格式。我主要使用PIL库中的Image模块来实现对图像的一些简单操作。
在windows平台上一般现在官方安装文件即可,但是由于官方的PIL库支持32位系统,所以64位的系统需要下载其他非官方编译的库的.whl文件(网址),将.whl文件放到本地,然后用pip安装。
PIL库Image模块使用
以前面的课程练习为例:通过对多幅连续拍照的图像累加,来消除噪点。
下面仅仅介绍本例中使用到的PIL库Image模块的基本方法,详细的说明参考官方文档
导入PIL的Image模块
1
from PIL import Image
打开和关闭图片
1
2im = Image.open(fileName)
im = Image.close()获取和设置pixel的Rawdata大小
1
2rawdata = im.getdata()
im.putdata(rawdata)显示和保存图像
1
2im.show()
im.save('image.jpg')
通过以上的方法,就可以通过PIL库的Image模块操作图片了:
打开图片-->获取图像原始数据-->改变图像原始数据-->保存图像-->关闭图像
使用以上方法的体验
打开图像速度快
由于open的操作默认是不进行Load操作的,所以用open()函数打开图像时,速度是比较快的。
图像数据为3种颜色通道的3维矩阵,转换为numpy的array处理比较方便
为了对图像实现加法操作,我需要将获取解码后的图像的原始rawdata,在累加完成求取平均值之后,再将其编码放回去。
getdata函数的返回值类型是 ImagingCore类型,是PIL内部类型,为了方便我外部使用,我们最容易想到的是事是转化为numpy的array,来做矩阵数据计算时最方便的。为了转换为numpy的array可以用以下两种方法:
1
dataArray = np.array(list(im.getdata()))
or
1
dataArray = np.array(im.getdata()))
表面上看第二种要简洁,但是实际运行时间,反而第二种方法比第一种时间要长,有点搞不懂。
putdata函数使用不是很方便
oupdata函数需要的参数类型为 tuple或 ImagingCore,当我们用numpy的array处理完数据后,还需要将数据转为 tuple,可以用下面的方法转化:
1
tupledat = tuple(map(tuple,avgdata))
但是这个转化比较费时,我的机器处理一个1366 x 768像素大小的图像,需要花费几乎1.4s的时长,当需要处理的图像多了后就有点不合算了。
当处理大图片时 内存会炸掉
用这种方法需要将图片数据全部读入内存,这样导致过大的图片就肯定是无法处理的。我尝试处理过用该方法去2352 x 4160大小的图片,结果机器剩余的1.5G内存几乎全部占完,而且处理速度也是慢的不行。
优化:(2016-7-25 后面才发现以下方法更高效方便,前面的方法慢成渣)
nunpy导入数据直接用Iamge对象:
1
dataArray = np.array(Image.open(fileName)))
将nunpy的矩阵数据用fromarray()函数直接转换为Image对象:
1
im = Image.fromarray(rawdata))
注意fromarray函数要求rawdata中的元素需要为np.uint8的类型,不是的用astype()函数来转换。
可以用matplotlib.pyplot模块来显示图像:
1
2
3import matplotlib.pyplot as plt
plt.imshow(im2)
plt.show()