python中简单的图像操作(一)

学了这么久的 OI ,发现自己竟然完全不会任何有关图像的知识,实在是一件惭愧的事情,于是取学习了一波,并借助 Python 这一强有力的工具,完成了封存多年的一道题目。本文旨在记录这一学习的过程。

准备工作

使用 Python 经行图像操作,当然是要先安装一些库文件,我们选择 Pillow(PIL)

$ pip3 install Pillow

然后就可以使用以下代码来导入这些库文件了。

from PIL import Image

基本操作

以下内容来自博客: https://www.cnblogs.com/kongzhagen/p/6295925.html

Image模块是在Python PIL图像处理中常见的模块,对图像进行基础操作的功能基本都包含于此模块内。如opensaveconvershow…等功能。

open

Image.open(file) ⇒ image
Image.open(file, mode) ⇒ image

要从文件加载图像,使用 open() 函数, 在 Image 模块:

from PIL import Image					##调用库
im = Image.open("Pictures/ithea.jpg")	##文件存在的路径

此时,im 就已经代表了这张名为 ithea.jpg 的图片,你可以利用接下来提到的函数对其经行操作。

show

A.show()

需要知道的是在win/linux的环境下im.show的方式为win/linux自带的图像显示应用。打开并确认给定的图像文件。这个是一个懒操作;该函数只会读文件头,而真实的图像数据直到试图处理该数据才会从文件读取(调用load()方法将强行加载图像数据)。如果变量mode被设置,那必须是“r”。用户可以使用一个字符串(表示文件名称的字符串)或者文件对象作为变量file的值。文件对象必须实现read(),seek()和tell()方法,并且以二进制模式打开。

save

A.save(outfile,options…)
A.save(outfile, format, options…)

若要保存文件,则使用 Image 类的 save() 方法,此时保存文件的文件名就变得十分重要了,除非指定格式,否则这个库将会以文件名的扩展名作为格式保存。使用给定的文件名保存图像。如果变量format缺省,如果可能的话,则从文件名称的扩展名判断文件的格式。该方法返回为空。关键字options为文件编写器提供一些额外的指令。如果编写器不能识别某个选项,它将忽略它。用户可以使用文件对象代替文件名称。在这种情况下,用户必须指定文件格式。文件对象必须实现了seek()、tell()和write()方法,且其以二进制模式打开。如果方法save()因为某些原因失败,这个方法将产生一个异常(通常为IOError异常)。如果发生了异常,该方法也有可能已经创建了文件,并向文件写入了一些数据。如果需要的话,用户的应用程序可以删除这个不完整的文件。

from PIL import Image
im = Image.open("Pictures/ithea.jpg")
im.show()
im.save("Pictures/ithea.png")			##保存
im = Image.open("Pictures/ithea.png")	##打开这个保存的文件

new

Image.new(mode,size) ⇒ image
Image.new(mode, size,color) ⇒ image

使用给定的变量mode和size生成新的图像。Size是给定的宽/高二元组,这是按照像素数来计算的。对于单通道图像,变量color只给定一个值;对于多通道图像,变量color给定一个元组(每个通道对应一个值)。在版本1.1.4及其之后,用户也可以用颜色的名称,比如给变量color赋值为“red”。如果没有对变量color赋值,图像内容将会被全部赋值为0(为黑色)。如果变量color是空,图像将不会被初始化,即图像的内容全为0。这对向该图像复制或绘制某些内容是有用的。

如下为将图像设置为128x128大小的红色图像。

from PIL import Image
im = Image.new(“RGB”, (128, 128), "red") ## 或者将 ”red“ 替换为 "#FF0000"
im.show()

copy

A.copy() ⇒ image

拷贝这个图像。如果用户想粘贴一些数据到这张图,可以使用这个方法,但是原始图像不会受到影响。

from PIL import Image
im = Image.open("Pictures/ithea.jpg")
im_cp = im.copy()
im_cp.show()

crop

A.crop(box) ⇒ image

从当前的图像中返回一个矩形区域的拷贝。变量box是一个四元组,定义了左、上、右和下的像素坐标。用来表示在原始图像中截取的位置坐标,如box(100,100,200,200)就表示在原始图像中以左上角为坐标原点,截取一个100*100(像素为单位)的图像。这是一个懒操作。对源图像的改变可能或者可能不体现在裁减下来的图像中。为了获取一个分离的拷贝,对裁剪的拷贝调用方法load()。

from PIL import Image
im = Image.open("Pictures/ithea.jpg")
box = (100150250300)
im.crop(box).show()

paste

A.paste(B,box)

将一张图粘贴到另一张图像上,准确的说,是将B粘贴到A上。变量box或者是一个给定左上角的2元组,或者是定义了左,上,右和下像素坐标的4元组,或者为空(与(0,0)一样)。如果给定4元组,被粘贴的图像的尺寸必须与区域尺寸一样。如果模式不匹配,被粘贴的图像将被转换为当前图像的模式。

blend

point

split

merge

resize

rotate

getpixel

putpixel

好戏开始

拥有了以上的基础知识,做一些简单的运用也是十分轻松自然的了。

Luogu T24906

我们来看看这道题目,表面看上去挺无厘头的,这一坨坨又黑又白的字符块是干啥的?~~考试要紧,题意不清,扔了扔了。

□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
□■■■■■■■□■■□□■□■□■■■■■□■■■■■■■□
□■□□□□□■□■■□■□□■■■■■□□□■□□□□□■□
□■□■■■□■□□□□■□□■■□■■□■□■□■■■□■□
□■□■■■□■□□□■□■□■■□□□■□□■□■■■□■□
□■□■■■□■□□■□□□■□□■■■□□□■□■■■□■□
□■□□□□□■□■□□■■□□□□■■■■□■□□□□□■□
□■■■■■■■□■□■□■□■□■□■□■□■■■■■■■□
□□□□□□□□□■■■□■■□■□■□□□□□□□□□□□□
□□□□■■□■□□□■□■■□■■□■■□■■■□□□■■□
□■□■□□■□■■□■□■□□□□■□■■■□■■□□□□□
□■□■■■■■□■■□■■■□■□■■□□■■■□□■□□□
□■■■■□□□□□□■■□□□□□□□■■□□□■□■■■□
□□■□□■□■■■□■□□■□■■□■□□■□■■□■□□□
□□□□□□□□□□□■□■■□□■□■□□■■■■□□□□□
□□■■■■□■□□□□■□□■□■■■□□■■□□□□□□□
□□□■□□□□□□■■□■■■■□■■■■■■■□■■□□□
□■□■■■■■□□□■■□■■□■□□■■□■■■■□■□□
□■■□■□□□□■□□□□□■□■□■□■■■□□□■□■□
□□■□□□■■■□■■□□■■□□■□□■■□□□□■□□□
□□□■■■□□■□■□■■■□■■■■■■□■□■■■■■□
□□■■■□■■■□□□□□■■□□■■■■■■■■□□□□□
□□□□□□□□□□□□□□■□■□□□■■□□□■■■■□□
□■■■■■■■□□□■□■■□■□■□■■□■□■□■■■□
□■□□□□□■□□■□■■□■■■■□■■□□□■■■■■□
□■□■■■□■□■■□□□■□■□■□■■■■■■□■□■□
□■□■■■□■□■□□■□□■□■□■□□■■□■■■■■□
□■□■■■□■□□■□□□□■■■■□□■□■□□■■■■□
□■□□□□□■□□■□□□■□□□■□□■□□■□□■□□□
□■■■■■■■□□□□□■■□■□■■□■□□□■■□■□□
□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□

先不管三七二十一,把这段奇奇怪怪的字符复制到记事本里看看,顺便加几个换行

我好像发现了一个天大的秘密,这是一个二维码 !!!但为什么手机扫不出来阿,坑爹啊!

要是能把断断续续字符转为连续的图片,应该能扫出来吧?

人生苦短,我用 Python~

考虑到这个二维码的字符表示时大小为 31×3131\times 31,所以我们令一个方格大小为 16×1616\times16,所以生成的图片大小是 496×496496\times496 的。利用一张白底图片,根据字符,在上面粘贴上相应的黑色方块即可完成这个二维码的生成。

  • 方式一
from PIL import Image
C = open("data", "r").read().split()
n, m = len(C), len(C[0])
A = Image.new("RGB", (16 * n, 16 * m), "#FFFFFF")
B = Image.new("RGB", (16, 16), "#000000")
for i in range(0, n):
	for j in range(0, m):
		if (C[i][j] == '■'):
			A.paste(B, (i * 16, j * 16))
			
A.show()
A.save("img.jpg")
  • 方式二
from PIL import Image
C = open("data", "r").read().split()
n, m = len(C), len(C[0])
A = Image.new("RGB", (n, m), 'white')
for i in range(0, n):
	for j in range(0, m):
		if (C[i][j] == '■'):
			A.putpixel((i, j), (0, 0, 0))

A = A.resize((n * 16, m * 16))			
A.show()
A.save("img.jpg")