• 用python将视频转换为字符画视频


    import cv2 
    from PIL import Image,ImageFont,ImageDraw
    import os
    from cv2 import VideoWriter, VideoWriter_fourcc, imread, resize
    #=========================
    #coding:UTF-8
    # 视频转字符画含音频version-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):
        #vp = cv2.VideoCapture(video_path)
        number = 0
        if vp.isOpened():
            r,frame = vp.read()
            if not os.path.exists('cache_pic'):
                os.mkdir('cache_pic')
            os.chdir('cache_pic')
        else:
            r = False
        while r:
            number += 1
            cv2.imwrite(str(number)+'.jpg',frame)
            r,frame = vp.read()
        print('
    由视频一共生成了{}张图片!'.format(number))
        os.chdir("..")
        return number
    
    
    def img_to_char(image_path,raw_width,raw_height,task):
        width = int(raw_width/ 6)
        height = int(raw_height / 15)
        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 += '
    '
            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]=='
    '):
                x += font_h
                y = -font_w
            dr.text((y,x),txt[i] ,fill = color[i])
            y+=font_w
        os.chdir('cache_char')
        im_txt.save(str(task)+'.jpg')
        os.chdir("..")
        return 0
    
    
    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 image was finished!')
        print('=======================')
        return 0
    
    def process_bar(percent, start_str='', end_str='', total_length=0):
        #进度条
        bar = ''.join("" * int(percent * total_length)) + ''
        bar = '
    ' + 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):
        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   #获取图片的分辨率
        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('
    ')
        print('=======================')
        print('The video is finished!')
        print('=======================')
    
    if __name__ == '__main__':
        
        video_path = 'Produce_BiliBili.mp4'
        save_pic_path = 'cache_pic'
        save_charpic_path = 'cache_char'
    
        vp = cv2.VideoCapture(video_path)
        number = video_to_pic(vp)
        FPS = vp.get(cv2.CAP_PROP_FPS)
        star_to_char(number , save_pic_path)
        vp.release()
        jpg_to_video(save_charpic_path,FPS)

    视频源文件为

    video_path

    分割图片的存放地址为

    save_pic_path

    转化后的图片存放地址为

    save_charpic_path

     

     生成视频样例地址

    https://www.bilibili.com/video/BV1BN411R7Hc/

    感谢大佬hongcyu

    github地址:https://github.com/hongcyu/char_painting

    参考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

     
  • 相关阅读:
    GeoHash核心原理解析
    线程安全与可重入函数
    malloc和free的实现
    数字金字塔最大路径和——递归
    TCP连接建立与断开
    Gray Code
    C压缩字符串中的空格
    C++链接与装载
    epoll测试实例
    C++之手写strlen函数
  • 原文地址:https://www.cnblogs.com/ljy1227476113/p/14402850.html
Copyright © 2020-2023  润新知