DAY 1 项目1:Python图片转字符画

2019.4.2

虽然自己十分喜欢Python,但一直都只是处于入门的状态而已,平时没有通过一些小项目来增强自己的能力,因此找了逼乎上很多的一些Python小项目来练练手,并凭此文来记录进度。



DAY 1:

项目1:Python图片转字符画


1. 声明

项目来自于实验楼文章的作用仅用于自己记录学习,并且该项目在实验楼免费。如若侵权,请及时联系我删除。


2. 需要用到的模块

1. argparse模块

argparse文档


  1. 概述

argparse模块用于处理命令行的参数在本例中,就是使用命令行打开一个图片文件,并通过argparse的一个实例parser去获取之后处理图片会用到的一些参数(输入文件、输出文件的路径,长宽高等等)。


  1. 用到的函数
  • argparse.ArgumentParser()用于实例化一个argparse对象,这些参数基本不用管。
  • ArgumentParser.add_argument()用于从命令行参数中获取信息,添加到argparse类实例中。
  • ArgumentParser.parse_args()将参数字符串转换为对象并将其指定为命名空间的属性。返回填充的命名空间。只有使用了这个函数,才能使用相应对象的参数。本例中就是用了args来接收属性参数。


2. PIL(Pillow).Image模块

Pillow.Image模块文档


  1. 概述

PIL(原名,现已更名为pillow,但使用时仍打作PIL) 是python中的标准的图形图像处理模块,拥有强大的图像处理功能。本例中将用它来打开图像文件,以方便对图像进行处理。


  1. 用到的函数
  • PIL.Image.open()用于读取指定路径的图片。
  • PIL.Image.resize()根据args得到的命令行的属性对图片进行宽和高的修改,其中的'NEAREST'参数表示以低质量输出图片。


3. 代码分析


  1. 准备部分:实例化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

  1. 编程像素转换成字符的函数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)]

  1. 编写主函数,处理图片,输出转换后的图片并写入到一个输出文件中
  • 打开图片文件,根据命令行获得的参数来重新调整图片的大小
  • 创建空字符串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 
  1. 效果

    • 终端


      DAY 1 项目1:Python图片转字符画_第1张图片
      哆啦A梦的头
    DAY 1 项目1:Python图片转字符画_第2张图片
    哆啦A梦的腰
    DAY 1 项目1:Python图片转字符画_第3张图片
    哆啦A梦的小短腿
    • 文件中的效果


      DAY 1 项目1:Python图片转字符画_第4张图片
      哆啦A梦
    DAY 1 项目1:Python图片转字符画_第5张图片
    小绵羊


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真的很有趣,加油,做个大神吧!



你可能感兴趣的:(DAY 1 项目1:Python图片转字符画)