前言
最近看完了python的基础语法,该怎么继续呢?还是继续在网上找课程,学习吧,也计划看看有没有可以利用在工作上的内容。
近一周多搞了两个内容,都是利用python处理图片,一个是在图片上的最左上角输入字符,一个是用python生成字符画,这里呢因为都用到了pillow库所以放在一起记录一下。
pillow库简单介绍
是一个图像处理的库。自己参考了这两篇内容: https://zhuanlan.zhihu.com/p/59849190 https://zhuanlan.zhihu.com/p/58671158
1、python图片上添加文字
这里要求的是 图片的左上角放置一段文字 。 首先需要导入库的几个类
from PIL import Image,ImageDraw,ImageFont
接下来我们要用python读取图片来进行后续的操作
image1 = Image.open(path) #path是图片路径,windows的话写成类似'C:\\Users\\ytds\\Desktop\\MYTEST\\ca.jpg'
要在图片上进行绘制,需要再根据Image对象创建ImageDraw对象。
draw = ImageDraw.Draw(image1)
现在我们就可以调用draw的不同方法在我们读取的图片上绘画了,具体介绍看上边的第一个链接。
这里我们要做的是写字,所以用到的方法是:draw.text()。这里我总结一下自己使用时的点:
如果不设置字体参数,则不能调整图片上的字大小(我没有找到调整的方法,我只会通过字体参数来调整字的大小)因为上边提到了要设字体参数,那么我们需要指定一个字体,这里可以调整它的大小。
font = ImageFont.truetype('C:\\Users\\ytds\\Desktop\\MYTEST\\calibri.ttf',size=num)
有了字体我们就可以往图片上写字了。
draw.text((x,y),text,font=font,fill='#DC143C') #(x,y)是第一个字的位置
至此,我们基本就实现了我们的想法。但是还有几个问题
如何判断一段文字能被放入图片中(这里牵扯到是否换行,我是选择不换行) 如何确保一段文字刚好在最左边?要解决以上问题,我们需要知道图片的大小和文字的大小,可以通过以下方法获得
image1.width #获取图片的宽 image1.height #获取图片的高 move = draw.textsize(text,font) #获取绘制文字的大小,返回一个元组(width,height)
这样通过一些判断就可以解决问题了。剩下的就是把我们操作后的东西保存成图片了。
image1.save(path)
2、python绘制字符画
这是一个根据一个教程走完的,这里推荐一个地址:https://www.bilibili.com/read/cv1859294/ 里面介绍了字符画的实现原理,通过这个可以了解关键函数的基本原理。
2.1 代码目标读取一副图片,用字符给出模拟图。命令行接收参数,参数写法类似于操作系统命令。
pyton3 pic.py filename -o filename --height xxx
2.2 接受参数的部分实现首先继续是一个参考网址:https://docs.python.org/zh-cn/3/howto/argparse.html#argparse-tutorial 可以深入了解需要的内容或是丰富选项。
我们的代码就接受一个图片,给出一个存放字符内容的文件,以及可以设置字符画的宽和高,宽和高默认的值为300。设置代码如下:
import argparse #导入模块 #命令行输入参数处理 parser = argparse.ArgumentParser() ## 以下是添加了从命令行可以接受的参数名称,以及参数的类型和默认值 parser.add_argument('file') #位置参数,必须有,输入文件 parser.add_argument('-o', '--output') #可选参数 输出文件 parser.add_argument('--width', type = int, default = 80) #可选参数,默认类型为字符,这里指定成数字 输出字符画宽 parser.add_argument('--height', type = int, default = 80) # 输出字符画高 #获取参数 args = parser.parse_args()
这样我们给出的参数就保存在args中了,用args.来使用参数。
IMG = args.file WIDTH = args.width HEIGHT = args.height OUTPUT = args.output2.2 图片转换部分
简单说下思路:图片的彩色值变为灰度值,灰度值对应成字符串中的字符,灰度值有256个,字符串中的字符一般没有那么多,所以要把一个字符对应多个灰度值。
这里我曾有疑问就是字符串的选择是随意的吗?看过开头链接的介绍后我知道了
字符串可以是任意的,都能显示出图片的轮廓,但是如果要像的话,那么最好字符串开始的字符大而满,后边的字符少而小,符合灰度的递减。
下边是教程转换代码:
### 实现图片转换的函数 def get_char(r,g,b,alpha = 256): #参数为图片的 rgba值,前三个比较好理解,最后一个在png图时,没内容的地方值为0 if alpha == 0: # 判断,如果没内容返回空格 return ' ' length = len(ascii_char) gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b) #彩色转灰度 unit = (256.0 + 1)/length return ascii_char[int(gray/unit)] # 灰度转成字符串的index
至此,我们能把一个个的灰度转换成字符了,后续我们只要直接获取图片的所有灰度值,并打印出字符即可了。
from PIL import Image im = Image.open(IMG) #打开图片 im = im.resize((WIDTH,HEIGHT), Image.NEAREST) #调整图片大小 txt = "" for i in range(HEIGHT): for j in range(WIDTH): txt += get_char(*im.getpixel((j,i))) #获取的值传给get_char()函数,值是一个元组 txt += '\n' #换行 print(txt)
上边用到了一个我之前不知道的内容
In [1]: a = (1,2,3,4) In [2]: b,c,d,e= *a File "<ipython-input-2-3f4b061fea3e>", line 4 SyntaxError: can't use starred expression here In [3]: *a File "<ipython-input-3-b252d56222c4>", line 4 SyntaxError: can't use starred expression here In [4]: print(*a) 1 2 3 4 In [5]: def test(b,c,d,e): ...: return b+c+d+e...: In [6]: test(*a) #当参数带* Out[6]: 10 In [7]: b,c,d,e= a #不用*,可直接拆开 In [8]: b Out[8]: 1
就是知道一下元组可以这样用,至于原因先不查了。
3 结尾
回过头再看一遍,其实难的地方不多,大部分是知道了就可以用的知识。当然了,熟练度还是很重要的。
现就这样慢慢的熟悉一下python,再继续往后走吧。
查看更多关于python入门,字符画和图片写字的详细内容...