Python图像处理-Pillow

简介

Python传统的图像处理库PIL(Python Imaging Library ),可以说基本上是Python处理图像的标准库,功能强大,使用简单。

但是由于PIL不支持Python3,而且更新缓慢。所以有志愿者在PIL的基础上创建了一个分支版本,命名为PillowPillow目前最新支持到python3.6,更新活跃,并且增添了许多新的特性。所以我们安装Pillow即可。

安装

Pillow的安装比较的简单,直接pip安装即可:

  1. pip install Pillow

但是要注意的一点是,PillowPIL不能共存在同一个环境中,所以如果安装的有PIL的话,那么安装Pillow之前应该删除PIL

由于是继承自PIL的分支,所以Pillow的导入是这样的:

  1. import PIL
  2. # 或者
  3. from PIl import Image

使用手册

Image

Image是Pillow中最为重要的类,实现了Pillow中大部分的功能。要创建这个类的实例主要有三个方式:

  1. 从文件加载图像

  2. 处理其他图像获得

  3. 创建一个新的图像

读取图像

一般来说,我们都是都过从文件加载图像来实例化这个类,如下所示:

  1. from PIL import Image
  2. picture = Image.open('happy.png')

如果没有指定图片格式的话,那么Pillow会自动识别文件内容为文件格式。

新建图像

Pillow新建空白图像使用new()方法, 第一个参数是mode即颜色空间模式,第二个参数指定了图像的分辨率(宽x高),第三个参数是颜色。

  • 可以直接填入常用颜色的名称。如'red'。

  • 也可以填入十六进制表示的颜色,如#FF0000表示红色。

  • 还能传入元组,比如(255, 0, 0, 255)或者(255, 0, 0)表示红色。

  1. picture = Image.new('RGB', (200, 100), 'red')

保存图像

保存图片的话需要使用save()方法:

  1. picture.save('happy.png')

保存的时候,如果没有指定图片格式的话,那么Pillow会根据输入的后缀名决定保存的文件格式。

图像的坐标表示

在Pillow中,用的是图像的左上角为坐标的原点(0,0),所以这意味着,x轴的数值是从左到右增长的,y轴的数值是从上到下增长的。

我们处理图像时,常常需要去表示一个矩形的图像区域。Pillow中很多方法都需要传入一个表示矩形区域的元祖参数。

这个元组参数包含四个值,分别代表矩形四条边的距离X轴或者Y轴的距离。顺序是(左,顶,右,底)。其实就相当于,矩形的左上顶点坐标为(左,顶),矩形的右下顶点坐标为(右,底),两个顶点就可以确定一个矩形的位置。

右和底坐标稍微特殊,跟python列表索引规则一样,是左闭又开的。可以理解为[左, 右)[顶, 底)这样左闭右开的区间。比如(3, 2, 8, 9)就表示了横坐标范围[3, 7];纵坐标范围[2, 8]的矩形区域。

常用属性

  • PIL.Image.filename

    图像源文件的文件名或者路径,只有使用open()方法创建的对象有这个属性。

    类型:字符串

  • PIL.Image.format

    图像源文件的文件格式。

  • PIL.Image.mode

    图像的模式,一般来说是“1”, “L”, “RGB”, 或者“CMYK” 。

  • PIL.Image.size

    图像的大小

  • PIL.Image.width

    图像的宽度

  • PIL.Image.height

    图像的高度

  • PIL.Image.info

    图像的一些信息,为字典格式

常用方法

裁剪图片

Image使用crop()方法来裁剪图像,此方法需要传入一个矩形元祖参数,返回一个新的Image对象,对原图没有影响。

  1. croped_im = im.crop((100, 100, 200, 200))

复制与粘贴图像

复制图像使用copy()方法:

  1. copyed_im = im.copy()

粘贴图像使用paste()方法:

  1. croped_im = im.crop((100, 100, 200, 200))
  2. im.paste(croped_im, (0, 0))

im对象调用了paste()方法,第一个参数是被裁剪下来用来粘贴的图像,第二个参数是一个位置参数元祖,这个位置参数是粘贴的图像的左顶点。

调整图像的大小

调整图像大小使用resize()方法:

  1. resized_im = im.resize((width, height))

resize()方法会返回一个重设了大小的Image对象。

旋转图像和翻转图像

旋转图像使用rotate()方法,此方法按逆时针旋转,并返回一个新的Image对象:

  1. # 逆时针旋转90度
  2. im.rotate(90)
  3. im.rotate(180)
  4. im.rotate(20, expand=True)

旋转的时候,会将图片超出边界的边角裁剪掉。如果加入expand=True参数,就可以将图片边角保存住。

翻转图像使用transpose()

  1. # 水平翻转
  2. im.transpose(Image.FLIP_LEFT_RIGHT)
  3. # 垂直翻转
  4. im.transpose(Image.FLIP_TOP_BOTTOM)

获取单个像素的值

使用getpixel(xy)方法可以获取单个像素位置的值:

  1. im.getpixel((100, 100))

传入的xy需要是一个元祖形式的坐标。

如果图片是多通道的,那么返回的是一个元祖。

通过通道分割图片

split()

split()可以将多通道图片按通道分割为单通道图片:

  1. R, G, B = im.split()

split()方法返回的是一个元祖,元祖中的元素则是分割后的单个通道的值。

getchannel(channel)

getchannel()可以获取单个通道的数据:

  1. R = im.getchannel("R")

加载图片全部数据

我们可以使用load()方法加载图片所有的数据,并比较方便的修改像素的值:

  1. pixdata = im.load()
  2. pixdata[100,200] = 255

此方法返回的是一个PIL.PyAccess,可以通过这个类的索引来对指定坐标的像素点进行修改。

关闭图片并释放内存

此方法会删除图片对象并释放内存

  1. im.close()
  2. 把图片转为高对比度的图片
  1. # -*- coding:utf-8 -*-
  2. # 斌彬电脑
  3. # @Time : 2018/9/11 0011 下午 2:50
  4.  
  5. from PIL import Image
  6. im = Image.open('ss.png')
  7. im = im.convert('L') # 灰度图片
  8. data = im.load()
  9. h,w = im.size # 读出图片大小,
  10. # 不是黑的就是白的,
  11. for i in range(h):
  12. for j in range(w):
  13. if data[i,j] > 128: # 根据坐标读出像素的值
  14. data[i,j] = 255
  15. else: data[i,j] = 0
  16.  
  17. # 得到一个高对比度的图片
  18. im.show()

  

验证码简单处理

  1. # -*- coding: utf-8 -*-
  2. # 斌彬电脑
  3. # @Time : 2018/9/12 0012 5:34
  4.  
  5. from PIL import Image
  6.  
  7. im = Image.open('aaaaaaa.png')
  8. im = im.convert('L') # 灰度图片
  9. data = im.load()
  10. h, w = im.size # 读出图片大小,
  11. # 不是黑的就是白的,
  12. for i in range(h):
  13. for j in range(w):
  14. if data[i, j] > 20: # 根据坐标读出像素的值
  15. data[i, j] = 255
  16. else:
  17. data[i, j] = 0
  18.  
  19. # 降嗓
  20. for x in range(1,h - 1):
  21. for y in range(1,w - 1):
  22. count = 0
  23. if data[x - 1, y - 1] == 255:
  24. count += 1
  25. if data[x + 1, y + 1] == 255:
  26. count += 1
  27. if data[x - 1, y - 1] == 255:
  28. count += 1
  29. if data[x + 1, y + 1] == 255:
  30. count += 1
  31.  
  32. # if data[x, y - 1] == 255:
  33. # count += 1
  34. # if data[x, y + 1] == 255:
  35. # count += 1
  36. # if data[x - 1, y] == 255:
  37. # count += 1
  38. # if data[x + 1, y] == 255:
  39. # count += 1
  40.  
  41. if count > 2:
  42. data[x, y] = 255
  43.  
  44. im.save('123.png')
  45. # 得到一个高对比度的图片
  46. im.show()

  

  1.  
  2. 非黑即白的后处理
  1. # -*- coding:utf-8 -*-
  2. # 斌彬电脑
  3. # @Time : 2018/9/12 0012 上午 8:37
  4.  
  5. from PIL import Image
  6. import json, re
  7.  
  8. im = Image.open('aaaaaaa.png')
  9. im = im.convert('L') # 灰度图片
  10. data = im.load()
  11. h, w = im.size # 读出图片大小,
  12. # 不是黑的就是白的,
  13. for i in range(h):
  14. for j in range(w):
  15. if data[i, j] > 20: # 根据坐标读出像素的值
  16. data[i, j] = 255
  17. else:
  18. data[i, j] = 0
  19.  
  20. # 降嗓
  21. for x in range(1,h - 1):
  22. for y in range(1,w - 1):
  23. count = 0
  24. if data[x - 1, y - 1] == 255:
  25. count += 1
  26. if data[x + 1, y + 1] == 255:
  27. count += 1
  28. if data[x - 1, y - 1] == 255:
  29. count += 1
  30. if data[x + 1, y + 1] == 255:
  31. count += 1
  32.  
  33. if count > 2:
  34. data[x, y] = 255
  35.  
  36. itm = {}
  37. file = open('itm.json', 'a', encoding='utf8')
  38. for x in range(1,h - 1):
  39. itm = {}
  40. y = 1
  41. file.write('\n')
  42. while (w-y)!=0:
  43. if data[x, y] == 0:
  44. itm[x] = y
  45. item1 = json.dumps(itm, ensure_ascii=False )
  46. file.write(item1)
  47. y += 1
  48.  
  49. bb=''
  50. with open("itm.json", "r") as f:
  51. for i in f:
  52. if len(i.strip()) < 50:
  53. # print(i.strip())
  54. bb = bb+i.strip()
  55. # print(bb)
  56.  
  57. a,b = re.findall(r"{'(.*?)':(.*?)}", bb)
  58. print(a,b)
  59.  
  60. # im.save('123.png')
  61. # 得到一个高对比度的图
  62. # im.show()

 

验证码黑白处理

  1. # -*- coding:utf-8 -*-
  2. # 斌彬电脑
  3. # @Time : 2018/9/12 0012 上午 8:37
  4.  
  5. from PIL import Image
  6. import json, re
  7.  
  8. im = Image.open('9.png')
  9. im = im.convert('L') # 灰度图片
  10. data = im.load()
  11. h, w = im.size # 读出图片大小,
  12. # 不是黑的就是白的,
  13. for i in range(h):
  14. for j in range(w):
  15. if data[i, j] > 50: # 根据坐标读出像素的值
  16. data[i, j] = 255
  17. else:
  18. data[i, j] = 0
  19.  
  20. # 降嗓
  21. for x in range(1, h - 1):
  22. for y in range(1, w - 1):
  23. count = 0
  24. if data[x - 1, y - 1] == 255:
  25. count += 1
  26. if data[x + 1, y + 1] == 255:
  27. count += 1
  28. if data[x - 1, y - 1] == 255:
  29. count += 1
  30. if data[x + 1, y + 1] == 255:
  31. count += 1
  32.  
  33. if count > 2:
  34. data[x, y] = 255
  35.  
  36. itm = {}
  37. file1 = open('itm.json', 'a', encoding='utf8')
  38. for x in range(1, h - 1):
  39. itm = {}
  40. y = 1
  41. file1.write('\n')
  42. while (w - y) != 0:
  43. if data[x, y] == 0:
  44. itm[x] = y
  45. item1 = json.dumps(itm, ensure_ascii=False)
  46. file1.write(item1)
  47. y += 1
  48. file1.close()
  49.  
  50. bb = ''
  51. with open("itm.json", "r") as f:
  52. for i in f:
  53. if len(i.strip()) < 30: # 杂点大小
  54. # print(i.strip())
  55. bb = bb + i.strip()
  56. # print(bb)
  57. # {"4": 40}
  58. a = re.findall(r'{"(.*?)":.*?}', bb)
  59. b = re.findall(r'{".*?":(.*?)}', bb)
  60. # print(a)
  61. # print(b)
  62. print(len(a),len(b))
  63. for i in range(len(a)):
  64. data[int(a[i]), int(b[i])] = 255
  65.  
  66. # im2 = im
  67. # data2 = im.load()
  68. # h2, w2 = im2.size # 读出图片大小,
  69. # # print(h2,w2,'00000')
  70. #
  71. # atm = {}
  72. # file2 = open('atm.json', 'a', encoding='utf8')
  73. # for n in range(1, w2 - 1):
  74. # atm = {}
  75. # m = 1
  76. # file2.write('\n')
  77. # while (h2 - m) != 0:
  78. # if data2[n, m] == 0:
  79. # atm[n] = m
  80. # stem1 = json.dumps(atm, ensure_ascii=False)
  81. # file2.write(stem1)
  82. # n += 1
  83. # file2.close()
  84. #
  85. # cc = ''
  86. # with open("atm.json", "r") as f:
  87. # for i in f:
  88. # if len(i.strip()) < 30: # 杂点大小
  89. # # print(i.strip())
  90. # cc = cc + i.strip()
  91. # # print(bb)
  92. # # {"4": 40}
  93. # c = re.findall(r'{"(.*?)":.*?}', cc)
  94. # d = re.findall(r'{".*?":(.*?)}', cc)
  95. # # print(c)
  96. # # print(d)
  97. # print(len(c), len(d))
  98. # for i in range(len(c)):
  99. # data2[int(c[i]), int(d[i])] = 255
  100.  
  101. # im.save('123.png')
  102. # 得到一个高对比度的图
  103. # im2 = im2.rotate(270)
  104. im.show()

  

  1.  

潭州课堂25班:Ph201805201 爬虫基础 第九课 图像处理- PIL (课堂笔记)的更多相关文章

  1. 潭州课堂25班:Ph201805201 爬虫高级 第九课 scrapyd 部署 (课堂笔记)

    c rapyd是 scrapy 的部署, 是官方提供的一个爬虫管理工具, 通过他可以非常方便的上传控制爬虫的运行, 安装 : pip install scapyd 他提供了一个json ,web, s ...

  2. 潭州课堂25班:Ph201805201 爬虫基础 第一课 (课堂笔记)

    爬虫的概念: 其实呢,爬虫更官方点的名字叫数据采集,英文一般称作spider,就是通过编程来全自动的从互联网上采集数据.比如说搜索引擎就是一种爬虫.爬虫需要做的就是模拟正常的网络请求,比如你在网站上点 ...

  3. 潭州课堂25班:Ph201805201 爬虫基础 第二课 fidder (课堂笔记)

    通过浏览器访问百度的详细过程? 一.通过dns获取百度IP地址.二.通过百度IP访问百度服务器, 三,返回数据. 四,通过渲染显示内容, fidder设置 tf 信任证书

  4. 潭州课堂25班:Ph201805201 爬虫高级 第二课 sclapy 框架 (课堂笔记)

    win 下安装 sclapy 先安装 pip install wheel py 库下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 在这 ...

  5. 潭州课堂25班:Ph201805201 爬虫高级 第一课 pyspider框架 (课堂笔记)

    利用wheel安装 S1: pip install wheelS2: 进入www.lfd.uci.edu/~gohlke/pythonlibs/,Ctrl + F查找pycurl 这个包名是pycur ...

  6. 潭州课堂25班:Ph201805201 WEB 之 页面编写 第四课 登录注册 (课堂笔记)

    index.html 首页 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...

  7. 潭州课堂25班:Ph201805201 WEB 之 页面编写 第三课 (课堂笔记)

    index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  8. 潭州课堂25班:Ph201805201 WEB 之 页面编写 第二课 (课堂笔记)

    index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  9. 潭州课堂25班:Ph201805201 WEB 之 页面编写 第一课 (课堂笔记)

    index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

随机推荐

  1. python中argparse模块用法实例详解

    python中argparse模块用法实例详解 这篇文章主要介绍了python中argparse模块用法,以实例形式较为详细的分析了argparse模块解析命令行参数的使用技巧,需要的朋友可以参考下 ...

  2. Faster rcnn代码理解(3)

    紧接着之前的博客,我们继续来看faster rcnn中的AnchorTargetLayer层: 该层定义在lib>rpn>中,见该层定义: 首先说一下这一层的目的是输出在特征图上所有点的a ...

  3. Linux: 介绍make menuconfig中的每个选项含义【转】

    转自:http://blog.csdn.net/gaoyuanlinkconcept/article/details/8810468 介绍make menuconfig中的每个选项含义 Linux 2 ...

  4. Linux 调优方案, 修改最大连接数(ulimit命令)【转】

    转自:http://blog.csdn.net/liangxiaozhang/article/details/8363435 Linux对于每个用户,系统限制其最大进程数.为提高性能,可以根据设备资源 ...

  5. XAF 与 CIIP

    XAF 与 CIIP:网站:http://www.uims.top, XAF技术博客:http://www.cnblogs.com/foreachlife/ tylike 升级到  DevExpres ...

  6. PHP查看编译参数

    PHP查看编译参数 [root@test ~]# php -i|grep configure Configure Command => './configure' '--prefix=/usr/ ...

  7. mysql5.5.48的my.cnf配置

    MYSQL配置 [client] port = 3306 socket = /tmp/mysql.sock [mysqld] port = 3306 default-storage-engine=My ...

  8. centos6中创建软raid方法

    raid概述: 组建raid阵列命令: mdadm:模式化的工具 /etc/mdadm.conf     -A  Assemble 装配模式     -C  Create 创建模式     -C:专用 ...

  9. vue及webpack在项目中的一些优化

    传送:https://www.haorooms.com/post/vue_webpack_youhua

  10. 使用swiper.js实现移动端tab切换

    在项目中遇到的,要实现tab切换,我用的是swiper.js 官网:http://www.swiper.com.cn/api/start/new.html <!DOCTYPE html> ...