用Python对图像进行简单的操作(利用PIL库)

用Python来处理图像的原因

《图像与视频处理》这门课程的实验都是用Matlab去实现的,不过鉴于我自己对Python更熟悉一些,而且Python中也有专门对图像操作的库,所以我希望我能用Python也能实现相同的功能。

PIL库

PIL(Python Imaging Library)是Python平台最常用的图像处理第三方库,支持多种图片格式。我主要使用PIL库中的Image模块来实现对图像的一些简单操作。

在windows平台上一般现在官方安装文件即可,但是由于官方的PIL库支持32位系统,所以64位的系统需要下载其他非官方编译的库的.whl文件(网址),将.whl文件放到本地,然后用pip安装。

PIL库Image模块使用

以前面的课程练习为例:通过对多幅连续拍照的图像累加,来消除噪点。

下面仅仅介绍本例中使用到的PIL库Image模块的基本方法,详细的说明参考官方文档

  1. 导入PIL的Image模块

    1
    from PIL import Image
  2. 打开和关闭图片

    1
    2
    im = Image.open(fileName)
    im = Image.close()
  3. 获取和设置pixel的Rawdata大小

    1
    2
    rawdata = im.getdata()
    im.putdata(rawdata)
  4. 显示和保存图像

    1
    2
    im.show()
    im.save('image.jpg')

通过以上的方法,就可以通过PIL库的Image模块操作图片了:

打开图片-->获取图像原始数据-->改变图像原始数据-->保存图像-->关闭图像


使用以上方法的体验

  1. 打开图像速度快

    由于open的操作默认是不进行Load操作的,所以用open()函数打开图像时,速度是比较快的。

  2. 图像数据为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()))

    表面上看第二种要简洁,但是实际运行时间,反而第二种方法比第一种时间要长,有点搞不懂。

  3. putdata函数使用不是很方便

    oupdata函数需要的参数类型为 tupleImagingCore,当我们用numpy的array处理完数据后,还需要将数据转为 tuple,可以用下面的方法转化:

    1
    tupledat = tuple(map(tuple,avgdata))

    但是这个转化比较费时,我的机器处理一个1366 x 768像素大小的图像,需要花费几乎1.4s的时长,当需要处理的图像多了后就有点不合算了。

  4. 当处理大图片时 内存会炸掉

    用这种方法需要将图片数据全部读入内存,这样导致过大的图片就肯定是无法处理的。我尝试处理过用该方法去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
    3
    import matplotlib.pyplot as plt
    plt.imshow(im2)
    plt.show()
Compartir