利用Python程序生成字符画 让男大学生们洗脑的挖呀挖呀挖

news2025/1/8 4:13:19

源码地址

原教程在这里

演示效果:(有点虚)

利用Python程序生成字符画 让男大学生们洗脑的挖呀挖呀挖

使用教程(源码在文章最后)

  1. 打开pyhton编译器安装opencv和Pillow库
  2. 把要进行字符串化的视频命名为input.mp4(或者在代码里修改进行字符串化的视频从input.mp4改为你的视频名)
  3. 运行代码,此时会有进度提示
  4. 找自己这个pyhton文件的位置会有一个video文件夹生成
  5. 完了,记得帮我点个赞或者收藏一下😳😳😳

你可能需要安装opencv和Pillow。如果没有这两个库,通常情况下本脚本会自动帮你安装。如果自动安装失败,请在cmd分别运行。

pip3 install opencv-python-headlesspip3 install Pillow

在这里插入图片描述

在这里插入图片描述

源代码

import sys
import os
import time
import shutil
from multiprocessing import Process

try:
    from PIL import Image, ImageFont, ImageDraw
except ImportError:
    os.system('pip3 install Pillow -i https://mirrors.aliyun.com/pypi/simple/')
    from PIL import Image, ImageFont, ImageDraw

try:
    import cv2
    from cv2 import VideoWriter, VideoWriter_fourcc, imread, resize
except ImportError:
    os.system('pip3 install opencv-python-headless -i https://mirrors.aliyun.com/pypi/simple/')
    import cv2
    from cv2 import VideoWriter, VideoWriter_fourcc, imread, resize


# =========================
# coding:UTF-8
# 视频转字符画含音频version-2.1
# 参考1:https://blog.csdn.net/mp624183768/article/details/81161260
# 参考2:https://blog.csdn.net/qq_42820064/article/details/90958577
# 参考3:https://blog.csdn.net/zj360202/article/details/79026891
# =========================


def get_char(r, g, b, alpha=256):
    ascii_char = list("#RMNHQODBWGPZ*@$C&98?32I1>!:-;. ")
    # ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:oa+>!:+. ")
    if alpha == 0:
        return ''
    length = len(ascii_char)
    gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
    unit = (256.0 + 1) / len(ascii_char)
    return ascii_char[int(gray / unit)]


# 将视频转换为图片 并进行计数,返回总共生成了多少张图片!
def video_to_pic(vp):
    print('正在对视频进行逐帧切片,请稍候...')
    # vp = cv2.VideoCapture(video_path)
    number = 0
    if vp.isOpened():
        r, frame = vp.read()
        if not os.path.exists(sys.path[0] + '/cache_pic'):
            os.mkdir(sys.path[0] + '/cache_pic')
        os.chdir(sys.path[0] + '/cache_pic')
    else:
        r = False
    while r:
        number += 1
        cv2.imwrite(sys.path[0] + '/cache_pic/' + str(number) + '.jpg', frame)
        r, frame = vp.read()
    print('由视频一共生成了{}张图片!'.format(number))
    os.chdir(sys.path[0])
    # os.chdir("../../../Downloads")
    return number


def img_to_char(image_path, raw_width, raw_height, task):
    width = int(raw_width / 6)
    height = int(raw_height / 15)
    os.chdir(sys.path[0])
    im = Image.open(image_path).convert('RGB')  # 必须以RGB模式打开
    im = im.resize((width, height), Image.NEAREST)

    txt = ''
    color = []
    for i in range(height):
        for j in range(width):
            pixel = im.getpixel((j, i))
            color.append((pixel[0], pixel[1], pixel[2]))  # 将颜色加入进行索引
            if len(pixel) == 4:
                txt += get_char(pixel[0], pixel[1], pixel[2], pixel[3])
            else:
                txt += get_char(pixel[0], pixel[1], pixel[2])
        txt += '\n'
        color.append((255, 255, 255))

    im_txt = Image.new("RGB", (raw_width, raw_height), (255, 255, 255))
    dr = ImageDraw.Draw(im_txt)
    # font = ImageFont.truetype('consola.ttf', 10, encoding='unic') #改为这个字体会让图片比例改变
    font = ImageFont.load_default().font
    x, y = 0, 0
    font_w, font_h = font.getsize(txt[1])
    font_h *= 1.37  # 调整字体大小
    for i in range(len(txt)):
        if (txt[i] == '\n'):
            x += font_h
            y = -font_w
        dr.text((y, x), txt[i], fill=color[i])
        y += font_w
    os.chdir(sys.path[0])
    # os.chdir('cache_char')
    im_txt.save(sys.path[0] + '/cache_char/' + str(task) + '.jpg')
    os.chdir(sys.path[0])
    # os.chdir("../../../Downloads")
    return 0


# 使用多进程进行图片转字符画,number是cahce_pic中图片总数,start_number是该进程从第几副图开始做,end_number是该进程到第几副图结束。
class StarToCharMultiProcess(Process):
    def __init__(self, threadID, number, save_pic_path, start_number, end_number):
        super().__init__()
        self.threadID = threadID
        self.number = number
        self.save_pic_path = save_pic_path
        self.start_number = start_number
        self.end_number = end_number

    def run(self):
        print("开始进程:" + self.name)
        star_to_char2(self.number, self.save_pic_path, self.start_number, self.end_number)
        print(self.name + ":处理完成")
        print("退出进程:" + self.name)


def star_to_char(number, save_pic_path):
    if not os.path.exists('cache_char'):
        os.mkdir('cache_char')
    img_path_list = [save_pic_path + r'/{}.jpg'.format(i) for i in range(1, number + 1)]  # 生成目标图片文件的路径列表
    task = 0
    for image_path in img_path_list:
        img_width, img_height = Image.open(image_path).size  # 获取图片的分辨率
        task += 1
        img_to_char(image_path, img_width, img_height, task)
        print('{}/{} is finished.'.format(task, number))
    print('=======================')
    print('All images were finished!')
    print('=======================')
    return 0


def star_to_char2(number, save_pic_path, start_number, end_number):
    os.chdir(sys.path[0])
    if not os.path.exists('cache_char'):
        try:
            os.mkdir('cache_char')
        except:
            pass
    img_path_list = [save_pic_path + r'/{}.jpg'.format(i) for i in range(start_number, end_number + 1)]  # 生成目标图片文件的路径列表
    task = start_number - 1
    for image_path in img_path_list:
        img_width, img_height = Image.open(image_path).size  # 获取图片的分辨率
        task += 1
        img_to_char(image_path, img_width, img_height, task)
        # print('{}/{} is finished.'.format(task, number))
    # print('=======================')
    # print('Finished!')
    # print('=======================')
    return 0


def star_to_char_multi_process(number, save_pic_path, process_number):
    print("\n正在把图片转字符画,请稍候...")
    print("启动多进程处理:")
    processes = []
    for count in range(1, process_number + 1):
        if count == 1:
            start_number = 1
            end_number = start_number + number // process_number
        elif count == process_number:
            start_number = end_number + 1
            end_number = number
        else:
            start_number = end_number + 1
            end_number = start_number + number // process_number
        process = StarToCharMultiProcess(count, number, save_pic_path, start_number, end_number)
        process.start()
        processes.append(process)
        time.sleep(1)
    return processes


def process_bar(percent, start_str='', end_str='', total_length=0):
    # 进度条
    bar = ''.join("■ " * int(percent * total_length)) + ''
    bar = '\r' + start_str + bar.ljust(total_length) + ' {:0>4.1f}%|'.format(percent * 100) + end_str
    print(bar, end='', flush=True)


def jpg_to_video(char_image_path, FPS):
    print("\n开始合成视频")
    video_fourcc = VideoWriter_fourcc(*"MP42")  # 设置视频编码器,这里使用使用MP42编码器,可以生成更小的视频文件
    char_img_path_list = [char_image_path + r'/{}.jpg'.format(i) for i in range(1, number + 1)]  # 生成目标字符图片文件的路径列表
    char_img_test = Image.open(char_img_path_list[1]).size  # 获取图片的分辨率
    os.chdir(sys.path[0])
    if not os.path.exists('video'):
        os.mkdir('video')
    video_writter = VideoWriter('video/new_char_video.avi', video_fourcc, FPS, char_img_test)
    sum = len(char_img_path_list)
    count = 0
    for image_path in char_img_path_list:
        img = cv2.imread(image_path)
        video_writter.write(img)
        end_str = '100%'
        count = count + 1
        process_bar(count / sum, start_str='', end_str=end_str, total_length=15)

    video_writter.release()
    print('\n')
    print('=======================')
    print('The video is finished!')
    print('=======================')


def write_audio(video_path):
    # 加入音频
    cmd = 'ffmpeg -i ' + sys.path[
        0] + '/video/new_char_video.avi' + ' -i ' + video_path + ' -c copy -map 0 -map 1:1 -y -shortest ' + sys.path[
              0] + '/video/videoWithAudio.avi' + ' -y'
    os.system(cmd)
    # 压制成H.264 mp4格式
    cmd2 = 'ffmpeg -i ' + sys.path[0] + '/video/videoWithAudio.avi' + ' -c:v libx264 -strict -2 ' + sys.path[
        0] + '/video/finalOutput_VideoWithAudio.mp4' + ' -y'
    os.system(cmd2)


def delete(path):
    try:
        shutil.rmtree(path)
        print('已删除:' + path)
        return 0
    except:
        print('删除' + path + '失败,可能是权限不足或目录不存在')
        return -1


def input_process(default_video_path):
    video_path = default_video_path
    while not os.path.exists(video_path):
        if len(sys.argv) == 2:
            video_path = sys.argv[1]
        elif len(sys.argv) == 1 and not os.path.exists(video_path):
            video_path = input('请输入要处理的视频名称:')
            video_path = sys.path[0] + '/' + video_path
    return video_path


if __name__ == '__main__':
    # 各种参数
    video_path = sys.path[0] + '/input.mp4'  # 把input.mp4改成你的视频名字,注意前面的斜杠要保留
    save_pic_path = sys.path[0] + '/cache_pic'  # 别动
    save_charpic_path = sys.path[0] + '/cache_char'  # 别动
    processes_number = 8  # 使用多少个进程同时处理图片,通常不超过CPU线程数,可以自行设置
    video_path = input_process(video_path)

    # 处理
    vp = cv2.VideoCapture(video_path)
    number = video_to_pic(vp)
    FPS = vp.get(cv2.CAP_PROP_FPS)
    threads = star_to_char_multi_process(number, save_pic_path, processes_number)
    for thread in threads:
        thread.join()
    vp.release()
    jpg_to_video(save_charpic_path, FPS)
    delete(save_pic_path)
    delete(save_charpic_path)
    write_audio(video_path)  # 把原视频的音频复制到新视频中。需要安装ffmpeg,否则报错。没有ffmpeg请注释掉这行代码。


在这里插入图片描述
在这里插入图片描述

为什么报错?

在这里插入图片描述

你可能需要安装opencv和Pillow。如果没有这两个库,通常情况下本脚本会自动帮你安装。如果自动安装失败,请在cmd分别运行。

在这里插入图片描述

注意的事及其使用方法

你可能需要安装opencv和Pillow。如果没有这两个库,通常情况下本脚本会自动帮你安装。如果自动安装失败,请在cmd分别运行、。

pip3 install opencv-python-headlesspip3 install Pillow

支持常见的mp4、flv等格式。

需要在main函数中修改你的视频文件路径,默认视频文件名称为input.mp4,放在与本py文件相同的目录里。如果没有找到input.mp4,会自动询问你视频名称。

最简单的方法:将视频放置在py文件的文件夹下,并修改 video_path后的参数为你的视频名字即可运行。

此外还可以设置多进程处理图片,可自行修改进程数量。

if __name__ == '__main__':
   video_path = sys.path[0] + '/input.mp4'  # 把input.mp4改成你的视频名字,注意前面的斜杠要保留
   save_pic_path = sys.path[0] + '/cache_pic'  # 别动
   save_charpic_path = sys.path[0] + '/cache_char'  # 别动
   processes_number = 8  # 使用多少个进程同时处理图片,通常不超过CPU线程数,可以自行设置

为生成的视频添加原视频音轨并且压制为mp4需要预先安装好ffmpeg,如果没有安装ffmpeg,请注释掉或者删掉最后一行

write_audio(video_path)

最后附送一段舞蹈😍

利用Python程序生成字符画 跳舞

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/515356.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nginx: 配置https证书,wss证书

作用&#xff1a;SSL证书卸载 1、制作证书 openssl genrsa -des3 -out server.key 2048 openssl req -new -key server.key -out server.csr openssl rsa -in server.key -out server.key openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt …

windows 通过bat一键Android手机截图

首先资源需要5积分链接如下&#xff1a; https://download.csdn.net/download/weixin_38287114/87774870?spm1001.2014.3001.5501 使用范围&#xff1a; 有一台电脑是window系统&#xff0c;电脑安装配置了adb 有一台手机&#xff0c;打开了usb调试 你想截图的软件没有usb…

ArrayList 和 LinkedList 之间应该怎么选择?

Joshua Bloch&#xff1a;我写了 LinkedList&#xff0c;但我自己都不用&#xff01; 对&#xff0c;Joshua Bloch 就是 LinkedList 的作者&#xff01; 如果你真信了作者的话&#xff0c;那就真的大错特错了&#xff0c;LinkedList 虽然用的没有 ArrayList 多&#xff0c;但使…

高性能存储SIG月度动态:EROFS支持直接索引容器镜像tar包,io_uring将支持并优化NVMe直通

高性能存储 SIG&#xff08;Special Interest Group&#xff09;目标&#xff1a;存储领域的发展历程&#xff0c;本质上是存储介质与软件栈相互促进发展的过程。高性能存储 SIG 致力于存储栈性能挖掘&#xff0c;当前主要聚焦内核 io_uring 技术优化异步 IO 性能&#xff0c;使…

bugku——变量1

拿到题目后是一串PHP代码&#xff0c;给到提示是flag在变量中&#xff0c;接下来进行代码审计 error_reporting(0)&#xff1a;关闭错误报告 include “flag1.php”:包含flag1.php文件 highlight_file(_file_)&#xff1a;页面进行语法高亮显示 isset($_GET[‘args’])&#xf…

AI模型推理(4)—— 认识ServingRuntime

参考&#xff1a; Serving Runtimes - KServe Documentation Website 模型推理服务化&#xff1a;如何基于Triton开发自己的推理引擎&#xff1f; - 知乎 GitHub - openai/triton: Development repository for the Triton language and compiler 前言 ServingRuntime&#…

Qt quick基础3(基础动画,包含旋转动画、串行并行动画及其嵌套)

Qt quick基础3&#xff08;基础动画&#xff09; 目录 Qt quick基础3&#xff08;基础动画&#xff09;前言前期准备工作Animation on property 元素加载后自动运行动画Behavior on property 当元素值改变后运行动画Standalone Animation 单独动画旋转动画分组动画串行动画并行…

干货 | 科研决策怎么做?四个步骤一招解决!

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ 又是给大家带来满满干货的一天&#xff0c;今天要给大家介绍的是狐少侠对于科学决策的四个步骤的详细解读&#xff01; 最近&#xff0c;有读者问了我几个关于决策的问题&#xff1a;要不要…

ubuntu22.04 编译安装 Kate 编辑器

ubuntu22.04 编译安装 Kate 编辑器 文章目录 ubuntu22.04 编译安装 Kate 编辑器0x0 目的0x1 在 Ubuntu 22.04 编译安装 Kate0x11 Download dependencies0x12 Build kate and kwrite0x13 Setup paths for binary and shared libraries0x14 Misc trials 0x2 配置 Kate渲染空白字符…

R语言 | 数据分析与处理

目录 一、随机抽样 1.1 将随机抽样应用于扑克牌 1.2 种子值 ​1.3 模拟骰子 1.4 比重的设置 二、再谈向量数据的抽取——以islands为实例 三、数据框数据的抽取——重复值的处理 ​3.1 重复值的搜索 3.2 which()函数 3.3 抽取数据是去除重复值 四、数据框数据的抽取…

Linux命令·scp

scp是secure copy的简写&#xff0c;用于在Linux下进行远程拷贝文件的命令&#xff0c;和它类似的命令有cp&#xff0c;不过cp只是在本机进行拷贝不能跨服务器&#xff0c;而且scp传输是加密的。可能会稍微影响一下速度。当你服务器硬盘变为只读 read only system时&#xff0c…

【深度学习】第一门课 神经网络和深度学习 Week 2 神经网络基础

2.1 二元分类 前言 第二周的主题是学习神经网络的基础知识。 实现神经网络需要用到一些重要的技术和技巧&#xff0c;比如怎样处理包含大量样本的训练集。 在神经网络的计算中&#xff0c;还会有前向暂停、前向传播、反向暂停和反向传播等步骤&#xff0c;本周会对它们进行…

面试一个6年经验测试员:一年经验硬生生用了六年....

在众多面试中&#xff0c;对于那个工作了6年的面试者&#xff0c;我印象很深刻&#xff0c;因为最开始拿到简历的时候&#xff0c;我一摸:"这简历&#xff0c;好厚啊&#xff01;"再一看&#xff0c;工作6年。 于是我去找了我的领导&#xff0c;我说:“这人我应该没…

C++入门基础知识总结(超详细)

目录 C入门基础知识之什么是C? C入门基础知识看看C的历史版本&#xff1a; C入门基础知识关键字 C入门基础之C的命名空间 C入门基础命名空间的使用 C入门基础知识的输入和输出 C入门基础知识-缺省参数 C入门基础-C函数重载 extern “C” C入门基础知识-引用 C入门基…

图像处理:图像增广算法

目录 前言 图像增广算法 a.图像旋转 b.图像亮度调整 c.图像裁剪及拼接 实验分析 本章小结 前言 图像增广算法在计算机视觉领域扮演着至关重要的角色。随着深度学习的兴起&#xff0c;大规模数据集的需求变得更加迫切&#xff0c;而图像增广算法可以通过对原始图像进行一…

手把手教你安装PaddleDetection(最新CUDA11.7版本)

前言 本文记录一下在linux系安装PaddleDetection的过程&#xff0c;使用Conda的方式来安装&#xff1b; &#xff08;尝试过docker的方式&#xff0c;无法获取镜像&#xff1b;尝试过pip的方式&#xff0c;提升找不到库&#xff1b;最终使用Conda成功安装了。&#xff09; 目…

什么是中国版软件能力成熟度之CSMM

当前&#xff0c;中国软件产业蓬勃发展&#xff0c;产业增速迅猛&#xff0c;发展韧性和潜力进一步凸显。由于我国长期缺乏相关的自主标准&#xff0c;20多年来国外标准在我国软件评估领域占据主导地位&#xff0c;不仅阻碍了我国自主产业发展&#xff0c;甚至通过评估等手段可…

【STM32CubeMX项目】小时钟V1.0

前言 基于STM32CubeMxSTM32F103C6T6编写时钟功能。现在以及能实现时钟的简单功能&#xff0c;做文记录下。还有很多可以改进的地方&#xff0c;也算留下的基础版本下来备份吧。我愿称之为V1.0版本。可供学习参考。 实物 引脚接线&#xff1a; OLED STM32F103 SCL --> PB8 SD…

使用JS手动实现SementicUI的分页,解决页数过多的问题.

自己使用SemanticUI官网的分页组件&#xff0c; 但是有很多细节问题并没有解决方案&#xff0c;如果只是需要而分页&#xff0c;将页数渲染在分页组件上的话&#xff0c;那倒很简单&#xff0c;但是页面有很多的话&#xff0c;假如100页&#xff0c;那么整个tbody会随着tfoot…

C# PDF附件生成

最近项目上需要生成行业某证件&#xff0c;查阅了一下&#xff0c;大体有两个思路可以实现 1.图片格式 2.PDF格式 使用图片格式&#xff0c;GDI绘图的形式&#xff0c;GDI绘图相关库资料比较多&#xff0c;难度也还好&#xff0c;问题是生成的证不是很好看&#xff0c;看上去…