字符画转视频[Termux,Python]
#正文不能为空
import os,sys
import numpy as np
from tqdm import tqdm
from PIL import Image,ImageDraw,ImageFont
from multiprocessing import Process,Queue,Manager
exec('import CV2 as cv'.lower())
'''
这么写是因为B站专栏有BUG,字符串'cv'加一个数字,
会把其中的cv强制转换为大写的CV !!!
比如 :
import CV2
'''
########################################
#最终比例
P2 = 10
#图片比例缩放(0.05-0.2),原视频单帧图像尺寸越大,值越小;反之,值越大
P1 = 0.05
#是否二值化
TH = True
#二值化阈值,大于阈值设为白色,其他黑色
THRESH = 125
#处理图片用到的CPU个数
IMG2STR_CPU_COUNT = 4
########################################
img_str = Manager().dict()
cap_list = Queue(100)
END = Queue(1)
FPS = Queue(2)
pix =''' .'`^",:;Il!i><~+_-?][}{1)(|\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@'''
pixgray2str= lambda p: pix[(255 - p) * 68 //255]
def cap_while(cap_list,mv_path,END,FPS) :
cap = cv.VideoCapture(mv_path)
if not FPS.full() :
FPS.put(cap.get(cv.CAP_PROP_FPS))
FPS.put(int(cap.get(cv.CAP_PROP_FRAME_COUNT)))
b = 0
while True :
a = cap.read()
if a[0] == True:
cap_list.put((b,a[1]))
b += 1
else :
for _ in range(IMG2STR_CPU_COUNT) :
cap_list.put(False)
END.put(b)
cap.release()
break
def img2str(cap_list,img_str) :
while True :
if len(img_str) >= 500 :
continue
A = cap_list.get()
if A :
img = A[1]
gray_img = cv.cvtColor(img,cv.COLOR_RGB2GRAY)
if TH :
_,gray_img = cv.threshold(gray_img,THRESH,255,cv.THRESH_BINARY)
Y,X = gray_img.shape
s_img = cv.resize(gray_img,(int(X*P1),int(Y*P1)),interpolation=cv.INTER_AREA)
y,x = s_img.shape
txt = ''
for i in s_img :
for p in i :
txt += pixgray2str(p)*2
txt += '\n'
font = ImageFont.load_default()
bg_color = 'black'
#bg_color = 'white'
im_out = Image.new('L',(x*P2,y*P2), bg_color)
draw = ImageDraw.Draw(im_out)
draw.text((0,0),txt,fill=(255),font=font)
img_new_str = np.asarray(im_out)
img_str[A[0]] = img_new_str
else :
break
def videowriter() :
os.system('clear')
fps = FPS.get()
frames = FPS.get()
pbar = tqdm(total=frames)
while True :
if 0 in img_str :
WH = img_str[0].shape
break
width_height = (WH[1],WH[0])
fourcc = cv.VideoWriter_fourcc(*'mp4v')
video = cv.VideoWriter(sys.path[0]+'/out.mp4',fourcc,fps,width_height,isColor=False)
K = 0
end = None
while True :
if END.full() :
end = END.get()
if K == end :
video.release()
print('文件保存在 :',sys.path[0]+'/out.mp4')
break
if K in img_str :
video.write(img_str[K])
del img_str[K]
K+=1
pbar.update(1)
if __name__ == '__main__' :
mv_path = input('要处理的视频 :')
#获取每一帧
P=Process(target=cap_while,daemon=True,args=(cap_list,mv_path,END,FPS))
P.start()
#处理每一帧
for _ in range(IMG2STR_CPU_COUNT) :
Process(target=img2str,daemon=True,args=(cap_list,img_str)).start()
#合成
videowriter()