Python 图片转字符画 Pillow库的使用

主要思路

读取彩色图片的RGB值,利用公式转化为灰度值,并建立灰度值与自定义字符集质检的映射关系。最后将每个像素对应的字符按照原位置打印出来

公式和库

  • 灰度值 = 0.2126 * r + 0.7152 * g + 0.0722 * b 

这是一个比较有名的心理学公式,系数的取值依据的是人眼对不同原色的敏感度不同。

  • Pillow(PIL)库

Python的一个图像处理库。使用前需要安装。

Linux python3 环境下安装: sudo pip3 install pillow

官方文档:http://effbot.org/imagingbook/

  • argparse 库

命令行选项与参数控制库。系统库,使用前需import

测试图片和结果

 

Python 图片转字符画 Pillow库的使用_第1张图片

表白居老师 ^-^

 

源代码

以下源码参考自https://www.shiyanlou.com/courses/370 并按照自己的理解添加了注释。

编译时如果因为中文编码报错,需要在代码第一行添加 #coding=utf-8 指定中文编码方式。

 

from PIL import Image 
#安装图像处理库 pillow(PIL)
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)

'''
第一个参数file为位置参数,多个位置参数必须按定义顺序赋值。
-,--表示参数为可选参数。-后面只能跟一个字母,--后面可跟任意字符串
可选参数可以不赋值,也可以插在位置参数的任意位置,无需按顺序赋值
Eg. Python3 ascii.py -height 75 ascii_dora.png 代表了将ascii_dora.png赋值给file变量,75 赋值给height。output和width缺省
'''

args = parser.parse_args()

IMG = args.file
WIDTH = args.width
HEIGHT = args.height
OUTPUT = args.output

ascii_char = list("@@@*o0'/\0o*`.`.") 
#ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ") 
'''
字符串列表里面的内容可以自己根据图片色块的不同自行定义。可能需要多次测试才能有比较好的结果。
一般来说,越前面的字符串,代表灰度值越低,越接近黑色
注释掉的70个字符(最后一个字符是空格)是比较常用的一个序列,供大家参考
'''

def get_char(r,g,b,alpha = 256):
	if alpha == 0:
		return '  ' 
    
    '''
	透明色要单独处理,因为(225,225,225)白色,(0,0,0)黑色。透明色(0,0,0,0),如果不单独处理,就会被当成黑色
    '''
	
    length = len(ascii_char)
	gray = int(0.2126*r+0.7152*g +0.0722*b) 
	#业界惯用的彩色图像转灰度图像公式之一。
	#浮点数的运算比较耗时间,所以写成 gray = 2126*r+7152*g +0722*b)/10000会快一点。
	unit = (256.0+1)/length
	#unit = (256.0)/length也可以。
	#一定要写256.0,强行把整型转换为浮点型,否则两个整型相除默认为整型,则unit全部都会为0

    if gray > 250:
		return '  '
    #强行把近似白色的部分,当成背景做透明化处理。要不要这样做需要根据图片来决定。

	return ascii_char[int(gray/unit)]

if __name__=="__main__":

	im = Image.open(IMG) #生成一个image类
	im = im.resize((WIDTH,HEIGHT),Image.NEAREST)
        
    '''
    PIL.Image.NEAREST:最低质量, PIL.Image.BILINEAR:双线性,PIL.Image.BICUBIC:三次样条插值,Image.ANTIALIAS:最高质量
    resize 可以用来缩小,也可以放大,不过放大的话,显然很容易马赛克
    '''

	txt = ""

	for i in range(HEIGHT):
		for j in range(WIDTH):
			txt += get_char(*im.getpixel((j,i))) 
            
            '''
            getpixel根据图片的不同,返回值也不同。灰度图像返回指定像素的灰度值,RGB图像返回        
           (R,G,B)元组,RGBA返回(R,G,B,Alpha),其中Alpha为透明度
            *是元组传参数值给函数的一种用法,代表将元组解包,分别传给对应的变量。
            '''

		txt += '\n'

	print (txt)

	if OUTPUT:
		with open(OUTPUT,'w') as f:
		#with是与资源访问有关的异常处理功能。无论访问过程中是否出现异常,在with语句块结束后,都会自动关闭资源,解除占用
		#以写的方式打开OUTPUT指定的文件,并将其赋予变量f
			f.write(txt)
	else:
		with open("output.txt",'w') as f:
			f.write(txt)

你可能感兴趣的:(Python 图片转字符画 Pillow库的使用)