最近有个热议,说是何同学抄袭 ASCII-generator 到自己的视频里。
然后借着事件营销,ASCII-generator 的 star 量凶猛地上涨。
ASCII-generator 是一个使用 Python 将图像转换为 ASCII 字符画的小工具(作者得多无聊,才会写着玩具)
在本教程中,我们将学习如何使用 Python 将图像转换为 ASCII 字符画。该过程主要涉及图像处理和字符映射技术,结合 OpenCV 和 NumPy 库来实现。
参考复现的链接详见:https://github.com/XiaomingX/ASCII-generator-plus
实现原理
将图像转换为 ASCII 字符画的核心步骤如下:
灰度化图像:将彩色图像转换为灰度图像,以简化图像的亮度表示。
图像分块:将灰度图像分割成多个单元格,每个单元格用一个 ASCII 字符表示。
亮度映射到字符:根据每个单元格的平均亮度值,选择适当的 ASCII 字符进行替换。
输出字符画:将生成的字符画保存为文本文件。
步骤详解
1. 解析命令行参数
通过 argparse
模块,允许用户通过命令行指定输入图像路径、输出文本路径、字符集模式,以及输出字符画的宽度。
def get_args():
parser = argparse.ArgumentParser(description="将图像转换为 ASCII 字符画")
parser.add_argument("--input", type=str, default="data/input.jpg", help="输入图像的路径")
parser.add_argument("--output", type=str, default="data/output.txt", help="输出文本文件的路径")
parser.add_argument("--mode", type=str, default="complex", choices=["simple", "complex"],
help="字符集模式:简单模式(10个字符)或复杂模式(70个字符)")
parser.add_argument("--num_cols", type=int, default=150, help="输出字符画的宽度(列数)")
return parser.parse_args()
复制代码
2. 根据模式选择字符集
字符集决定了亮度与字符的映射关系。简单模式提供 10 个字符,复杂模式提供 70 个字符,以更精细地表示亮度梯度。
def get_char_list(mode):
if mode == "simple":
return '@%#*+=-:. '
else:
return "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. "
复制代码
3. 转换图像为 ASCII 字符
核心部分是将图像转换为 ASCII 字符画:
灰度化:使用 OpenCV 的 cv2.cvtColor
将图像转换为灰度图像。
分块:将灰度图像分割为若干单元格,每个单元格对应一个字符。
亮度映射:根据单元格的平均灰度值,从字符集中选择对应的字符。
def convert_image_to_ascii(image, char_list, num_cols):
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
height, width = gray_image.shape
cell_width = width / num_cols
cell_height = 2 * cell_width
num_rows = int(height / cell_height)
if num_cols > width or num_rows > height:
print("列数或行数过多,使用默认设置")
cell_width = 6
cell_height = 12
num_cols = int(width / cell_width)
num_rows = int(height / cell_height)
ascii_art = []
num_chars = len(char_list)
for i in range(num_rows):
row = ""
for j in range(num_cols):
cell = gray_image[int(i * cell_height):min(int((i + 1) * cell_height), height),
int(j * cell_width):min(int((j + 1) * cell_width), width)]
avg_brightness = np.mean(cell)
char_index = min(int(avg_brightness * num_chars / 255), num_chars - 1)
row += char_list[char_index]
ascii_art.append(row)
return ascii_art
复制代码
4. 保存 ASCII 字符画
生成的字符画会被保存为文本文件,方便用户查看或进一步使用。
def save_ascii_art(ascii_art, output_path):
with open(output_path, 'w') as output_file:
for row in ascii_art:
output_file.write(row + "\n")
复制代码
5. 主函数整合
通过主函数整合以上功能,接收用户输入并生成 ASCII 字符画。
def main():
args = get_args()
char_list = get_char_list(args.mode)
image = cv2.imread(args.input)
if image is None:
print(f"无法加载图像:{args.input}")
return
ascii_art = convert_image_to_ascii(image, char_list, args.num_cols)
save_ascii_art(ascii_art, args.output)
print(f"ASCII 字符画已保存到 {args.output}")
if __name__ == '__main__':
main()
复制代码
使用方法
安装必要的库:
pip install opencv-python numpy
复制代码
运行脚本,指定输入图像路径、输出路径、字符集模式和宽度:
python ascii_art.py --input "path/to/image.jpg" --output "path/to/output.txt" --mode complex --num_cols 100
复制代码
检查输出文件以查看生成的 ASCII 字符画。
总结
本教程展示了如何通过 Python 和 OpenCV 将图像转换为 ASCII 字符画,详细说明了灰度化、分块和亮度映射的实现原理。您可以根据需求调整参数或扩展功能,例如支持彩色字符画或输出到 HTML 文件。
评论