潭州课堂25班:Ph201805201 爬虫基础 第九课 图像处理- PIL (课堂笔记)

Python图像处理-Pillow

简介

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

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

安装

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

pip install Pillow

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

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

import PIL 
# 或者
from PIl import Image

使用手册

Image

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

  1. 从文件加载图像

  2. 处理其他图像获得

  3. 创建一个新的图像

读取图像

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

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

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

新建图像

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

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

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

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

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

保存图像

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

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对象,对原图没有影响。

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

复制与粘贴图像

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

copyed_im = im.copy()

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

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

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

调整图像的大小

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

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

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

旋转图像和翻转图像

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

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

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

翻转图像使用transpose()

# 水平翻转
im.transpose(Image.FLIP_LEFT_RIGHT)
# 垂直翻转
im.transpose(Image.FLIP_TOP_BOTTOM)

获取单个像素的值

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

im.getpixel((100, 100))

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

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

通过通道分割图片

split()

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

R, G, B = im.split()

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

getchannel(channel)

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

R = im.getchannel("R")

加载图片全部数据

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

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

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

关闭图片并释放内存

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

im.close()






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

  

 

验证码简单处理

# -*- coding: utf-8 -*-
# 斌彬电脑
# @Time : 2018/9/12 0012 5:34from PIL import Imageim = Image.open('aaaaaaa.png')
im = im.convert('L')  # 灰度图片
data = im.load()
h, w = im.size  # 读出图片大小,
#  不是黑的就是白的,
for i in range(h):for j in range(w):if data[i, j] > 20:  # 根据坐标读出像素的值data[i, j] = 255else:data[i, j] = 0# 降嗓
for x in range(1,h - 1):for y in range(1,w - 1):count = 0if data[x - 1, y - 1] == 255:count += 1if data[x + 1, y + 1] == 255:count += 1if data[x - 1, y - 1] == 255:count += 1if data[x + 1, y + 1] == 255:count += 1# if data[x, y - 1] == 255:#     count += 1# if data[x, y + 1] == 255:#     count += 1# if data[x - 1, y] == 255:#     count += 1# if data[x + 1, y] == 255:#     count += 1if count > 2:data[x, y] = 255im.save('123.png')
#  得到一个高对比度的图片
im.show()

  

 


非黑即白的后处理
# -*- coding:utf-8 -*-
# 斌彬电脑
# @Time :   2018/9/12 0012    上午 8:37from PIL import Image
import json, reim = Image.open('aaaaaaa.png')
im = im.convert('L')  # 灰度图片
data = im.load()
h, w = im.size  # 读出图片大小,
#  不是黑的就是白的,
for i in range(h):for j in range(w):if data[i, j] > 20:  # 根据坐标读出像素的值data[i, j] = 255else:data[i, j] = 0# 降嗓
for x in range(1,h - 1):for y in range(1,w - 1):count = 0if data[x - 1, y - 1] == 255:count += 1if data[x + 1, y + 1] == 255:count += 1if data[x - 1, y - 1] == 255:count += 1if data[x + 1, y + 1] == 255:count += 1if count > 2:data[x, y] = 255itm = {}
file = open('itm.json', 'a', encoding='utf8')
for x in range(1,h - 1):itm = {}y = 1file.write('\n')while (w-y)!=0:if  data[x, y] == 0:itm[x] = yitem1 = json.dumps(itm, ensure_ascii=False )file.write(item1)y += 1bb=''
with open("itm.json", "r") as f:for i in f:if  len(i.strip()) < 50:# print(i.strip())bb = bb+i.strip()
# print(bb)a,b = re.findall(r"{'(.*?)':(.*?)}", bb)
print(a,b)# im.save('123.png')
#  得到一个高对比度的图
# im.show()

 

 

 

 

验证码黑白处理

# -*- coding:utf-8 -*-
# 斌彬电脑
# @Time :   2018/9/12 0012    上午 8:37from PIL import Image
import json, reim = Image.open('9.png')
im = im.convert('L')  # 灰度图片
data = im.load()
h, w = im.size  # 读出图片大小,
#  不是黑的就是白的,
for i in range(h):for j in range(w):if data[i, j] > 50:  # 根据坐标读出像素的值data[i, j] = 255else:data[i, j] = 0# 降嗓
for x in range(1, h - 1):for y in range(1, w - 1):count = 0if data[x - 1, y - 1] == 255:count += 1if data[x + 1, y + 1] == 255:count += 1if data[x - 1, y - 1] == 255:count += 1if data[x + 1, y + 1] == 255:count += 1if count > 2:data[x, y] = 255itm = {}
file1 = open('itm.json', 'a', encoding='utf8')
for x in range(1, h - 1):itm = {}y = 1file1.write('\n')while (w - y) != 0:if data[x, y] == 0:itm[x] = yitem1 = json.dumps(itm, ensure_ascii=False)file1.write(item1)y += 1
file1.close()bb = ''
with open("itm.json", "r") as f:for i in f:if len(i.strip()) < 30:         #  杂点大小# print(i.strip())bb = bb + i.strip()
# print(bb)
# {"4": 40}
a = re.findall(r'{"(.*?)":.*?}', bb)
b = re.findall(r'{".*?":(.*?)}', bb)
# print(a)
# print(b)
print(len(a),len(b))
for i in range(len(a)):data[int(a[i]), int(b[i])] = 255# im2 = im
# data2 = im.load()
# h2, w2 = im2.size  # 读出图片大小,
# # print(h2,w2,'00000')
#
# atm = {}
# file2 = open('atm.json', 'a', encoding='utf8')
# for n in range(1, w2 - 1):
#     atm = {}
#     m = 1
#     file2.write('\n')
#     while (h2 - m) != 0:
#         if data2[n, m] == 0:
#             atm[n] = m
#             stem1 = json.dumps(atm, ensure_ascii=False)
#             file2.write(stem1)
#         n += 1
# file2.close()
#
# cc = ''
# with open("atm.json", "r") as f:
#     for i in f:
#         if len(i.strip()) < 30:  # 杂点大小
#             # print(i.strip())
#             cc = cc + i.strip()
# # print(bb)
# # {"4": 40}
# c = re.findall(r'{"(.*?)":.*?}', cc)
# d = re.findall(r'{".*?":(.*?)}', cc)
# # print(c)
# # print(d)
# print(len(c), len(d))
# for i in range(len(c)):
#     data2[int(c[i]), int(d[i])] = 255# im.save('123.png')
#  得到一个高对比度的图
# im2 = im2.rotate(270)
im.show()

  

 

转载于:https://www.cnblogs.com/gdwz922/p/9602382.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/426907.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 安装qq,如何安装linux版本QQ?

layout: pagetitle: linuxQQ发布description: linuxQQ安装tags:Linuxqqcategories: linux前文时光匆匆&#xff0c;随着时间流逝&#xff0c;已经来到了2019年&#xff0c;在这一年的1024程序员节这天&#xff0c;腾讯终于又发布了linux版的qq&#xff0c;说起来也是喜大普奔&a…

Python中range()函数的用法

1、函数原型&#xff1a;range&#xff08;start&#xff0c; end&#xff0c; scan)&#xff1a; 参数含义&#xff1a; start:计数从start开始。默认是从0开始。例如range&#xff08;5&#xff09;等价于range&#xff08;0&#xff0c; 5&#xff09;; end:技术到end结束&a…

[SimplePlayer] 1. 从视频文件中提取图像

在开始之前&#xff0c;我们需要了解视频文件的格式。视频文件的格式众多&#xff0c;无法三言两语就能详细分析其结构&#xff0c;尽管如此&#xff0c;ffmpeg却很好地提取了各类视频文件的共同特性&#xff0c;并对其进行了抽象描述。 视频文件格式&#xff0c;统称为contain…

android glide 版本,Android Studio 第六十七期 - Android Glide3.7.0和3.8.0用法

一、前言&#xff1a;再优秀的开源库都有坑要填手上的项目使用的图片加载框架是&#xff1a;Universal-Image-Loader业务需要定制化的一些代码。Universal-Image-Loader 这个框架是一个非常经典好用的框架&#xff0c;唯一的问题是是作者很久之前就不再更新了。所以综合考虑下&…

实例21:python

#猴子吃桃问题&#xff1a;猴子第一天摘下若干个桃子&#xff0c; #当即吃了一半&#xff0c;还不瘾&#xff0c;又多吃了一个第二天早上又将剩下的桃子吃掉一半&#xff0c; #又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。 #到第10天早上想再吃时&#xff0c;见只…

thincmf 分页无法搜索_thinkcmf5 后台搜索分页保持分页条件

本文最后更新于2019-05-16&#xff0c;已超过 1年没有更新&#xff0c;如果文章内容、图片或者下载资源失效&#xff0c;请留言反馈&#xff0c;我会及时处理&#xff0c;谢谢&#xff01;温馨提示&#xff1a;本文共568个字&#xff0c;读完预计2分钟。$where array();$keywo…

Python List insert()方法

Python 列表 描述 insert() 函数用于将指定对象插入列表的指定位置。 语法 insert()方法语法&#xff1a; list.insert(index, obj) 参数 • index – 对象 obj 需要插入的索引位置。 • obj – 要插入列表中的对象。 返回值 该方法没有返回值&#xff0c;但会在列表指定位置插…

android5.1 显示方向,Android5.1 Settings.apk定制显示选项

在Android5.0后&#xff0c;系统应用的目录结构发生了一些变化&#xff0c;以往/system/app/下直接是APK文件&#xff0c;目前是/system/app/应用名目录/应用apk类似这种目录结构。同时在Android5.1上反编译Settings.apk需要使用最新apktool_2.0.3来反编译&#xff0c;否则无法…

db2locate函数_DB2常用函数详解

VALUE函数语法&#xff1a;VALUE(EXPRESSION1,EXPRESSION2)VALUE函数是用返回一个非空的值&#xff0c;当其第一个参数非空&#xff0c;直接返回该参数的值&#xff0c;如果第一个参数为空&#xff0c;则返回第一个参数的值。eg:--表示如果T1.ID为空&#xff0c;则返回空串&…

实例22:python

#题目&#xff1a;两个乒乓球队进行比赛&#xff0c;各出三人。甲队为a,b,c三人&#xff0c; #乙队为x,y,z三人。已抽签决定比赛名单。 #有人向队员打听比赛的名单。a说他不和x比&#xff0c;c说他不和x,z比&#xff0c;请编程序找出三队赛手的名单。 #!/usr/bin/python -- c…

CF468B Two Sets

原题链接 DOWNLOAD AS PDF 题目大意 给出\(n\)个各不相同的数字&#xff0c;将它们分别放入\(A\)和\(B\)两个集合中&#xff0c;使它们满足&#xff1a; 若数字\(x\)在集合\(A\)中&#xff0c;那么数字\(a-x\)也在集合\(A\)中&#xff1b;若数字\(x\)在集合\(B\)中&#xff0c;…

windows c语言 redis,windows上使用VS2012 C++语言调用Redis的解决方案

最近我在VS2012上进行Redis开发遇到一些困扰. 编译Redis的lib库没问题。但是使用这些lib库就不太顺利了. 在网上查来查去也没解决。不过其实Redis的客户端项目RedisCli.vcxproj,就是一个最好的使用例子. 我把几个需要注意的地方贴出来注意事项1. 链接器->输入->忽略所有默…

plantuml 方法图_PlantUML 语法之时序图

plantUML 下载(含《plantUML语法指南手册》)&#xff1a;http://plantuml.com/downloadVisual Studio Code 安装 plantUML 插件&#xff0c;在插件应用商店中搜索&#xff1a;PlantUML&#xff0c;点击安装即可。快捷键&#xff1a;Alt D 即可快速预览&#xff0c;Ctrl Shift…

运维实施面试题

记得不是很清楚了&#xff0c;大概回忆一下 1集线器&#xff0c;路由器。交换机的区别 术语解释   路由器&#xff1a;&#xff08;Router&#xff09;是连接因特网中各局域网、广域网的设备。在路由器中记录着路由表&#xff0c;它会根据信道的情况自动选择和设定路由&#…

CCF 201312-3 最大的矩形[比较简单]

问题描述 试题编号&#xff1a;201312-3试题名称&#xff1a;最大的矩形时间限制&#xff1a;1.0s内存限制&#xff1a;256.0MB问题描述&#xff1a; 问题描述在横轴上放了n个相邻的矩形&#xff0c;每个矩形的宽度是1&#xff0c;而第i&#xff08;1 ≤ i ≤ n&#xff09;个矩…

鸿蒙系统太烂,一加终于觉醒!变相承认系统太烂,魅族的吐槽一针见血

刘作虎宣布&#xff0c;一加9系列出厂预装ColorOS 11&#xff0c;终于证实了外界的猜想&#xff0c;一加终于也要放弃自己的系统&#xff0c;这已经证明了之前的氢系统已经在国内市场上彻底失败。想要收服用户&#xff0c;还是需要本土定制化的应用。不过这也显示出一加手机的决…

安卓开发toolbar设置logo_Android之ToolBar的使用

Toolbar是在 Android 5.0 开始推出的一个 Material Design 风格的导航控件 &#xff0c;Google 非常推荐大家使用 Toolbar 来作为Android客户端的导航栏&#xff0c;以此来取代之前的 Actionbar 。与 Actionbar 相比&#xff0c; Toolbar 明显要灵活的多。它不像 Actionbar 一样…

实例23:python

#题目&#xff1a;打印出如下图案&#xff08;菱形&#xff09;: * *** ***** #******* ***** *** * #先把图形分成两部分来看待&#xff0c;前四行一个规律&#xff0c;后三行一个规律&#xff0c;利用双重for循环&#xff0c;第一层控制行&#xff0c;第二层控制列。…

babel 用法及其 .babelrc 的配置详解,想做前端架构,拒绝一知半解...

Babel 官方介绍&#xff1a;将 ECMAScript 2015 及其版本以后的 javascript 代码转为旧版本浏览器或者是环境中向后兼容版本的 javascript 代码。 简而言之&#xff0c;就是把不兼容的 JavaScript 代码转为可兼容&#xff0c;可以执行的 JavaScript 代码。 功能&#xff1a; 语…

android 滚动尺画到控件中间,android 刻度尺控件实现

主要实现刻度尺的效果&#xff0c;能够快速滑动刻度&#xff0c;设置刻度间距&#xff0c;刻度值&#xff0c;滑动回调。简单易用效果图textureView控件的选择总结来说:1.view的绘制在主线程里面&#xff0c;频繁绘制会导致主线程阻塞2.我们知道一个surfaceview是异步绘制的&am…