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('' '' ' ' '