2019.4.2
虽然自己十分喜欢Python,但一直都只是处于入门的状态而已,平时没有通过一些小项目来增强自己的能力,因此找了逼乎上很多的一些Python小项目来练练手,并凭此文来记录进度。
DAY 1:
项目1:Python图片转字符画
1. 声明
项目来自于实验楼,文章的作用仅用于自己记录学习,并且该项目在实验楼免费。如若侵权,请及时联系我删除。
2. 需要用到的模块
1. argparse模块
argparse文档
- 概述
argparse模块用于处理命令行的参数,在本例中,就是使用命令行打开一个图片文件,并通过argparse的一个实例parser去获取之后处理图片会用到的一些参数(输入文件、输出文件的路径,长宽高等等)。
- 用到的函数
- argparse.ArgumentParser(),用于实例化一个argparse对象,这些参数基本不用管。
- ArgumentParser.add_argument(),用于从命令行参数中获取信息,添加到argparse类实例中。
- ArgumentParser.parse_args(),将参数字符串转换为对象并将其指定为命名空间的属性。返回填充的命名空间。只有使用了这个函数,才能使用相应对象的参数。本例中就是用了args来接收属性参数。
2. PIL(Pillow).Image模块
Pillow.Image模块文档
- 概述
PIL(原名,现已更名为pillow,但使用时仍打作PIL) 是python中的标准的图形图像处理模块,拥有强大的图像处理功能。本例中将用它来打开图像文件,以方便对图像进行处理。
- 用到的函数
- PIL.Image.open(),用于读取指定路径的图片。
- PIL.Image.resize(),根据args得到的命令行的属性对图片进行宽和高的修改,其中的'NEAREST'参数表示以低质量输出图片。
3. 代码分析
- 准备部分:实例化argparse对象,获取命令行参数
- 实例化argparse对象parser,使用add_argument()方法来设置parser的参数 (图片是通过终端输入打开的,所以要用argparse对象来获取参数)
- 使用parser的parse_args()函数来返回参数对象到args中,并用IMG, WIDE, HEIGHT, OUTPUT来存储参数值。
# -*- coding=utf-8 -*-
from PIL import Image
import argparse #用来管理命令行输入的
#我们首先使用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
args = parser.parse_args()
IMG = args.file
WIDTH = args.width
HEIGHT = args.height
OUTPUT = args.output
- 编程像素转换成字符的函数get_char(),处理图片
- 先用ascii_char来存储转变成字符画所需要用到的所有字符
- get_char()函数实现将每个像素点的RGB值转化为字符的功能,函数接收像素点对应的R,G,B以及alpha值(为256则不为白色,为0则为白色)为参数进行RGB值到指定字符的转换
- 由于灰度的范围为0~255,但字符只有70个,所以要编写一个映射的关系,即ascii_char[int(gary/unit)],得到指定字符的转换
# 将RGB値转为灰度値,然后使用灰度値映射到字符列表中的某个字符。
# 先用ascii_char来储存会用到的所有字符
ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
"""这个函数实现了RGB値到字符的转换,实现以字符来表示像素的功能"""
# 判断alpha的値,是 0则不用转换,是0的位置就显示空白
def get_char(r,g,b,alpha = 256):
if alpha == 0:
return ' '
length = len(ascii_char)
# 将RGB转换成灰度:范围为0-255
gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
#由于灰度范围为0-255,但字符集只有70个,所以要处理一下
#用以下的方法将灰度映射到指定字符
unit = (256.0 + 1)/length
#返回指定的字符
return ascii_char[int(gray/unit)]
- 编写主函数,处理图片,输出转换后的图片并写入到一个输出文件中
- 打开图片文件,根据命令行获得的参数来重新调整图片的大小
- 创建空字符串txt,用于储存字符画
- 遍历图片的每一个像素点(使用getpixel((j,i))可以获得点(i, j)的像素点的RGB值以及alpha值),将其转换成字符
- 输出字符画
if __name__ == '__main__':
#打升并重新设置文件宽高, NEAREST表示输出低质量图片
im = Image.open(IMG)
im = im.resize((WIDTH,HEIGHT), Image.NEAREST)
#初始化 txt
txt = ""
#遍历图片中的每一行像素
for i in range(HEIGHT):
#遍历图片中的每一列像素
for j in range(WIDTH):
#使用 getpixel()可以获得像素点的 RGB値
#然后将用 get_char()获得的字符加入到输出字符串 txt中
txt += get_char(*im.getpixel((j,i)))
txt += '\n'
print(txt)
#字符画输出到文件
if OUTPUT:
with open(OUTPUT,'w') as f:
f.write(txt)
else:
with open("output.txt",'w') as f:
f.write(txt)
4. 运行
终端下输入 : python版本 py文件名 图片文件名(路径)。例如我的linux就是:
python3 pictures_to_character.py ascii_dora.png
-
效果
-
终端
-
文件中的效果
-
5. 完整代码
# -*- coding=utf-8 -*-
from PIL import Image
import argparse #用来管理命令行输入的
#我们首先使用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
args = parser.parse_args()
IMG = args.file
WIDTH = args.width
HEIGHT = args.height
OUTPUT = args.output
# 将RGB値转为灰度値,然后使用灰度値映射到字符列表中的某个字符。
# 先用ascii_char来储存会用到的所有字符
ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
"""这个函数实现了RGB値到字符的转换,实现以字符来表示像素的功能"""
# 判断alpha的値,是 0则不用转换,是0的位置就显示空白
def get_char(r,g,b,alpha = 256):
if alpha == 0:
return ' '
length = len(ascii_char)
# 将RGB转换成灰度:范围为0-255
gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
#由于灰度范围为0-255,但字符集只有70个,所以要处理一下
#用以下的方法将灰度映射到指定字符
unit = (256.0 + 1)/length
#返回指定的字符
return ascii_char[int(gray/unit)]
if __name__ == '__main__':
#打升并重新设置文件宽高, NEAREST表示输出低质量图片
im = Image.open(IMG)
im = im.resize((WIDTH, HEIGHT), Image.NEAREST)
#初始化 txt
txt = ""
#遍历图片中的每一行像素
for i in range(HEIGHT):
#遍历图片中的每一列像素
for j in range(WIDTH):
#使用 getpixel()可以获得像素点的 RGB値
#然后将用 get_char()获得的字符加入到输出字符串 txt中
txt += get_char(*im.getpixel((j,i)))
txt += '\n'
print(txt)
#字符画输出到文件
if OUTPUT:
with open(OUTPUT,'w') as f:
f.write(txt)
else:
with open("output.txt",'w') as f:
f.write(txt)
总结:
其实说实话,通过调用模块,Python真的做到了使用很少的代码做到很强大功能这一点,当我向命令行敲出命令,字符画出现那一刻,我真的像一个地主家的傻儿子那样哈哈哈哈;Python真的很有趣,加油,做个大神吧!