我们将这样的视频
变成这个样子
变得又难看,又看不清,搞这干啥?
闲的咯,下面我们来看看是如何实现的
1、思路
我参考了网上很多人的实现方法,最终我的思路是这样的
1、我们先准备好一个视频,想办法把这个视频变成很多很多的图片
2、接着我们把每一张图片都变成字符串的样式(是把彩色图片变成字符串填充的图片,不是变成一堆字符串)
3、最后,再把转换好的图片变成一个视频
下面我们看看每一步如何利用python实现呢
第一步:视频->图片
嘿嘿,要是一张一张去截图,好像可以满足我们的需求哦,但那肯定不行,我们知道视频都是又一幅幅图片构成的,或者叫一帧一帧的图片构成的,那么在所有的帧中有的帧是关键帧,按道理似乎只要知道关键帧,就可以把前面和后面的图片推导出来,以此似乎可以起到压缩视频的目的,这次我们不管那么多,直接把视频一帧一帧全部保存为图片,不管是不是关键帧。利用opencv-python,实现如下(截取)
def getFrame(self,videoPath, svPath):
cap = cv2.VideoCapture(videoPath)
numFrame = 0
nums = 0
while True:
nums +=1
if cap.grab():
flag, frame = cap.retrieve()
if not flag:
continue
else:
numFrame += 1
newPath = svPath + str(numFrame) + ".jpg"
cv2.imencode('.jpg', frame)[1].tofile(newPath)
if nums >= self.g_frame_num:
break
if cv2.waitKey(10) == 27:
break
看到在while循环中,我们视频的帧全部保存下来为jpg图片,g_frame_num是一个类成员变量,可以让我们定取多少帧数据,以此,我们完成第一步
第二步:彩色图片->字符串图片
这部分稍微麻烦一点点,我的思路是这样的,将图片的每个像素点,都用同样色彩的字符代替,然后生成一幅新图片,但是注意,一个字符串占得像素点可不是一个,所以在转换时我们还需要进行一些处理,看看图片应该用多少个像素来填充
ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
def get_char(r,g,b,alpha = 256):#获取对应的字符
if alpha == 0:
return ' '
length = len(ascii_char)
gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
unit = (256.0 + 1)/length
return ascii_char[int(gray/unit)]
def image_to_strimage(self,isgray=False):
for k in range(1, self.g_frame_num+1):
path = './img/' + str(k) + '.jpg'
im = Image.open(path).convert('RGB')
raw_width = int(im.width)
raw_height = int(im.height)
font = ImageFont.truetype('consola.ttf', 10, encoding='unic')
font_x, font_y = font.getsize(' ')
block_x = int(font_x)
block_y = int(font_y)
w = int(raw_width / block_x)
h = int(raw_height / block_y)
im = im.resize((w, h), Image.NEAREST)
txts = []
colors = []
for i in range(h): # 遍历行
line = ''
lineColor = []
for j in range(w): # 遍历列
pixel = im.getpixel((j, i))
lineColor.append((pixel[0], pixel[1], pixel[2]))
line += get_char(pixel[0], pixel[1], pixel[2])
txts.append(line)
colors.append(lineColor)
im_txt = Image.new("RGB", (raw_width, raw_height), (255, 255, 255))
draw_handle = ImageDraw.Draw(im_txt)
for j in range(len(txts)):
for i in range(len(txts[j])):
if isgray:
draw_handle.text((i * block_x, j * block_y), txts[j][i], (50, 50, 50))
else:
draw_handle.text((i * block_x, j * block_y), txts[j][i], colors[j][i])
# name = path + str(k) + '.jpg'
im_txt.save(path, 'JPEG')
第三步:图片->视频
利用opencv库实现,在循环中顺便吧那些没用的图片删掉(这种方法出来的视频文件较大)
def show(self):
img = Image.open('./img/1.jpg')
w = img.width
h = img.height
print('视频格式',w,'*',h)
videoWriter = cv2.VideoWriter('test.avi', cv2.VideoWriter_fourcc(*'MJPG'), 25, (w, h))
path_file_number = glob.glob(pathname='./img/*.jpg')
for i in range(1,len(path_file_number)+1):
path = './img/' + str(i) + '.jpg'
img = cv2.imread(path)
videoWriter.write(img)
os.remove(path)
videoWriter.release()
效果大概就是这么个样子
没有声音,可以想办法用python去取一下,问题应该不大吧