Python3视频转字符动画的实例代码
Python3视频转字符动画,具体代码如下所示:
#-*-coding:utf-8-*-
importjson
importos
importsubprocess
frompathlibimportPath
fromcv2importcv2
importnumpyasnp
fromtimeimporttime
importwebbrowser
play_chars_js='''
leti=0;
window.setInterval(function(){
letimg=frames[i++];
lethtml=""
for(letlineofimg){
for(letcharofline){
let[[r,g,b],ch]=char;
html+=''+ch+''
//html+=''+ch+''
}
html+="
"
}
document.getElementsByClassName("video-panel")[0].innerHTML=html
},1000/fps);
document.getElementsByTagName("audio")[0].play();
'''
classVideoToHtml:
#像素形状,因为颜色已经用rgb控制了,这里的pixels其实可以随意排
pixels="$#@&%ZYXWVUTSRQPONMLKJIHGFEDCBA098765432?][}{/)(>=self.width:
returnFalse
else:
self.resize_width=width
self.resize_height=int(self.height*(width/self.width))
returnTrue
defset_height(self,height):
"""只能缩小,而且始终保持长宽比"""
ifheight>=self.height:
returnFalse
else:
self.resize_height=height
self.resize_width=int(self.width*(height/self.height))
returnTrue
defresize(self,img):
"""
将img转换成需要的大小
原则:只缩小,不放大。
"""
#没指定就不需resize了
ifnotself.resize_widthornotself.resize_height:
returnimg
else:
size=(self.resize_width,self.resize_height)
returncv2.resize(img,size,interpolation=cv2.INTER_CUBIC)
defget_img_by_pos(self,pos):
"""获取到指定位置的帧"""
#把指针移动到指定帧的位置
self.cap.set(cv2.CAP_PROP_POS_FRAMES,pos)
#cap.read()返回值介绍:
#ret布尔值,表示是否读取到图像
#frame为图像矩阵,类型为numpy.ndarray.
ret,frame=self.cap.read()
returnret,frame
defget_frame_pos(self):
"""生成需要获取的帧的位置,使用了惰性求值"""
step=self.fps/self.fps_for_html
#如果未指定
ifnotself.time_interval:
self.frames_count=int(self.frames_count_all/step)#更新count
return(int(step*i)foriinrange(self.frames_count))
#如果指定了
start,end=self.time_interval
pos_start=int(self.fps*start)
pos_end=int(self.fps*end)
self.frames_count=int((pos_end-pos_start)/step)#更新count
return(pos_start+int(step*i)foriinrange(self.frames_count))
defget_imgs(self):
assertself.cap.isOpened()
foriinself.get_frame_pos():
ret,frame=self.get_img_by_pos(i)
ifnotret:
print("读取失败,跳出循环")
break
yieldself.resize(frame)#惰性求值
#结束时要释放空间
self.cap.release()
defget_char(self,gray):
percent=gray/255#转换到0-1之间
index=int(percent*(len(self.pixels)-1))#拿到index
returnself.pixels[index]
defget_json_pic(self,img):
"""测试阶段,不实用"""
json_pic=[]
#宽高刚好和size相反,要注意。(这是numpy的特性。。)
height,width,channel=img.shape
#转换成灰度图,用来选择合适的字符
img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
foryinrange(height):
line=[]
forxinrange(width):
r,g,b=img[y][x]
gray=img_gray[y][x]
char=self.get_char(gray)
line.append([[int(r),int(g),int(b)],char])
json_pic.append(line)
returnjson.dumps(json_pic)
defwrite_html_with_json(self,file_name):
"""测试阶段,不实用"""
mp3_path=self.video2mp3()
time_start=time()
withopen(file_name,'w')ashtml:
#要记得设置monospace等宽字体,不然没法玩
html.write(''
''
''
'