制作ASCII文本艺术图形

Hello ! 我是小恒不会java

背景

阅读国外一书《python playground》之中写道:将图片图像转化为ASCII文本图像,很有意思,以前都是用文字生成ASCII文本艺术,比如:

  _                            
 | |__     ___   _ __     __ _ 
 | '_ \   / _ \ | '_ \   / _` |
 | | | | |  __/ | | | | | (_| |
 |_| |_|  \___| |_| |_|  \__, |
                         |___/ 

图片生成ASCII

直接上Mahesh的代码,我稍微修改汉化了一下哈

# ascii.py
# 一个将图像转换为ASCII艺术的Python程序。

import sys, random, argparse
import numpy as np
import math

from PIL import Image

# 来自:http://paulbourke.net/dataformats/asciiart/
# 70级灰度值
gscale1 = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. "
# 10级灰度值
gscale2 = '@%#*+=-:. '

def getAverageL(image):
    """
    给定PIL Image对象,返回其灰度平均值
    """
    # 将图像转换为NumPy数组
    im = np.array(image)
    # 获取图像形状
    w, h = im.shape
    # 计算平均值
    return np.average(im.reshape(w * h))

def covertImageToAscii(fileName, cols, scale, moreLevels):
    """
    给定图像文件名及尺寸(行数,列数),返回一个由ASCII字符组成的m*n二维列表
    """
    # 声明全局变量
    global gscale1, gscale2
    # 打开图像并将其转换为灰度模式
    image = Image.open(fileName).convert('L')
    # 存储原始尺寸
    W, H = image.size[0], image.size[1]
    print("输入图像尺寸: %d x %d" % (W, H))
    # 计算每列的宽度
    w = W / cols
    # 根据比例和缩放因子计算每行的高度
    h = w / scale
    # 计算所需的行数
    rows = int(H / h)

    print("列数: %d, 行数: %d" % (cols, rows))
    print("每个单元格尺寸: %d x %d" % (w, h))

    # 检查图像尺寸是否小于指定的列数
    if cols > W or rows > H:
        print("对于指定的列数,图像太小了!")
        exit(0)

    # ASCII图像是一个由字符字符串构成的列表
    aimg = []
    # 生成一组维度数据
    for j in range(rows):
        y1 = int(j * h)
        y2 = int((j + 1) * h)
        # 对于最后一行单元格进行纠正
        if j == rows - 1:
            y2 = H
        # 添加一个空字符串
        aimg.append("")
        for i in range(cols):
            # 计算当前单元格左上角和右下角的坐标
            x1 = int(i * w)
            x2 = int((i + 1) * w)
            # 对于最后一列单元格进行纠正
            if i == cols - 1:
                x2 = W
            # 截取图像中的对应区域
            img = image.crop((x1, y1, x2, y2))
            # 计算该区域的平均亮度
            avg = int(getAverageL(img))
            # 查找对应的ASCII字符
            if moreLevels:
                gsval = gscale1[int((avg * 69) / 255)]
            else:
                gsval = gscale2[int((avg * 9) / 255)]
            # 将ASCII字符添加到字符串中
            aimg[j] += gsval

    # 返回ASCII文本图像
    return aimg

# 主函数
def main():
    # 创建解析器
    descStr = "此程序用于将图像转换为ASCII艺术形式。"
    parser = argparse.ArgumentParser(description=descStr)
    # 添加期望的参数
    parser.add_argument('--file', dest='imgFile', required=True)
    parser.add_argument('--scale', dest='scale', required=False)
    parser.add_argument('--out', dest='outFile', required=False)
    parser.add_argument('--cols', dest='cols', required=False)
    parser.add_argument('--morelevels', dest='moreLevels', action='store_true')

    # 解析参数
    args = parser.parse_args()

    imgFile = args.imgFile
    # 设置输出文件默认名为'out.txt'
    outFile = 'out.txt'
    if args.outFile:
        outFile = args.outFile
    # 设置缩放因子默认值为0.43,适合Courier字体
    scale = 0.43
    if args.scale:
        scale = float(args.scale)
    # 设置列数默认值为80
    cols = 80
    if args.cols:
        cols = int(args.cols)

    print('正在生成ASCII艺术...')
    # 将图像转换为ASCII文本
    aimg = covertImageToAscii(imgFile, cols, scale, args.moreLevels)

    # 打开文件
    with open(outFile, 'w') as f:
        # 将ASCII艺术写入文件
        for row in aimg:
            f.write(row + '\n')
    # 清理操作
    print("ASCII艺术已写入至 %s" % outFile)

# 当作为主脚本执行时调用main函数
if __name__ == '__main__':
    main()

运行

python c:/Users/李恒/Desktop/pp-master/ascii/ascii.py --file "C:\Users\李恒\Desktop\图库\80.png"

这将确保文件路径被正确解析(这是我的py文件路径)。

如果还需要指定其他参数,例如--scale--out--cols,请确保它们也用双引号括起来。

python c:/Users/李恒/Desktop/pp-master/ascii/ascii.py --file "C:\Users\李恒\Desktop\图库\80.png" --scale 0.43 --out "C:\Users\李恒\Desktop\output.txt" --cols 80
  1. 缩放因子或垂直比例系数(--scale):缩放因子会影响输出图像的大小。较小的缩放因子将导致输出图像较大,而较大的缩放因子将导致输出图像较小。请注意,缩放因子应根据所选字体的大小进行调整。

  2. 更改列数(--cols):列数会影响输出图像的宽度。增加列数将使输出图像更宽,而减少列数将使输出图像更窄。

  3. 使用更多的灰度级别(--morelevels):使用更多的灰度级别将提高输出图像的细节和对比度。请注意,这可能会导致输出图像的大小增加。

效果展示

基本原理

1.将图片转成灰度

定义灰度梯度,从10级到70级,也就是模拟从最亮到黑暗的变化过程

使用image.convert将打开的图片转化为灰度

2.将图片分成M*N小块,修正M以调整纵横比

设置列数(默认80),用--cols,再通过比例系数scale(默认0.43)计算对应行数

3.计算每小块亮度,并为小块寻找ASCII字符

使用getAverageL()函数实现每小块亮度计算

4.最后为程序定义命令行选项
5.汇集小块ASCII字符串,打印至文件

扩展

我准备扩展它的功能

  1. 色彩支持: 目前,程序仅处理灰度图像。如果要支持彩色图像,可以分别对红、绿、蓝三个通道计算平均亮度,并结合这三个通道的亮度选择合适的ASCII字符。

  2. 更精细的灰度映射: 现有的两个灰度等级表可以进一步优化,比如创建更多的级别,或者允许用户自定义灰度映射表。

  3. 自适应缩放: 程序目前要求用户提供列数和缩放因子。为了增加灵活性,您可以自动调整这些值以更好地适应图像的宽高比,确保输出的ASCII艺术具有较好的视觉效果。

  4. 动态字体大小: 考虑根据ASCII字符的实际宽度在终端或其他环境中显示,动态调整字符间距,使得输出的ASCII艺术更具可读性和美观性。

  5. 提供一个GUI界面

  • 16
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值