由于笔者近期的研究课题与图像后处理有关,需要通过图像处理工具对图像进行变换和处理,进而生成合适的训练图像数据。该系列文章即主要记录笔者在不同的环境下进行图像处理时常用的工具和库。在 Python 环境下,对图像的处理笔者主要使用 Pillow 库,主要操作包括对图像的读取、存储和变换等。实际应用中,Pillow 中提供的 Image 模块适合对图像整体进行变换处理操作。

  注:以下介绍仅包括对应模块和函数的基础用法,故而在介绍时省略了部分参数和选项,更完备的用法和介绍可参考 Pillow 的官方文档。

  

  安装

  用户可通过 pip 直接安装 Pillow,更多安装方式可以参见这里

    pip install Pillow    #安装 pillow

  使用

  在日常应用过程中,使用最多的是 Pillow 提供的 Image 模块,其提供了包括图像存储、变换以及一系列的相关处理功能。Pillow 使用 Image 对象来表示图像对象并基于其定义图像的属性信息以及可针对其进行的操作,后续即主要介绍通过 Image 对象可进行的图像操作。在 Python 中使用时,用户首先需从 PIL 中导入对应的 Image 模块。

    from PIL import Image    #通过 Image 进行图像处理相关的操作

  图像读取与存储

  通过 Image 提供的 open 方法读取图像,其以指定的文件名为参数,返回值为对应图像的 Image 对象,后续即可针对图像对应的 Image 对象进行操作。

    im = Image.open( "test.png" )    # open 方法以图像名(或图像对象)为参数,返回一个 Image 对象

  通过 Image 对象的 save 方法存储图像对象,其使用存储目标文件名为参数,也可通过 format 参数指定存储文件的格式。

    im.save( "test.png" )                   # im 为 Image 对象,其被保存至 test.png,不指定 format 参数时,该方法通过文件后缀推测文件类型
im.save( "test.jpg" , format="JPEG") # 以 JPEG 格式保存 Image 对象 im 至文件 test.jpg 中

  基本属性

  图像对应的 Image 对象具备基本属性。用户可以通过这些属性获得图像最基本的信息,Image 对象的完整属性信息可以查看这里

    im.filename        # Image 对象 im 对应的文件/路径名
im.mode # Image 对象图像数据的解释方式,如灰度图为 “L”,彩色图为 “RGB”等
im.size # 返回图像的尺寸信息,为( width , height ) 格式的元祖

  图像类型转换

  不同的图像数据具有不同的图像格式,进而拥有不同的组织数据的方式。对于 RGB 图像而言,图像拥有 R、G、B 三个通道,像素数据由三个对应三通道的 8 bit 数据组成;对于黑白图像而言,其每个像素由一个 8 bit 字节表示等等。在打开图像时,open 方法会自动解析图像的格式,用户可通过 Image 对象的 mode 属性获得图像的状态。

  Image 对象可通过 convert 方法进行图像类型间的转换,其使用转换的目标类型的字符串为参数,返回转换后的 Image 对象,常见的类型包括 RGB(真彩)、L(黑白)、YCbCr(视频图像)、HSV(色调饱和度亮度彩色空间)。

    data = im.convert( "L" )        #获得 RGB 图像 im 的灰度图

  与 numpy 数组的转换

  在程序中,一般使用图像对应的 Image 对象进行图像相关的操作,针对图像数据本身的计算处理一般将 Image 对象的数据转换为 numpy 数据后进行,处理完成之后的 numpy 数据再被转换为 Image 对象进行保存。

  a. 将 Image 对象转换为 numpy 数组

  使用 numpy.asarray 方法( 不唯一,可参见 Array creation routines )将 Image 对象的数据转换为 numpy 数组,进而可以对其进行计算处理。转换后 numpy 数组的数据类型根据 Image 数据对象本身的数据类型推断获得,使用时也可使用 numpy.asarray 的 dtype 参数指定转换后的数据类型。  

    im = Image.open( "test.png" )                  #打开图像 test.png ,并获得其对应的 Image 对象
data = numpy.asarray( im ) #将 Image 对象 im 的数据转换为 numpy 数组的形式,data 即为可供运算的 numpy 数组
data = numpy.asarray( im, dtype=np.uint8 ) #转换图像数据为 numpy 数组,并指定其类型为 np.uint8

  这里注意,对于 RGB 彩色图像而言,Image 对象的 size 参数为二元组 ( width,  height ),而将其转换为 numpy 数组后,数组的形状参数 shape 为 ( height, width, channel ),其中 channel = 3. 若是灰度图像,则转换后的 shape 为( height, width ) .而在 Pytorch 等深度学习框架中,进行卷积的输入对象的特征一般为 ( Batch, Channel, Height, Width ) 的形式,故而在使用不同的数据类型时,需要注意上述不同的数据组织方式,。  

  b.将 numpy 数组转换为 Image 对象

  对于 numpy 数据形式的图像数据( 通过数据处理或其他途径获得 ),可通过 Image.fromarray 方法将已有的 numpy 图像数据转换为 Image 对象。根据前面的介绍, Image.fromarray 方法将格式为 ( height, width, channel ) 的数据转换为对应的 Image 对象,其 size 属性为 ( width, height ) 的形式.在使用时需要注意不同维度数据的含义。

    im = Image.fromarray( data )                       # data 为 numpy 数组,im 为转换获得的 Image 对象

  注意,在使用 Image.fromarray 方法时可能会出现报错 raise TypeError("Cannot handle this data type") , 这是由于待转换的 numpy 数据类型可能并不符合 Image 对象所需的数据类型( 一般为 8 bit 无符号值 ),解决方法是在转换前先将 numpy 数组的数据类型转换为 np.uint8 .

    im = Image.fromarray( data.astype( np.uint8 ) )    #将 numpy 数组的数据类型转换为 np.uint8 后再转换为 Image 对象

  常用操作

  裁剪图像——crop

  可以使用 crop 方法获得图像的指定部分。crop 方法以指定 ( 左,上,右,下 ) 切割位置的元祖来定义待分割的图像部分,可以理解为定义的是切割获得的矩形的左上角和右下角位置的坐标( 同样为 width, height 的形式)。在 PIL 所支持的坐标系统中,坐标的( 0 , 0 ) 为图像的左上角,注意 ( 0 , 0 ) 指向的不是左上角的第一个像素,而是该像素位置前的位置,后续所有的坐标均为像素间的空隙位置,而不是指向像素。也就是说,第一个像素被 ( 0 , 0 ) 和 ( 0 , 1 ) 两个坐标左右包围。  

    part = im.crop( ( 0 , 0 , 100 , 100 ) )       #截取获得图像 im 左上角大小为 100 × 100 像素的矩形图像

  通道处理——split / getchannel

  split 方法将图像数据按通道分离,其返回值为包含各个通道分离数据的元组tuple,如对于 RGB 图像而言,其被分成 R、G、B 三个通道的数据。

    R, G, B = im.split()                          # im 为真彩色 Image 对象,其被分为独立的 R、G、B 通道信息

  getchannel 方法以图像的通道的索引或字符名字为参数,返回包含有对应通道数据的 L 类型的图像( 即为黑白模式 )。  

    R = im.getchannel( 0 )    # 获得 RGB 图像的第一个通道的数据,即 R 通道信息
R = im.getchannel( "R" ) #同上

  缩放图像——resize

  resize 方法以缩放目标图像大小的元祖( Width, Heigth ) 为参数,通过指定的采样方法将图像缩放为指定的图像大小。其支持采样的方法包括 PIL.Image.NEAREST、PIL.Image.BILINEAR、PIL.Image.BICUBIC 等,resize 支持的全部采样方式见文档。注意,以上采样方法的全名为 PIL.Image.xxxx,但实际上由于之前已经使用 from PIL import Image 导入了 Image 这个模块名,故而后续可以直接使用 Image.xxxx 的形式调用上述方法,反之,在未导入模块名时需使用完整的名称来使用上述方法,下同。

    data = im.resize( ( 100, 100 ) )                         #将 im 对应的 Image 对象缩放为 100×100 的大小,默认采用 PIL.Image.NEAREST 方法
data = im.resize( ( 100, 100 ), Image.BICUBIC ) #使用 PIL.Image.BICUBIC 方法进行采样

   翻转图像——rotate/transpose

   通过 rotate 方法旋转图像,rotate 方法以旋转的角度为参数,将图像顺时针中心旋转对应的度数,并返回对应的 Image 对象。注意,通过 rotate 方法进行旋转时,结果图像是中心旋转后图像在源图像大小范围内被截取的部分,其他部分为填充。如大小为宽×高 200 * 100 的图像,经过 90 度旋转后,其大小仍为 200 * 100 ,图像内容为旋转后的理论为 100 * 200 的图像与原 200 * 100 区域的重合部分,其余部分为填充。

  rotate 方法可以指定 expand 参数为 1 ,此时生成的新图像为完整包含有旋转后图像内容的最小矩形大小( 空白处为填充),如上例中,图像经过 90 度旋转后,获得的新图像的大小即为 100 * 200。更多介绍见 Image.rotate.

    data = im.rotate( 90 )                 #将图像顺时针旋转 90 度
data = im.rotate( 90 , expand=1 ) #将图像顺时针旋转 90 度,同时保留图像的完整内容

  在某些图像训练的数据生成中,将图像进行 90 度为单位的旋转、上下或左右翻转是更为常见的操作。此时可以使用 transpose 方法,transpose 以翻转方式为参数,返回经过翻转后的图像,其支持的参数如下所示。

    PIL.Image.FLIP_LEFT_RIGHT    #左右翻转图像
PIL.Image.FLIP_TOP_BOTTOM #上下翻转图像
PIL.Image.ROTATE_90
PIL.Image.ROTATE_180
PIL.Image.ROTATE_270 #顺时针旋转对应度数
PIL.Image.TRANSPOSE #类似于左右翻转后再逆时针旋转图像 90 度
PIL.Image.TRANSVERSE #类似与左右翻转后再顺时针旋转图像 90 度

  可以直接使用上述参数对图像进行变换,transpose 方法返回变换后的完整图像( 由于是 90 度倍数的变换,也不存在空白区域 )。

    data = im.transpose( Image.FLIP_LEFT_RIGHT )        #获得 im 图像经过左右旋转后的数据

图像处理基本工具——Python 环境下的 Pillow( PIL )的更多相关文章

  1. Python环境下NIPIR(ICTCLAS2014)中文分词系统使用攻略

    一.安装 官方链接:http://pynlpir.readthedocs.org/en/latest/installation.html 官方网页中介绍了几种安装方法,大家根据个人需要,自行参考!我采 ...

  2. python环境下实现OrangePi Zero寄存器访问及GPIO控制

    最近入手OrangePi Zero一块,程序上需要使用板子上自带的LED灯,在网上一查,不得不说OPi的支持跟树莓派无法相比.自己摸索了一下,实现简单的GPIO控制方法,作者的Zero安装的是Armb ...

  3. Azure REST API (4) 在Python环境下,使用Azure REST API

    <Windows Azure Platform 系列文章目录> 之前遇到的项目中,客户需要在Python环境下,监控Azure VM的CPU利用率,在这里简单记录一下. 笔者的环境是Win ...

  4. 关于python环境下的opencv安装

    吐槽: 这一天我终于记起了这个博客.今天搞python环境下的opencv,又弄了一天,很烦躁.之前配置VS的opencv也是花了好久的时间,然后突然发现之前记录在电脑上的文档都找不到了,于是决定还是 ...

  5. windows下多Python环境指定pip安装模块到对应Python环境下

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿在windows下装了2套Python,一套是直接安装的Pytho ...

  6. python环境下安装virtualenv,virtualenvwrapper

    在使用 Python 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题: 亦或者是在开发过程中不想让物理环境里充斥各种各样的库,引发未来的依赖灾难. 此时,我们需要对于不同的工程使用 ...

  7. Python环境下如何安装爬虫需求的一些库

    是在CMD环境下的: request库pip install request 回车 pandas库 同理,pip install pandas :这里需要声明下,这个是不一定成功的,刚入门稍微看了一点 ...

  8. Windows10系统python环境下安装Dlib库(转载,蔡军帅亲测可用)

    Dlib是一个很优秀的机器学习库,最近做人脸识别要用到这个库,简要记录一下配置过程,准备工作: 1.python环境 2.安装好pip(这里有个简单的安装教程) 3.Dlib包,贴一个我安装的版本,链 ...

  9. [转]LIBSVM-3.18在python环境下的使用

    http://blog.csdn.net/lj695242104/article/details/39500039 1)安装Python,直接去官方网站 2)运行“cmd”,直接输入python,查看 ...

随机推荐

  1. Shell脚本之一 Shell脚本简介

    一.什么是shell? 我们平时所说的 Shell 可以理解为 Linux 系统提供给用户的使用界面.Shell 为用户提供了输入命令和参数并可得到命令执行结果的环境.当一个用户登录 Linux 之后 ...

  2. Oracle 'no privileges on tablespace 表空间名称' 问题解决

    create user bryan identified by bryan;   grant create session to bryan;   grant create table to brya ...

  3. python面试题300多题

    第一部分 Python基础篇(80题) 为什么学习Python? 通过什么途径学习的Python? Python和Java.PHP.C.C#.C++等其他语言的对比? 简述解释型和编译型编程语言? P ...

  4. mongodb数据库操作 python+命令行

      一.python操作 from bson.objectid import ObjectId import pymongo client1 = pymongo.MongoClient(host=) ...

  5. 【洛谷】P1022 计算器的改良-全AC题解

    #include <iostream> #include <cstring> #include <iomanip> using namespace std; int ...

  6. 【chromium】 Chromium OS的oom机制

    前一段时间,运行在Chromium OS上的一个相机应用经常会自己崩溃,进程戛然而止,测试过程中发现使用的内存以肉眼可见的内存增长,当增长到1G左右,应用窗口突然消失,虽然原因不明,但是能猜到个大概, ...

  7. 彻底搞懂Javascript的this

    在Javascript中,最玄妙的特性之一,就是this的指向玄幻莫测,一会儿指向这一会儿指向那,让初学者十分伤脑筋. 本文总结一下,方便初学者掌握奥妙之处,同时方便老鸟温故而知新. 首先,看一段代码 ...

  8. zynq开发板外设配置演示

    有幸得到米尔电子zynq系列开发板Z-turn Board试用体验,下面说说我这款zynq系列的Z-TURN板子外设配置.从Z-turn Board原理图上看,目前可以配置的FPGA管脚大概有100多 ...

  9. django配置文件

    1.BASSE_DIR BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 当前工程的根目录,Django会依 ...

  10. Django:RestFramework之-------视图

    10.视图 GenericAPIView封装一些方法,将这些方法返回值放在类变量位置上. 1.GenericAPIView视图示例:不怎么用 from api.utils.serializers.pa ...