思路
本文实现思路分为如下三步:
- 将视频转化为一帧一帧的图片(video2image)
- 把图片转化为字符图片(image2str)
- 把一帧一帧的字符图片组合成字符视频(image2video
References
Pillow文档
python将图片转化为字符图
OpenCV-视频转图片/图片转视频
Python+opencv将图片生成成视频
代码
import cv2
import numpy as np
from PIL import Image,ImageFont,ImageDraw
# =============================================================================
# video2image
# =============================================================================
#import cv2
def getFrame(videoPath, savePicturePath):
cap = cv2.VideoCapture(videoPath)
numFrame = 0
rval=cap.isOpened()
while rval:
numFrame+=1
rval,frame=cap.read()
if rval:
#jinji为py文件的当前目录下新建的文件夹
cv2.imwrite('./jinji/'+str(numFrame) + '.jpg', frame) #文件保存路径不能有中文
#cv2.imwrite(savePicturePath+str(numFrame) + '.jpg', frame) 如果你的svPath不含有中文,可以这样使用
cv2.waitKey(1)
else:
break
return numFrame
videoPath=r'D:\学习\计算机视觉\进击的巨人\勇士.mp4'
savePicturePath=r'D:\学习\计算机视觉\进击的巨人'
numFrame=getFrame(videoPath,savePicturePath)#numFrame表示有多少张图片,下面有用到
# =============================================================================
# image2str
# =============================================================================
#import numpy as np
#from PIL import Image,ImageFont,ImageDraw
def img_to_char(image_path,height):
#读取图片
img = Image.open(image_path)
img_width, img_height = img.size
# 假设字符的宽度是高度的2倍
width = 2* height * img_width // img_height
img = img.resize((width, height), Image.ANTIALIAS)#图片的缩放
#读取图片的灰度值矩阵
data = np.array(img.convert('L'))
#设定字符,字符数要是256的因子,这里取32
chars = "#RMNHQODBWGPZ*@$C&98?32I1>!:-;. "
N = len(chars)
#计算每个字符的区间,//取整
n = 256 // N
#result是字符结果
result = ''
for i in range(height):
for j in range(width):
result += chars[data[i][j] // n]
result += '\n'
#保存为txt文件
with open(image_file+'str.txt', mode='w') as f:
f.write(result)
#保存字符图片
font = ImageFont.truetype(r"控制面板\所有控制面板项\字体\Calibri\calibri.ttf",1)
im = Image.new("RGB",(width,height*2),(255,255,255))
dr = ImageDraw.Draw(im)
x,y=0,0
lines2=result.split('\n')[:height]
for line in lines2:
for word in line:
dr.text((x,y),word,font=font,fill=0)
x+=1
x=0
y += 2 #假设一个字符占2*1像素
im.save(image_file+'img.jpg')
numframes=numFrame #numFrame表示有多少图片
image_file_list=[ r'D:\学习\计算机视觉\jinji\{}'.format(i) for i in range(1,numframes+1)]#此处路径是刚刚图片保存的路径
#image_file = r'D:\学习\计算机视觉\jinji\1'
image_file_format='.jpg'
height = 150 #可自己调
task=0
for image_file in image_file_list:
image_path=image_file+image_file_format
img_to_char(image_path,height)
task+=1
print("我已经完成{}/{}啦0.0".format(task,numframes))
# =============================================================================
# image2video
# =============================================================================
#import cv2
fps = 30.17 #根据自己视频秒数和分割的帧数来算
img_temp = Image.open(image_path)
img_width, img_height = img_temp.size
width = 2* height * img_width // img_height
size = (width,height*2)
videowriter = cv2.VideoWriter("braves.MP4",cv2.VideoWriter_fourcc(*'MP42'),fps,size)#mp4比avi效果好一些;文件名最好用英文
for i in range(1,numframes):
img = cv2.imread('./img/'+'{}img.jpg'.format(i))
videowriter.write(img)
videowriter.release()
示例gif
这个示例是之前做的“鸡你太美”先看下效果的,发现还可以。(由于大小限制,这边只用了70帧来制作gif)