视频转字符视频

# -*- coding: utf-8 -*-
import os
import time

import cv2
import numpy
from PIL import Image, ImageDraw, ImageFont

ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")  # 所用字符列表


# 将256灰度映射到70个字符上
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 frame2char(frame):
    im = Image.fromarray(frame)
    origin_img_width = im.width
    origin_img_height = im.height
    new_img_width = int(im.width / 6)
    new_img_height = int(im.height / 15)
    im_txt = Image.new("RGB", (origin_img_width, origin_img_height), (255, 255, 255))
    im = im.resize((new_img_width, new_img_height), Image.NEAREST)
    txt = ""
    colors = []
    for i in range(new_img_height):
        for j in range(new_img_width):
            pixel = im.getpixel((j, i))
            colors.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'
        colors.append((255, 255, 255))
    dr = ImageDraw.Draw(im_txt)
    font = ImageFont.load_default().font
    x = y = 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], colors[i])
        y += font_w
    return im_txt


def get_image_size(video_path):
    frame_count, frame_width, frame_height = 0, 0, 0
    vc = cv2.VideoCapture(video_path)
    ret = vc.isOpened()
    while ret:
        ret, frame = vc.read()
        if ret:
            frame_count = int(vc.get(cv2.CAP_PROP_FRAME_COUNT))
            frame_height = vc.get(cv2.CAP_PROP_FRAME_HEIGHT)
            frame_width = vc.get(cv2.CAP_PROP_FRAME_WIDTH)
            break
    vc.release()
    time.sleep(1)
    return frame_count, frame_width, frame_height


def video2char_video(video_path, char_video_dir):
    frame_count, frame_width, frame_height = get_image_size(video_path)
    fourcc = cv2.VideoWriter_fourcc('D', 'I', 'V', 'X')
    video_writer = cv2.VideoWriter(f"{char_video_dir}/output.mp4", fourcc, 30.0,
                                   (int(frame_width), int(frame_height)))
    vc = cv2.VideoCapture(video_path)
    c = 0
    ret = vc.isOpened()
    while ret:
        c = c + 1
        ret, frame = vc.read()
        if ret:
            im_txt = frame2char(frame)
            img = cv2.cvtColor(numpy.array(im_txt), cv2.COLOR_RGB2BGR)
            video_writer.write(img)
            schedule = round(c / float(frame_count), 1) if frame_count != 0 else 1.0
            print(schedule)
        else:
            break
    # 视频释放
    vc.release()
    video_writer.release()


def main():
    video_path = '/home/navy/Desktop/1.mp4'
    video_dir = os.path.dirname(os.path.abspath(video_path))
    output_dir = f"{video_dir}/output"
    os.makedirs(output_dir, exist_ok=True)
    video2char_video(video_path, output_dir)


if __name__ == "__main__":
    main()

  

posted @ 2023-07-22 15:04  NAVYSUMMER  阅读(19)  评论(0)    收藏  举报
交流群 编程书籍