Python实例题:Python3实现图片转彩色字符

目录

Python实例题

题目

代码实现

实现原理

图像预处理:

灰度值计算:

字符映射:

彩色输出:

关键代码解析

1. 字符映射和灰度计算

2. 图像模式输出

3. 命令行参数处理

使用说明

基本用法(终端输出):

保存为图像文件:

调整字符画大小:

自定义字符集:

查看完整帮助:

扩展建议

增强功能:

性能优化:

用户界面:

输出格式:

Python实例题

题目

Python3实现图片转彩色字符

代码实现

import argparse
import os
from PIL import Image, ImageDraw, ImageFont
import sys
import termcolor
import platform

class ImageToColorAscii:
    def __init__(self, width=80, height=40, 
                 charset=" .:-=+*#%@", 
                 bg_color=(0, 0, 0), 
                 fill_color=(255, 255, 255),
                 output_mode="terminal"):
        """初始化图片转彩色字符画转换器
        
        Args:
            width: 输出字符画的宽度
            height: 输出字符画的高度
            charset: 用于绘制的字符集,按从暗到亮的顺序排列
            bg_color: 背景颜色,默认为黑色
            fill_color: 填充颜色,默认为白色
            output_mode: 输出模式,可选"terminal"或"image"
        """
        self.width = width
        self.height = height
        self.charset = charset
        self.bg_color = bg_color
        self.fill_color = fill_color
        self.output_mode = output_mode
        self.terminal_support_color = self._check_terminal_color_support()
    
    def _check_terminal_color_support(self):
        """检查终端是否支持彩色输出"""
        if platform.system() == 'Windows':
            return False  # Windows终端默认不支持ANSI颜色
        return True
    
    def convert(self, image_path, output_path=None):
        """将图片转换为彩色字符画
        
        Args:
            image_path: 输入图片路径
            output_path: 输出文件路径,默认为None(直接打印到终端)
        
        Returns:
            转换后的字符画字符串或生成的图片路径
        """
        try:
            # 打开并调整图片大小
            with Image.open(image_path) as img:
                img = img.resize((self.width, self.height), Image.LANCZOS)
                
                # 转换为RGB模式
                img = img.convert("RGB")
                
                # 生成字符画
                if self.output_mode == "terminal":
                    return self._convert_to_terminal(img)
                else:
                    return self._convert_to_image(img, output_path)
        except Exception as e:
            print(f"转换失败: {e}")
            return None
    
    def _convert_to_terminal(self, img):
        """将图片转换为终端彩色字符画
        
        Args:
            img: PIL Image对象
        
        Returns:
            彩色字符画字符串
        """
        ascii_art = []
        
        for y in range(self.height):
            line = []
            for x in range(self.width):
                r, g, b = img.getpixel((x, y))
                
                # 计算灰度值
                gray = int(0.299 * r + 0.587 * g + 0.114 * b)
                
                # 根据灰度值选择字符
                char_index = min(int(gray * len(self.charset) / 256), len(self.charset) - 1)
                char = self.charset[char_index]
                
                # 添加彩色字符
                if self.terminal_support_color:
                    colored_char = termcolor.colored(char, color=None, on_color=None, attrs=None)
                    line.append(colored_char)
                else:
                    line.append(char)
            
            ascii_art.append(''.join(line))
        
        return '\n'.join(ascii_art)
    
    def _convert_to_image(self, img, output_path=None):
        """将图片转换为图像格式的彩色字符画
        
        Args:
            img: PIL Image对象
            output_path: 输出图片路径
        
        Returns:
            输出图片路径
        """
        # 创建新图像
        char_width = 10
        char_height = 18
        output_img = Image.new('RGB', (self.width * char_width, self.height * char_height), self.bg_color)
        draw = ImageDraw.Draw(output_img)
        
        # 尝试加载中文字体
        try:
            font = ImageFont.truetype("simhei.ttf", 14)
        except IOError:
            # 使用默认字体
            font = ImageFont.load_default()
        
        for y in range(self.height):
            for x in range(self.width):
                r, g, b = img.getpixel((x, y))
                
                # 计算灰度值
                gray = int(0.299 * r + 0.587 * g + 0.114 * b)
                
                # 根据灰度值选择字符
                char_index = min(int(gray * len(self.charset) / 256), len(self.charset) - 1)
                char = self.charset[char_index]
                
                # 绘制字符
                draw.text((x * char_width, y * char_height), char, font=font, fill=(r, g, b))
        
        # 保存图像
        if not output_path:
            base, ext = os.path.splitext(os.path.basename(image_path))
            output_path = f"{base}_ascii.png"
        
        output_img.save(output_path)
        return output_path


def main():
    parser = argparse.ArgumentParser(description='图片转彩色字符画工具')
    parser.add_argument('-i', '--input', required=True, help='输入图片路径')
    parser.add_argument('-o', '--output', help='输出文件路径,默认为终端或原文件名加_ascii后缀')
    parser.add_argument('--width', type=int, default=80, help='输出宽度,默认为80')
    parser.add_argument('--height', type=int, default=40, help='输出高度,默认为40')
    parser.add_argument('--charset', default=" .:-=+*#%@", help='字符集,按从暗到亮的顺序排列')
    parser.add_argument('--bg-color', default="0,0,0", help='背景颜色,RGB值,用逗号分隔')
    parser.add_argument('--fill-color', default="255,255,255", help='填充颜色,RGB值,用逗号分隔')
    parser.add_argument('--mode', choices=['terminal', 'image'], default='terminal', help='输出模式,可选terminal或image')
    
    args = parser.parse_args()
    
    # 解析颜色参数
    bg_color = tuple(map(int, args.bg_color.split(',')))
    fill_color = tuple(map(int, args.fill_color.split(',')))
    
    # 创建转换器
    converter = ImageToColorAscii(
        width=args.width,
        height=args.height,
        charset=args.charset,
        bg_color=bg_color,
        fill_color=fill_color,
        output_mode=args.mode
    )
    
    # 执行转换
    result = converter.convert(args.input, args.output)
    
    if result:
        if args.mode == 'terminal':
            print(result)
            print(f"\n字符画宽度: {args.width}, 高度: {args.height}")
        else:
            print(f"彩色字符画已保存到: {result}")
    else:
        print("转换失败")


if __name__ == "__main__":
    main()    

实现原理

这个图片转彩色字符画工具基于以下核心技术实现:

  • 图像预处理

    • 调整图片大小以适应字符画输出
    • 转换为 RGB 模式以便获取每个像素的颜色值
  • 灰度值计算

    • 使用加权平均法计算 RGB 像素的灰度值
    • 公式:gray = 0.299*R + 0.587*G + 0.114*B
  • 字符映射

    • 根据灰度值选择合适的字符
    • 使用从暗到亮的字符集进行映射
  • 彩色输出

    • 终端模式:使用 ANSI 转义序列输出彩色字符
    • 图像模式:创建新图像并在每个位置绘制对应字符

关键代码解析

1. 字符映射和灰度计算

def _convert_to_terminal(self, img):
    ascii_art = []
    
    for y in range(self.height):
        line = []
        for x in range(self.width):
            r, g, b = img.getpixel((x, y))
            
            # 计算灰度值
            gray = int(0.299 * r + 0.587 * g + 0.114 * b)
            
            # 根据灰度值选择字符
            char_index = min(int(gray * len(self.charset) / 256), len(self.charset) - 1)
            char = self.charset[char_index]
            
            # 添加彩色字符
            if self.terminal_support_color:
                colored_char = termcolor.colored(char, color=None, on_color=None, attrs=None)
                line.append(colored_char)
            else:
                line.append(char)
        
        ascii_art.append(''.join(line))
    
    return '\n'.join(ascii_art)

2. 图像模式输出

def _convert_to_image(self, img, output_path=None):
    char_width = 10
    char_height = 18
    output_img = Image.new('RGB', (self.width * char_width, self.height * char_height), self.bg_color)
    draw = ImageDraw.Draw(output_img)
    
    # 尝试加载中文字体
    try:
        font = ImageFont.truetype("simhei.ttf", 14)
    except IOError:
        font = ImageFont.load_default()
    
    for y in range(self.height):
        for x in range(self.width):
            r, g, b = img.getpixel((x, y))
            gray = int(0.299 * r + 0.587 * g + 0.114 * b)
            char_index = min(int(gray * len(self.charset) / 256), len(self.charset) - 1)
            char = self.charset[char_index]
            
            # 绘制字符,使用原始RGB颜色
            draw.text((x * char_width, y * char_height), char, font=font, fill=(r, g, b))
    
    # 保存图像
    if not output_path:
        base, ext = os.path.splitext(os.path.basename(image_path))
        output_path = f"{base}_ascii.png"
    
    output_img.save(output_path)
    return output_path

3. 命令行参数处理

def main():
    parser = argparse.ArgumentParser(description='图片转彩色字符画工具')
    parser.add_argument('-i', '--input', required=True, help='输入图片路径')
    parser.add_argument('-o', '--output', help='输出文件路径')
    parser.add_argument('--width', type=int, default=80, help='输出宽度')
    parser.add_argument('--height', type=int, default=40, help='输出高度')
    parser.add_argument('--charset', default=" .:-=+*#%@", help='字符集')
    parser.add_argument('--bg-color', default="0,0,0", help='背景颜色')
    parser.add_argument('--fill-color', default="255,255,255", help='填充颜色')
    parser.add_argument('--mode', choices=['terminal', 'image'], default='terminal', help='输出模式')
    
    args = parser.parse_args()
    
    # 解析颜色参数
    bg_color = tuple(map(int, args.bg_color.split(',')))
    fill_color = tuple(map(int, args.fill_color.split(',')))
    
    # 创建转换器并执行转换
    converter = ImageToColorAscii(
        width=args.width,
        height=args.height,
        charset=args.charset,
        bg_color=bg_color,
        fill_color=fill_color,
        output_mode=args.mode
    )
    
    result = converter.convert(args.input, args.output)
    
    if result:
        if args.mode == 'terminal':
            print(result)
        else:
            print(f"彩色字符画已保存到: {result}")

使用说明

  • 基本用法(终端输出)

python image_to_color_ascii.py -i input.jpg
  • 保存为图像文件

python image_to_color_ascii.py -i input.jpg -o output.png --mode image
  • 调整字符画大小

python image_to_color_ascii.py -i input.jpg --width 120 --height 60
  • 自定义字符集

python image_to_color_ascii.py -i input.jpg --charset " .:;+=xX$#@"
  • 查看完整帮助

python image_to_color_ascii.py --help

扩展建议

  • 增强功能

    • 添加对动图的支持
    • 实现不同的字符渲染算法
    • 添加艺术滤镜效果
    • 支持视频转字符动画
  • 性能优化

    • 使用 NumPy 加速图像处理
    • 优化字符选择算法
    • 实现多线程处理
  • 用户界面

    • 开发图形界面版本
    • 添加实时预览功能
    • 支持交互式调整参数
  • 输出格式

    • 支持导出为 HTML、SVG 等格式
    • 添加对不同字体的支持
    • 实现彩色 PDF 输出
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值