抖音上看到那种把舞蹈变成字符型的小视频,如下图那种。就一直想弄一个。参考了网上写的好多代码,自己整理了一个。

python视频压缩编码 python视频编码传输_ide

大概思路:

  1. 先将原视频分割为一张一张的图片
  2. 再将这些图片转换为字符型的
  3. 又将这些字符型的图片串成视频即可

废话不多说,完整代码如下,有注释说明,只需更改一下视频路径及其存储路径即可。

# -*- coding: utf-8 -*-
"""
Created on Sun Aug 11 20:55:29 2019

@author: Administrator
"""

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

WIDTH = 80  #定义输出画面的宽度
HEIGHT = 45  #定义
ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")  #所用字符列表

# 将256灰度映射到70个字符上
def get_char(r, g, b, alpha=256):  # alpha透明度
    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 PictureToChar(sourcePath,storagePath):
    print("开始将图片转为字符型:")
    # 循环最多读取1100张图片,自己可更改
    for icount in range(1, 1100):
        IMG = sourcePath+str(icount)+'.jpg' #文件路径
        if os.path.exists(IMG):
            im = Image.open(IMG)
            #视频分割后图片的长与宽,与合成视频时要相统一,保存下来,合成字符视频时用到
            sourceImage=im
            WIDTH = int(im.width/6) #高度比例为原图的1/6较好,由于字体宽度
            HEIGHT = int(im.height/15)  #高度比例为原图的1/15较好,由于字体高度
            im_txt = Image.new("RGB",(im.width,im.height),(255,255,255))
            im = im.resize((WIDTH,HEIGHT),Image.NEAREST)
            txt = ""
            colors = []
            for i in range(HEIGHT):
                for j in range(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 #调整后更佳
            #ImageDraw为每个ascii码进行上色
            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
            #输出
            name = str(icount) + '.jpg'
            print(name)
            im_txt.save(storagePath + str(icount) + '.jpg')
    return sourceImage

def charToVideo(storagePath,sourceImage): 
    # 设置视频编码器,这里使用使用MJPG编码器
    #fourcc = cv2.VideoWriter_fourcc(*'MJPG')
    
    #这里是mp4格式
    fourcc = cv2.VideoWriter_fourcc('D', 'I', 'V', 'X')#不同视频编码对应不同视频格式(例:'I','4','2','0' 对应avi格式)
 
    print("开始将字符型图片变为视频:")
    #输出视频参数设置,包含视频文件名、编码器、帧率、视频宽高(此处参数需和字符图片大小一致)
    videoWriter = cv2.VideoWriter(storagePath+'test.mp4', fourcc, 30.0, (sourceImage.width,sourceImage.height))
     
    #循环最多读取1100张图片,自己可更改
    for i in range(1, 1100):
        filename = storagePath +str(i)+'.jpg'
        # 判断图片是否存在
        if os.path.exists(filename):
            img = cv2.imread(filename=filename)
            # 在一个给定的时间内(单位ms)等待用户按键触发,100ms
            cv2.waitKey(100)
            # 将图片写入视频中
            videoWriter.write(img)
            print(str(i) + '.jpg' + ' done!')
    # 视频释放
    videoWriter.release()
    print("字符视频已成功生成!!!")
    
def VideoToPicture(path):
    # 在当前目录下新建文件夹
    folder_path = "imgbear/"
    os.makedirs(folder_path)
    # 进行视频的载入
    vc = cv2.VideoCapture(path)
    print("开始将原视频分割为图片:")
    c = 0
    # 判断载入的视频是否可以打开
    ret = vc.isOpened()
    # 循环读取视频帧
    while ret:
        c = c + 1
        # 进行单张图片的读取,ret的值为True或者Flase,frame表示读入的图片
        ret, frame = vc.read()
        if ret:
            # 存储为图像
            cv2.imwrite(folder_path+str(c) + '.jpg', frame)
            # 输出图像名称
            print(folder_path+str(c) + '.jpg')
            # 在一个给定的时间内(单位ms)等待用户按键触发,1ms
            cv2.waitKey(1)
        else:
            break
    # 视频释放
    vc.release()
    return folder_path
    
if __name__=='__main__':  
    
    #视频所在路径
    path='C://Users//Administrator//Desktop//aa.mp4'
    #存储路径,路径上的文件夹必须已经存在
    storagePath='C://Users//Administrator//Desktop//1//'
    sourcePath = VideoToPicture(path)
    sourceImage = PictureToChar(sourcePath,storagePath) 
    charToVideo(storagePath,sourceImage)

最后结果如下:

python视频压缩编码 python视频编码传输_python实现视频转字符_02