Python简单实现图片转字符画的实例项目

作者:David 612 时间:2023-02-24 02:01:47 

1. 原理

利用 PIL 库来获取图片并修改大小,
利用灰度值转换公式把每一个像素的 RGB 值转为灰度值


gray = int(0.2126*r+0.7152*g+0.0722*b)

再从字符集里获取对应的字符


asciis = list('M%$@#&WNBRwm8S5A4E3KXFPH69nsxeazgpqbdoctfhkyvuGZYVTUCI2QOD0L7Jjl1ri!^{}[]()/|;:*<>_~-,. ')

最后将字符连接起来并保存就完成了

2. 开始制作

2.1 导入所需的库

在这个工程中,我们需要的第三方库是 PIL
但我们不用 pip install PIL 来安装它,而是使用 pip install pillow


pip install pillow

导入库
在导入 PIL 库时,不能用 import pillow,应使用 import PIL


from PIL import Image as Image

2.2 获取图片路径和选项


inputfile = input('inputfile:')
outputfile = input('outputfile:')
distance = {'y':' ','':' ','n':''}
distance = distance[input('distance?(Y/n):')]
re = input("resize?:")

字母占用的位置是矩形的,因此生成出来的字符画会被“挤压”。我们可以在字母与字母之间添加空格来防止这种情况的发生。
如果图片太大了,会导致耗费时间过长、乱码等问题。我们应该对图片进行必要的缩放。在询问“resize?”时,可以设置以下几种回答:

回答方式作用
“”,啥也不输入不缩放
“100”,边长输入单个数字时,会按比例缩放为较长边为此长度的矩形
“100,200”,宽和高缩放为指定宽高的矩形

2.3 图片获取

使用 PILopen 函数打开图片


image = Image.open(inputfile)

注意:这里的 open 函数不要和 python 内置函数 open 混淆

2.4 调整图片大小

获取图片大小


w, h = image.size

获取变量 re 中存储的大小信息,并用函数 split 分割


nwh = re.split(',')
for i in range(len(nwh)):
   nwh[i] = int(nwh[i])

调整图片大小


if len(nwh) == 1:
   #如果项数为1,表示用户只输入了一个数字。即按比例缩放为较长边为此长度的矩形
   ww = int(nwh[0] / max(w,h) * w) #max函数获取较大值
   hh = int(nwh[0] / max(w,h) * h)
   image = image.resize((ww,hh),Image.ANTIALIAS)
   #改变图片大小
   #第一个参数放入一个元组,指定宽高
   #第二个参数 Image.ANTIALIAS 表示获取高质量图片
else:
   #项数不为1,缩放为指定宽高的矩形
   image = image.resize((nwh[0],nwh[1]),Image.ANTIALIAS)

2.5 转换字符

指定转换的字符集


asciis = list('M%$@#&WNBRwm8S5A4E3KXFPH69nsxeazgpqbdoctfhkyvuGZYVTUCI2QOD0L7Jjl1ri!^{}[]()/|;:*<>_~-,. ')
#list函数将字符串转换为列表

定义转换字符的函数


def getasc(r,g,b,t=100): #t为透明度
   if t == 0:
       return(' ') #如果是透明的,则直接返回空值
   else:
       asc = ''
       gray = int(0.2126*r+0.7152*g+0.0722*b) #转灰度值
       asc = asciis[int(len(asciis)/256*(gray))] #获取字符
       return(asc)

开始转换字符


for i in range(h):
   for o in range(w): #按行读取每一个像素的RGB值
       p = image.getpixel((o,i))
       g = getasc(*p) # * 将参数列表转换为多个项
       txt = txt + g + distance #连接字符
   txt = txt + '\n' #换行

函数 getpixel 获取指定位置的 RGB 值,它的第一个参数为元组,传入像素位置 (x,y),如果图片是 JPG 格式的,它会返回含三项的列表 [r,g,b],如果图片是 PNG 格式的,它会返回含四项的列表 [r,g,b,t]t 是透明度

2.6 保存文本

使用 python 内置函数 open 保存文件


with open(outputfile,'w') as f: # 'w' 表示写入
   f.write(txt)

2.7 效果

================== RESTART: D:\Python38-32\Files\ji2a\ji2a.py ==================
=====image to ascii=====
inputfile:
dora.png
outputfile:
dora.txt
distance?(Y/n):
y
resize?(needn't:'', square:side length, restangle:width,height):
100

Opening 'dora.png'...
Getting...
Saving...
Seccessfully

原图:

Python简单实现图片转字符画的实例项目

结果:

Python简单实现图片转字符画的实例项目

3. 完整代码


from PIL import Image as Image

asciis = list('M%$@#&WNBRwm8S5A4E3KXFPH69nsxeazgpqbdoctfhkyvuGZYVTUCI2QOD0L7Jjl1ri!^{}[]()/|;:*<>_~-,. ')
#gray = int(0.2126*r+0.7152*g+0.0722*b)

def main():
   global asciis

print('=====image to ascii=====')

inputfile, outputfile, distance, re = getargs()

image = openfile(inputfile)

image = resize(image,re)
   w, h = image.size

txt = gettxt(image,w,h,distance)

savefile(outputfile,txt)

print('Seccessfully')

def getargs():
   inputfile = input('inputfile:\n')
   outputfile = input('outputfile:\n')
   distance = {'':' ','y':' ','n':''}
   distance = distance[input('distance?(Y/n):\n')]
   re = input("resize?(needn't:'', square:side length, restangle:width,height):\n")

return(inputfile,outputfile,distance,re)

def openfile(inputfile):
   print("\nOpening '"+inputfile+"'...")
   image = Image.open(inputfile)

return(image)

def resize(image,re):
   if re != '':
       print('Resizing...')
       nwh = re.split(',')
       for i in range(len(nwh)):nwh[i]=int(nwh[i])
       w, h = image.size

if len(nwh) == 1:
           ww = int(nwh[0] / max(w,h) * w)
           hh = int(nwh[0] / max(w,h) * h)
           image = image.resize((ww,hh),Image.ANTIALIAS)
       else:
           image = image.resize((nwh[0],nwh[1]),Image.ANTIALIAS)

return(image)

def gettxt(image,w,h,distance):    
   txt = ''
   print('Getting...')

for i in range(h):
       for o in range(w):
           p = image.getpixel((o,i))
           txt = txt + getasc(*p) + distance
       txt = txt + '\n'

return(txt)

def getasc(r,g,b,t=100):
   if t == 0:
       return(' ')
   else:
       asc = ''
       gray = int(0.2126*r+0.7152*g+0.0722*b)
       asc = asciis[int(len(asciis)/256*(gray))]
       return(asc)

def savefile(outputfile,txt):
   print('Saving...')

with open(outputfile,'w') as f:
       f.write(txt)

return()

if __name__ == '__main__':
   main()

此代码在 Python3.8 下调试通过

4. 后记

我们的图片转字符画程序完成了!

要想将它打造成一个真正的命令行工具,可以加入命令行参数功能,
利用 sys 模块的 argv 函数获取命令行参数,
利用 getopt 模块的 getop 函数解析命令行参数。

来源:https://blog.csdn.net/weixin_48448842/article/details/115803401

标签:Python,图片,字符画
0
投稿

猜你喜欢

  • python爬虫之scrapy框架详解

    2023-08-23 13:16:52
  • 用Python自动发邮件提醒你周末吃啥

    2022-04-10 11:44:28
  • Python数组条件过滤filter函数使用示例

    2021-06-11 15:10:51
  • BeautifulSoup中find和find_all的使用详解

    2023-11-08 21:00:22
  • asp如何获知文件最后的修改日期和时间?

    2009-11-24 20:49:00
  • tensorflow模型继续训练 fineturn实例

    2023-07-10 12:53:09
  • SQLite3中文编码 Python的实现

    2023-02-03 13:21:38
  • Python 如何强制限定小数点位数

    2022-10-01 15:25:43
  • python爬虫爬取股票的k线图

    2021-06-30 15:54:37
  • python优化数据预处理方法Pandas pipe详解

    2021-12-27 06:34:51
  • mac下如何将python2.7改为python3

    2023-12-07 17:14:43
  • 装载iframe 子页面,自适应高度

    2008-11-20 12:53:00
  • golang编程入门之http请求天气实例

    2024-05-09 09:32:00
  • Python人脸识别初探

    2023-01-24 09:39:58
  • 对Python的交互模式和直接运行.py文件的区别详解

    2023-12-18 00:03:55
  • 一个有趣的SQL命题 用一条语句切换BIT型的真假值

    2024-01-24 04:57:38
  • JavaScript中常见的几种获取元素的方式

    2023-07-13 07:46:12
  • JavaScript入门学习书籍的阶段选择

    2008-01-11 19:39:00
  • python实现DEM数据的阴影生成的方法

    2023-11-09 11:17:25
  • python/golang 删除链表中的元素

    2021-05-05 14:08:07
  • asp之家 网络编程 m.aspxhome.com