博客专栏

EEPW首页>博客> Python 的一万种用法:生成字符视频

Python 的一万种用法:生成字符视频

发布人:AI科技大本营 时间:2021-05-25 来源:工程师 发布文章

以下文章来源于新建文件夹X ,作者ZackSock

前言

在之前也写过生成字符视频的文章,但是使用的是命令行窗口输出,效果不是很好,而且存在卡顿的情况。于是我打算直接生成一个mp4的字符视频。大致思路和之前一样:Python20行代码实现视频字符化。

下面来看一个效果图:

1.gif

卡卡西vs带土效果截取

OpenCV的操作图像

我们先来看一些基本操作。首先我们需要安装OpenCV,执行下面语句:

pip install opencv-python

之后就可以使用了。

1.1、读取和显示

我们直接看代码:

import cv2 # 读取图片 img = cv2.imread("1.jpg") # 显示图片 cv2.imshow("img", img) cv2.waitKey() cv2.destroyAllWindows()

其中waitKey是等待输入的函数,因为imshow之后显示一瞬间,所以我们需要调用它。而destroyAllWindows是释放窗口。

1.2、灰度转换

灰度转换就是将图片转换成黑白图片(灰色),这样可以方便我们处理像素。代码如下:

import cv2 img = cv2.imread("1.jpg") # 灰度转换 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

我们还可以直接以灰度形式读入:

import cv2 # 以灰度形式读入 img = cv2.imread("1.jpg", 0)

1.3、获取图片尺寸并修改尺寸

我们直接看代码:

import cv2 img = cv2.imread("1.jpg", 0) # 获取图片的高宽 h, w = img.shape # 缩放图片 res = cv2.resize(img, (w//2, h//2))

因为img的shape属性是一个元组,所以我们可以直接自动拆包。

然后调用cv2.resize函数,第一个参数传入图片,第二个参数传入修改后的尺寸。

1.4、绘制文字

绘制文字我们需要调用cv2.putText函数,代码如下:

import cv2 img = cv2.imread('1.jpg') # 绘制文字 cv2.putText( # 被绘制的图片 img, # 要绘制的文字 'Hello', # 文字左下角的坐标 (100, 500), # 字体 cv2.FONT_HERSHEY_SIMPLEX, # 字体大小缩放 20, # 文字颜色 (0, 0, 0), # 文字粗细 10 )

我们只需要注意这些参数就好了。

1.5、读取视频

读取视频的操作一般是通用的,代码如下:

import cv2 # 读取视频 cap = cv2.VideoCapture('1.mp4') # 获取视频的帧率 fps = cap.get(cv2.CAP_PROP_FPS) # 循环读取图片的每一帧 while True: # 读取下一帧 ret, frame = cap.read() if not ret: break else: pass cap.release()

上面我们获取的视频的帧,在写入视频的时候我们需要用到。

1.6、写入视频

写入视频的操作也是常规代码:

import cv2 fourcc = cv2.VideoWriter_fourcc(*'mp4v') writer = cv2.VideoWriter('11.mp4', fourcc, fps, (w, h)) # 写入视频 writer.write(frame) *** write.release()

有了这些知识,我们就可以开始下一步工作了。

像素映射成字符

对于只有一个通道的图片,我们可以把它当成一个矩形,这个矩形最小单位就是一个像素。而字符化的过程就是用字符替代像素点的过程。所以我们要遍历图像的每个像素点,但是我们应该用什么字符取代呢?

我们颜色有一个参照表,而opencv将这个参数表切割成256份,代表不同的程度,我们也可以做一个参照表,不过表中的内容不是颜色,而是字符。

2.png

颜色表

上图为颜色表,我们可以使颜色表和字符表建立映射关系。假如字符表如下:

mqpka89045321@#$%^&*()_=||||}

我们可以得到下列公式:

3.png

字符和颜色之间等式

经过变换可以求得相应颜色对应字符表中的字符:

4.png

计算字符下标的公式

这个公式不理解也没关系,只需要会用即可。下面就是我们像素转字符的代码:

def pixel2char(pixel): char_list = "@#$%&erytuioplkszxcv=+---. " index = int(pixel / 256 * len(char_list)) return char_list[index]

这个字符表是可以自己定义的。

生成字符图片

现在我们只需要将像素逐个转换成字符就好了,代码如下:

def get_char_img(img, scale=4, font_size=5): # 调整图片大小 h, w = img.shape re_im = cv2.resize(img, (w//scale, h//scale)) # 创建一张图片用来填充字符 char_img = np.ones((h//scale*font_size, w//scale*font_size), dtype=np.uint8)*255 font = cv2.FONT_HERSHEY_SIMPLEX # 遍历图片像素 for y in range(0, re_im.shape[0]): for x in range(0, re_im.shape[1]): char_pixel = pixel2char(re_im[y][x]) cv2.putText(char_img, char_pixel, (x*font_size, y*font_size), font, 0.5, (0, 0, 0)) return char_img

这里我们使用了一个np.ones函数,它的作用我们理解为生成一个黑色图片。

生成的尺寸我们先除了scale,然后再乘font_size。scale是原图的缩小程度,因为像素有很多,所以我们需要先把图片缩小。而为了让我们的字体显示更清楚,我们需要把生成的字符图片放大。

因此需要注意,虽然我们生成的图片看起来单调,但是当font_size设置为5时,得到的图片已经比较大了。因此当你生成长时间的视频时,会花费比较多的时间,生成的视频也比较大。

我们来测试一下上面的函数:

import cv2 import numpy as np def pixel2char(pixel): char_list = "@#$%&erytuioplkszxcv=+---. " index = int(pixel / 256 * len(char_list)) return char_list[index] def get_char_img(img, scale=4, font_size=5): # 调整图片大小 h, w = img.shape re_im = cv2.resize(img, (w//scale, h//scale)) # 创建一张图片用来填充字符 char_img = np.ones((h//scale*font_size, w//scale*font_size), dtype=np.uint8)*255 font = cv2.FONT_HERSHEY_SIMPLEX # 遍历图片像素 for y in range(0, re_im.shape[0]): for x in range(0, re_im.shape[1]): char_pixel = pixel2char(re_im[y][x]) cv2.putText(char_img, char_pixel, (x*font_size, y*font_size), font, 0.5, (0, 0, 0)) return char_img if __name__ == '__main__': img = cv2.imread('dl.jpg', 0) res = get_char_img(img) cv2.imwrite('d.jpg', res)

效果如下:

5.png

生成的字符画

可以看到效果还是很不错的。

生成字符视频

有了上面的代码,我们就可以对整个视频进行转换了。将视频转换成字符视频的代码如下:

def generate(input_video, output_video): # 1、读取视频 cap = cv2.VideoCapture(input_video) # 2、获取视频帧率 fps = cap.get(cv2.CAP_PROP_FPS) # 读取第一帧,获取转换成字符后的图片的尺寸 ret, frame = cap.read() char_img = get_char_img(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY), 4) # 创建一个VideoWriter,用于保存视频 fourcc = cv2.VideoWriter_fourcc(*'mp4v') writer = cv2.VideoWriter(output_video, fourcc, fps, (char_img.shape[1], char_img.shape[0])) while ret: # 读取视频的当前帧,如果没有则跳出循环 ret, frame = cap.read() if not ret: break # 将当前帧转换成字符图 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) char_img = get_char_img(gray, 4) # 转换成BGR模式,便于写入视频 char_img = cv2.cvtColor(char_img, cv2.COLOR_GRAY2BGR) writer.write(char_img) writer.release()

下面是卡卡西经典战役的字符视频片段:

2.gif

卡卡西vs带土效果

完整代码如下:

import cv2 import numpy as np def pixel2char(pixel): char_list = "@#$%&erytuioplkszxcv=+---. " index = int(pixel / 256 * len(char_list)) return char_list[index] def get_char_img(img, scale=4, font_size=5): # 调整图片大小 h, w = img.shape re_im = cv2.resize(img, (w//scale, h//scale)) # 创建一张图片用来填充字符 char_img = np.ones((h//scale*font_size, w//scale*font_size), dtype=np.uint8)*255 font = cv2.FONT_HERSHEY_SIMPLEX # 遍历图片像素 for y in range(0, re_im.shape[0]): for x in range(0, re_im.shape[1]): char_pixel = pixel2char(re_im[y][x]) cv2.putText(char_img, char_pixel, (x*font_size, y*font_size), font, 0.5, (0, 0, 0)) return char_img def generate(input_video, output_video): # 1、读取视频 cap = cv2.VideoCapture(input_video) # 2、获取视频帧率 fps = cap.get(cv2.CAP_PROP_FPS) # 读取第一帧,获取转换成字符后的图片的尺寸 ret, frame = cap.read() char_img = get_char_img(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY), 4) # 创建一个VideoWriter,用于保存视频 fourcc = cv2.VideoWriter_fourcc(*'mp4v') writer = cv2.VideoWriter(output_video, fourcc, fps, (char_img.shape[1], char_img.shape[0])) while ret: # 读取视频的当前帧,如果没有则跳出循环 ret, frame = cap.read() if not ret: break # 将当前帧转换成字符图 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) char_img = get_char_img(gray, 4) # 转换成BGR模式,便于写入视频 char_img = cv2.cvtColor(char_img, cv2.COLOR_GRAY2BGR) writer.write(char_img) writer.release() if __name__ == '__main__': generate('in.mp4', 'out.mp4')

我们只需要修改generate的参数就好了。

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

霍尔传感器相关文章:霍尔传感器工作原理


霍尔传感器相关文章:霍尔传感器原理


关键词:Python

相关推荐

技术专区

关闭