用 Python 把坤坤动起来

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: 最近看到一个 Up 主 Ele实验室 发布的一个视频:字符化视频是怎么做出来的,感觉很有意思。不如自己也实现一个来玩玩?以前也没怎么写过 Python,只用来刷过 LeetCode。正好借这个机会再学一学 Python 吧。

image.png


前言


阅读时长 用脑度 前置知识
5min 25% Python

最近看到一个 Up 主 Ele实验室 发布的一个视频:字符化视频是怎么做出来的,感觉很有意思。不如自己也实现一个来玩玩?


以前也没怎么写过 Python,只用来刷过 LeetCode。正好借这个机会再学一学 Python 吧。


效果



先来看看实现效果。

image.png


Emmm,有那味了。


思路


首先,我们都知道视频本质上是一张张图片快速展示的效果,所以第一步就是将视频进行 分帧


当将视频分成一张张图片后,每张图片里的每个像素点都是由 红、绿、蓝 三原色混合而成的。而这样的混合机制就是通过数值值来表示的,比如 rgb(255, 255, 255) 就是白色,而 rgb(0, 0, 0) 则表示连个颜色都没有,也就是黑色。

image.png


拿到三种值后,可以通过一定计算将单像素变成一个值,一般来说这个过程可以是灰度化。

rgba(255, 255, 255) -> 0
复制代码


拿到灰度后的值,就可以将所有像素映射到 Hash 表上的一个字符,从而形成 字符画

0 -> $
复制代码

将这些字符画都以 txt 文件保存到一个目录,再按顺序打印出来就形成了 字符视频 了。

那我们现在开始实现吧。


分帧


分帧这里可以不用我们实现,直接使用 ffmpeg 就可以了。先用下面命令进行安装:

brew install ffmpeg
复制代码


然后使用这个命令来分帧:

ffmpeg -i res/cxk-video.mov res/image_frames/%d.jpg
复制代码


上面命令很容易理解:res/cxk-video.mov 是原视频,后面的 res/image_frames/%d.jpg 就是存放的路径,%d 表示数字.jpg。

image.png


生成字符画


这里要借用到 Pillow 这个库,可以直接获取图片的 rgb 值。

先安装一下这个库:

pip3 install Pillow
复制代码


如果你是 M1 的 Mac 电脑,需要用下面这两个命令来安装。

sudo python3 -m pip install --upgrade pip
sudo python3 -m pip install --upgrade Pillow
复制代码


然后来实现将图片变成字符画:

from os import listdir
from os.path import isfile, join
image_frames_dir = 'res/image_frames'
txt_frames_dir = 'res/txt_frames'
def prepare(width, height):
    for file_name in listdir(image_frames_dir):
        print("正在处理 " + file_name)
        image_path = join(image_frames_dir, file_name) // 获取图片地址
        txt_path = join(txt_frames_dir, file_name.split('.')[0] + '.txt') // 获取 txt 文件地址
        if not isfile(image_path):
            continue
        image = Image.open(image_path) // 获取图片
        image = image.resize((width, height), Image.NEAREST)  # NEAREST 低质量图
        txt = to_string(image, width, height) // 生成字符文本
        with open(txt_path, 'w') as txt_file: // 保存字符文本
            txt_file.write(txt)
复制代码


使用 getpiexel 获取 tuple 然后通过算法生成 gray 值,再映射到定义好的数组上。

ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
def get_char(r, g, b, alpha=256):
    if alpha == 0:
        return ' '
    length = len(ascii_char)
    gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b) // 生成灰度值
    unit = (256.0 + 1) / length
    return ascii_char[int(gray / unit)] // 映射到字符
def to_string(image, width, height):
    txt = ""
    for h in range(height):
        for w in range(width):
            txt += get_char(*image.getpixel((w, h)))  # 获取 pixel 的颜色数值
        txt += '\n' # 记得最后要换行
    return txt
复制代码


然后就可以生成很多个 txt 文件了。

image.png


字符视频


好了,上面已经可以实现将所有图片转换成字符画了,下面将这些字符画顺序地打印出来就可以了。

import os
from time import sleep
def display(speed):
    def compare_file_name(file_name1, file_name2):
        index1 = int(file_name1.split('.')[0])
        index2 = int(file_name2.split('.')[0])
        return index1 - index2 # 以文件名来作对比
    # 获取所有 txt 文件,并排好序
    for file_name in sorted(listdir(txt_frames_dir), key=cmp_to_key(compare_file_name)):
        txt_path = join(txt_frames_dir, file_name)
        os.system('cat ' + txt_path) # cat 出来
        sleep(speed)
复制代码

现在已经可以实现把坤坤打印出来了。


工具函数


虽然功能已经实现好了,但是如果要做出一个别人也能玩得嗨的产品还需要再打磨一下。

首先,可以添加 is_ready 函数来判断是否已经有生成好了的字符画。

from os import listdir
def is_ready():
    return len(listdir(txt_frames_dir)) != 0
复制代码


还可以添加 clear 函数来清楚缓存。

import glob
import os
def clear():
    files = glob.glob(join(txt_frames_dir, '*'))
    for f in files:
        os.remove(f)
复制代码


最后一步,做一个入口文件,添加一些参数来自定义打出字符视频:

#!/usr/local/bin/python3
import argparse
from procedure import prepare, display, is_ready, clear
# 获取参数
def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('command', type=str, default='run')
    parser.add_argument('--width', type=int, default=240)
    parser.add_argument('--height', type=int, default=100)
    parser.add_argument('--speed', type=float, default=0.02)
    return parser.parse_args()
if __name__ == '__main__':
    args = get_args()
    # 参数
    command = args.command
    width = args.width
    height = args.height
    speed = args.speed
    if command == 'clear':
        clear()
    if command == 'compile':
        prepare(width, height)
    if command == 'run':
        if not is_ready():
            print('运行 python3 main.py compile 来编译')
        else:
            display(speed) # 输出字符视频
复制代码


用户就可以有多种玩法了:

./main.py run --speed 0.02 # 控制速度,单位为 seconds,这里数值为默认值
./main.py run --width 240 --height 100 # 控制宽高,这里数值为默认值
复制代码


最后


上面所有完整的代码都可以在 Github - cxk-dance 这个仓库 里获取,各位观众老爷自行 clone 来玩吧。


在 M1 的 Mac 上有可能会出现 Pillow 安装不成功的问题,在 README.md 也给出了相应的解决办法。





相关文章
|
4月前
|
弹性计算 人工智能 运维
部署OpenClaw购买阿里云轻量应用服务器售罄?全方位抢购与替代方案指南!
阿里云轻量服务器OpenClaw特惠机型(2核4G/200M)因新用户专享、限量发售常“售罄”。本文揭秘每日10:00/15:00抢购技巧,推荐免抢的2核2G轻量(68元/年)及ECS经济型(99元/年)替代方案,助你快速部署AI助手!
587 4
|
安全 Linux 网络安全
在Linux中传输文件文件夹的10个scp命令
本文为转载,原文链接为:https://mp.weixin.qq.com/s/IPFNwPiWioMPAix51hrXzg
|
安全 程序员 编译器
Python有多少个版本?不同Python版本之间有什么区别?我应该选择哪一个?
Python有多少个版本?不同Python版本之间有什么区别?我应该选择哪一个?
5905 0
Python有多少个版本?不同Python版本之间有什么区别?我应该选择哪一个?
|
9月前
|
移动开发 小程序 前端开发
小程序开发平台有哪些?哪个好
小程序的开发方式丰富多元,开发团队可根据自身的技术背景、项目具体需求以及资源状况,灵活挑选最为适宜的开发路径。以下将详细介绍几种主流的小程序开发方式。
716 1
|
12月前
|
存储 前端开发 搜索推荐
typora最新版解决方法,typora免费下载
Typora是一款简洁高效的Markdown编辑器,支持实时预览、语法高亮、数学公式、图表绘制等功能,适用于写作、编程和技术文档编写。界面极简,功能全面,支持多平台使用。
2239 1
|
人工智能 vr&ar
TRELLIS:微软联合清华和中科大推出的高质量 3D 生成模型,支持局部控制和多种输出格式
TRELLIS 是由微软、清华大学和中国科学技术大学联合推出的高质量 3D 生成模型,能够根据文本或图像提示生成多样化的 3D 资产,支持多种输出格式和灵活编辑。
1577 3
TRELLIS:微软联合清华和中科大推出的高质量 3D 生成模型,支持局部控制和多种输出格式
|
Web App开发 监控 前端开发
React音频播放控制组件开发深度解析
本文介绍了构建React音频控制组件时遇到的关键问题及优化方案。主要包括: 1. **状态同步难题**:解决播放按钮与音频状态不同步的问题,通过双向绑定机制确保一致。 2. **跨浏览器兼容性**:处理Safari和Chrome预加载策略差异,确保`duration`属性正确获取。 3. **进度控制优化**:避免使用`setInterval`,采用`requestAnimationFrame`提升性能;优化拖拽交互,防止音频卡顿。 4. **音量控制进阶**:实现渐变音量调节和静音状态同步。
617 15
|
网络协议 Linux Shell
CentOS 7 下 GitLab安装部署教程
GitLab一个开源的git仓库管理平台,方便团队协作开发、管理。在GitLab上可以实现完整的CI(持续集成)、CD(持续发布)流程。而且还提供了免费使用的Plan,以及免费的可以独立部署的社区版本
4632 0
|
存储 安全 数据安全/隐私保护
安全升级!Python AES加密实战,为你的代码加上一层神秘保护罩
【8月更文挑战第2天】数据安全至关重要,AES加密作为对称加密的标准之一,因其高效性与灵活性被广泛采用。本文通过实战演示Python中AES的应用,使用pycryptodome库进行安装及加密操作。示例代码展示了生成随机密钥与初始化向量(IV)、对数据进行加密及解密的过程。注意事项包括密钥管理和IV的随机性,以及加密模式的选择。掌握AES加密能有效保护敏感数据,确保信息安全无虞。
641 6
|
安全 Shell Windows
记windows自定义bat脚本自启动
【8月更文挑战第27天】在Windows系统中,可让自定义bat脚本自启动的方法有两种:一是利用“启动”文件夹,通过创建bat脚本的快捷方式并将其放置于该文件夹;二是使用任务计划程序,创建一个启动时触发的任务来运行bat脚本。需确保脚本正确安全,避免对系统产生不良影响。
3421 0