python--视频转换动画

这段代码是一个 Python 程序,它使用了一些图像处理和视频处理的技术来将视频转换为字符画并进行播放。下面是对代码的详细解释:

  1. 导入必要的模块和库:
import numpy as np
import subprocess
import time
import cv2
  • numpy 是一个用于科学计算的 Python 库,它提供了高效的多维数组和数值计算功能。
  • subprocess 是一个 Python 模块,用于启动和与外部命令行程序进行交互。
  • time 是 Python 的一个内置模块,用于处理时间和定时操作。
  • cv2 是 OpenCV 的 Python 接口库,用于计算机视觉和图像处理。
  1. 定义字符画的像素:
pixels = " .,-'`:!1+*abcdefghijklmnopqrstuvwxyz<>()\/{}[]?1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ%&@#$"

这行代码定义了一个字符串 pixels,其中包含了用于生成字符画的像素。每个字符都对应着一个像素点,其中空格代表白色像素,其他字符代表不同的颜色像素。

  1. 按帧读取视频:
def video2imgs(video_name, size):
    """
    :param video_name: 字符串, 视频文件的路径
    :param size: 二元组,(宽, 高),用于指定生成的字符画的尺寸
    :return: 一个 img 对象的列表,img 对象实际上就是 numpy.ndarray 数组
    """
    img_list = []

    # 从指定文件创建一个 VideoCapture 对象
    cap = cv2.VideoCapture(video_name)

    # 如果 cap 对象已经初始化完成了,就返回 true,换句话说这是一个 while true 循环
    while cap.isOpened():
        # cap.read() 返回值介绍:
        # ret 表示是否读取到图像
        # frame 为图像矩阵,类型为 numpy.ndarry.
        ret, frame = cap.read()
        if ret:
            # 转换成灰度图
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

            # resize 图片,保证图片转换成字符画后,能完整地在命令行中显示
            img = cv2.resize(gray, size, interpolation=cv2.INTER_AREA)

            # 分帧保存转换结果
            img_list.append(img)
        else:
            break

    # 结束时要释放空间
    cap.release()

    return img_list

这段代码定义了一个函数 video2imgs,用于将视频转换为一系列图像帧。它接受两个参数:video_name 表示视频文件的路径,size 表示生成的字符画的尺寸。函数返回一个包含所有图像帧的列表。

在函数内部,首先创建了一个 cv2.VideoCapture 对象来读取视频文件。然后,使用一个循环来逐帧读取视频,并将每一帧转换为灰度图像。接下来,使用 cv2.resize 函数将图像调整为指定的尺寸,以适应字符画的显示。最后,将调整后的图像添加到列表中,并在循环结束后释放 cv2.VideoCapture 对象。

  1. 图像转化为字符画:
def img2chars(img):
    """
    :param img: numpy.ndarray, 图像矩阵
    :return: 字符串的列表:图像对应的字符画,其每一行对应图像的一行像素
    """
    res = []

    # 灰度是用 8 位表示的,最大值为 255。
    # 这里将灰度转换到 0-1 之间
    # 使用 numpy 的逐元素除法加速,这里 numpy 会直接对 img 中的所有元素都除以 255
    percents = img / 255

    # 将灰度值进一步转换到 0 到 (len(pixels) - 1) 之间,这样就和 pixels 里的字符对应起来了
    # 同样使用 numpy 的逐元素算法,然后使用 astype 将元素全部转换成 int64 值
    indexes = (percents * (len(pixels) - 1)).astype(np.int64)

    # 要注意这里的顺序和 之前的 size 刚好相反(numpy 的 shape 返回 (行数、列数))
    height, width = img.shape
    for row in range(height):
        line = ""
        for col in range(width):
            index = indexes[row][col]
            # 添加字符像素(最后面加一个空格,是因为命令行有行距却没几乎有字符间距,用空格当间距)
            line += pixels[index] + " "
        res.append(line)

    return res

这段代码定义了一个函数 img2chars,用于将图像转换为字符画。它接受一个 numpy.ndarray 类型的图像作为输入,并返回一个字符串列表,每个字符串表示图像的一行像素。

在函数内部,首先使用 numpy 的逐元素除法将图像的灰度值转换到 0 到 1 之间。然后,将灰度值进一步转换到 0 到 len(pixels) - 1 之间,以便与 pixels 中的字符对应起来。接下来,使用 numpy 的逐元素算法将灰度值转换为对应的字符索引,并将索引转换为字符串。最后,遍历图像的每一行,将每行的字符像素添加到结果列表中,并在每行的末尾添加一个空格作为字符间距。

  1. 转换所有的帧:
def imgs2chars(imgs):
    video_chars = []
    for img in imgs:
        video_chars.append(img2chars(img))

    return video_chars

这段代码定义了一个函数 imgs2chars,用于将一系列图像帧转换为字符画。它接受一个包含图像帧的列表作为输入,并返回一个包含字符画的列表。

在函数内部,使用一个循环遍历输入列表中的每个图像帧,并使用 img2chars 函数将每个图像帧转换为字符画。最后,将所有的字符画添加到结果列表中,并返回该列表。

  1. 播放字符视频:
def play_video(video_chars):
    """
    播放字符视频
    :param video_chars: 字符画的列表,每个元素为一帧
    :return: None
    """
    # 获取字符画的尺寸
    width, height = len(video_chars[0][0]), len(video_chars[0])

    for pic_i in range(len(video_chars)):
        # 显示 pic_i,即第i帧字符画
        for line_i in range(height):
            # 将 pic_i 的第 i 行写入第 i 列。
            print(video_chars[pic_i][line_i])
        time.sleep(1 / 24) # 粗略地控制播放速度。

        # 调用 shell 命令清屏
        # subprocess.run("clear", shell=True) # linux 版
        subprocess.run("cls", shell=True) # cmd ,windows 版

这段代码定义了一个函数 play_video,用于播放字符视频。它接受一个字符画列表作为输入,并按照指定的速度逐帧显示字符画。

在函数内部,首先获取字符画的尺寸,以便在播放时正确对齐。然后,使用一个循环遍历字符画列表中的每一帧。对于每一帧,使用另一个循环遍历每一行,并将该行的字符打印到控制台。最后,使用 time.sleep 函数暂停一段时间,以便观看视频。在每次循环结束后,调用 subprocess.run 函数来执行系统命令 clearcls,以清除控制台中的内容,以便显示下一帧。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

测试界的酸菜鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值