网络知识 娱乐 如何用python实现视频转换为字符画

如何用python实现视频转换为字符画

UI设计

  • 浏览文件夹及输入视频地址框
  • 浏览文件夹及保存位置输入框
  • 颜色模式选择单选按钮
  • 视频缩放比例滑动刻度条
  • 程序执行结果输出滚动文本框
如何用python实现视频转换为字符画

tkinter

  • 设置窗口图标,将图片转换为base64编码形式以变量存放,代码运行时解码并转换为图片,图标设置完成之后删除图片。背景图片也是这样设置,base64编码过长就不放出来了

img=b'AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAlJSX/KSkp/y0tLf8wMDD/NjY2/0RERP+Dg4P/Pz8//x4eHv8hISH/IiIi/x0dHf8rKyv/Ly8v/4SEhP+jo6P/HBwc/yEhIf8mJib/KCgo/yEhIf9gYWH/PT4+/x4eHv8gICD/RERE/0xMTP8rKyv/ICAg/zExMf+QkJD/qKio/xoaGv8cHBz/HBwc/x4eHv8gICD/LS0t/x8fH/8fHx//LS0t/3l5ef9qamr/SkpK/yQkJP8oKSj/kZGQ/6ysrP8bGxv/HBwc/x0dHf8cHBz/Hx8f/yAgIP8hISH/NTY2/4OFhf+Xl5f/ampq/2JiYv8zNDL/Jycn/5OTk/+wsLD/Gxsb/xwcHP8dHR3/HR0d/x4eHv8hISH/RUVF/6Ghof/BwcH/tLS0/21ubP9FRkX/TU1N/yoqKv+VlZX/s7Oz/xwcHP8dHR3/HR0d/x0dHf8fHx//Pj4+/66urv/CwsL/ycnJ/7Gxsf89PT3/Nzc3/1tbW/89PT3/eXl5/7e3t/8cHBz/HR0d/x8fH/8fHx//JiYm/4qKiv/MzMz/w8PD/8rKyv+mpqb/QEBA/zs7O/9hYWH/VlZW/1tbW/+5ubn/HBwc/x0dHf8eHh7/ICAg/y0uLv/FxcX/1dXV/9XV1f/W1tb/1NTU/7Ozs/+Kior/bGxs/2JiYv9OTk3/t7e3/xwcHP8cHBz/HR0d/x8fH/8jJCT/ampp/8rKyv+Xl5b/i4yK/87Ozv/Dw8P/dnZ2/2hoaP9qamr/Q0ND/7e3t/8dHR3/Hh4e/x4eHv8fHx//KSkp/yoqKv9aWlr/dnZ2/4WFhf+np6f/iYmJ/y0tLf9LS0v/Y2Nj/1JSUv+/v7//MzQ0/zExMf8vLy//MzMz/6SkpP86Ojr/Jycn/3Nzc/+3t7b/r6+v/8zMzP9FRUX/MDAw/ysrK/9dXV3/v7+//0hJSf9FRUX/QkND/21ubv9nZ2f/RERE/yIiIv8nJyf/NDQ0/2tra/+en5//Ly8v/yMjI/8qKir/lJSU/729vf9ERUX/QENC/z4/P/9fYGD/V1dX/2lpaf8kJCT/Hx8f/yMjI/8pKSn/LCws/yIiIv8lJSX/Wlpa/66urv+6urr/MzMz/zExMf8uLi7/RkZG/15eXv8yMjL/KSkp/yoqKv8uLi7/KSkp/ycnJ/88Pj3/MjIy/2hoaP+mpqb/sLCw/yEhIf8gICD/Hx8f/x4eHv8dHR3/NjY2/yYmJv8cHBz/Hx8f/ycnJ/8mJib/aWpp/z4+Pv9tbW3/np6e/6Wlpf8vLy//MzQ0/y8vL/80NTX/MDAw/zU1Nf8gICD/Ghoa/xoaGv8aGhr/Kysr/0dHR/9BQUH/a2tr/5WUlf+bm5v/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='n#设置窗口图标ntmp = open("tmp.ico","wb+")ntmp.write(base64.b64decode(img))ntmp.close()nroot.iconbitmap("tmp.ico")nos.remove("tmp.ico")

  • 视频输入与保存位置,分别包含一个标签、一个文本输入框与一个按钮,通过place绝对定位将控件放到指定位置。

#选择输入视频:ntip1=Label(root, text='请选择输入视频(必填!): ',font = ('楷体',25),bg='#CCCEC4',bd=0)ntip1.place(relx=0.1,rely=0.10,anchor=W)n#视频地址输入框ninput_vedio_address= Entry(root,bg='#C4C7C5')ninput_vedio_address.place(width=420,height=38,relx=0.1,rely=0.159,anchor=W)nn#选择保存地址:ntip2=Label(root, text='请选择保存位置(必填!): ',font = ('楷体',25),bg='#CCCEC4',bd=0)ntip2.place(relx=0.1,rely=0.24,anchor=W)n#保存地址输入框ninput_save_address= Entry(root,bg='#C4C7C5')ninput_save_address.place(width=420,height=38,relx=0.1,rely=0.30,anchor=W)nn# “浏览文件夹”按钮nbrowse_folder_button = Button(root, text='浏览',font = ('楷体',15),bg="#C4C7C5",command=lambda :thread_it(browse_folder1))nbrowse_folder_button.place(relx=0.73,rely=0.159,anchor="w")nn# “浏览文件夹”按钮nbrowse_folder_button = Button(root, text='浏览',font = ('楷体',15),bg='#C4C7C5',command=lambda :thread_it(browse_folder2))nbrowse_folder_button.place(relx=0.73,rely=0.30,anchor="w")

  • 选择颜色模式为radiobutton单选按钮,选择缩放比例为一个滑动刻度条,可以通过颜色模式选择ASCII码是否上色,缩放比例可以有效减少运行时间与提高视频可观赏性

#选择颜色模式ntip3=Label(root, text='请选择颜色模式 ',font = ('楷体',25),bg='#CCCEC4',bd=0)ntip3.place(width=500,relx=0.1,rely=0.385,anchor=W)nv=IntVar()nv.set(1)nradiobutton=Radiobutton(root,text='彩色',font = ('楷体',18),variable=v,value=1,bg='#CCCEC4')nradiobutton.place(relx=0.55,rely=0.385,anchor=W)nradiobutton=Radiobutton(root,text='黑白',font = ('楷体',18),variable=v,value=2,bg='#CCCEC4')nradiobutton.place(relx=0.65,rely=0.385,anchor=W)nn#选择缩放比例ns=IntVar()ns.set(100)nscale=Scale(root, from_=0, to_=100, tickinterval=10, orient='horizontal',sliderrelief=RIDGE,bg='#CCCEC4',troughcolor='#D5CDC6',bd=0,resolution=10, variable=s,showvalue=False,length=500,borderwidth=0,label='请选择缩放比例!!!!!!数值越大越接近原视频,耗时更长;1080p(60~80),720p及以下(100)')nscale.place(relx=0.1,rely=0.49,anchor=W)

  • 程序运行通过一个滚动文本框输出,点击开始转换按钮程序开始运行

# “开始转换”按钮nbrowse_folder_button = Button(root, text='开始转换',font = ('楷体',15),bg='#C4C7C5',command=lambda :thread_it(run))nbrowse_folder_button.place(width=100,height=40,relx=0.75,rely=0.71,anchor="nw")nn# ScrolledText组件(滚动文本框)nstext = ScrolledText(root, width=65, height=23, bg='#C4C7C5')nstext.place(width=420,height=300,relx=0.1,rely=0.58,anchor="nw")

功能实现

程序开始运行

  • 点击开始转换之后,首先或许视频输入地址保存位置颜色模式缩放比例四个变量

def run():n INPUT=input_vedio_address.get()n OUTPUT=input_save_address.get()n color_radio=v.get()n scale_scale=s.get()

视频提取帧图片

  • 将视频每一帧提取出来保存为jpg格式,运行时将图片存放在Cache缓存文件夹,程序运行结束后自动删除

def video2txt_jpg(file_name,color_radio,scale_scale):n vc = cv2.VideoCapture(file_name)n c=1n if vc.isOpened():n r,frame = vc.read()n if not os.path.exists('Cache'):n os.mkdir('Cache')n os.chdir('Cache')n else:n r = Falsen while r:n cv2.imwrite(str(c)+'.jpg',frame)n txt2image(str(c)+'.jpg',color_radio,scale_scale)#同时转换为ascii图n r,frame = vc.read()n c += 1n os.chdir('..')n return vc

图片转换为ASCII形式

  • 该功能实现主要根据像素点的rgb值对应一个ASCII代码,不同的颜色值对应不同的ASCII码。不同ASCII码组合起来就能形成一幅画面。我们还可以调整颜色模式与缩放比例来改善

图片合成视频

  • 将图片合成视频后删除缓存文件夹即可,利用一个for循环遍历所有jpg格式图片,将所有图片作为帧加入视频中,最后生成avi格式的视频文件

def jpg2video(outfile_name,fps):n fourcc = VideoWriter_fourcc(*"MJPG")nn images = os.listdir('Cache')n im = Image.open('Cache/'+images[0])n if(os.path.exists(outfile_name+'avi')):n os.remove(outfile_name+'avi')n vw = cv2.VideoWriter(outfile_name+'.avi',fourcc,fps,im.size)nn os.chdir('Cache')n for image in range(len(images)):n #Image.open(str(image)+'.jpg').convert("RGB").save(str(image)+'.jpg')n frame = cv2.imread(str(image+1)+'.jpg')n vw.write(frame)n stext.insert(END,str(image+1)+'.jpg'+' finishedn')n stext.see(END)n os.chdir('..')n vw.release()

提取音频与合成音频

  • 调用ffmpeg提取音频文件并与avi格式文件合成音频生成mp4文件,删除mp3文件与avi文件

打包为exe形式

  • 使用pyinstaller将程序打包为exe文件格式

pyinstaller -F gudu12306.py -i 1.ico -w --clean

github源地址

https://github.com/gudu12306/vedio_to_ASCII