用Python Opencv实现视频快进

Posted 师大先生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Python Opencv实现视频快进相关的知识,希望对你有一定的参考价值。

怎么用Opencv实现视频快进?小白可能会增大ftp,减小等待时间,但是这种方式大大增加了程序计算量,而且快进有上限,一般电脑全力计算也只不过能快进两三倍而已。要想实现大步幅快进就要用到跳帧:比如读取完第一帧直接读取第十帧,这样就快进了十倍。

如何实现跳帧读取?这里就要用到VideoCapture::set函数。set函数用于为视频对象的属性VideoCaptureProperties设置值。 cv.CAP_PROP_POS_FRAMES 属性就是接下来要读取的帧的索引。 `

cap = cv2.VideoCapture(path)
cap.set(cv.CAP_PROP_POS_FRAMES, index)

就可以实现读取第index帧了。

set就会有getVideoCapture::get函数用于获取相应属性的值,比如视频的总帧数,播放帧率等。

getset函数通过API来调用操作系统,进而调用设备驱动,再调用硬件。

VideoCaptureProperties都是用int型整数来表示的,大约有40个左右。
后面的是对一些专业相机的设置,不太常用。这里记录前16个:

Velue属性名描述
0cv.CAP_PROP_POS_MSEC视频当前播放位置的时间(毫秒)
1cv.CAP_PROP_POS_FRAMES接下来要解码/捕获的帧的基于0的索
2cv.CAP_PROP_POS_AVI_RATIO视频文件的相对位置:0 为开始,1 为结束。
3cv.CAP_PROP_FRAME_WIDTH帧图像的宽度。
4cv.CAP_PROP_FRAME_HEIGHT帧图像的高度。
5cv.CAP_PROP_FPS帧率。
6cv.CAP_PROP_FOURCC视频编码格式 (4个字符)。
7cv.CAP_PROP_FRAME_COUNT视频文件中的帧数。
8cv.CAP_PROP_FORMATVideoCapture :: retrieve()返回的Mat对象的格式。
9cv.CAP_PROP_MODE特定于后端的值,指示当前的捕获模式。
10cv.CAP_PROP_BRIGHTNESS图像的亮度(仅适用于支持该功能的相机)。
11cv.CAP_PROP_CONTRAST图像的对比度(仅适用于相机)。
12cv.CAP_PROP_SATURATION图像饱和度(仅适用于相机)。
13cv.CAP_PROP_HUE图像的色相(仅适用于相机)。
14cv.CAP_PROP_GAIN图像增益(仅适用于支持该功能的相机)。
15cv.CAP_PROP_EXPOSURE曝光(仅适用于支持该功能的相机)。
16cv.CAP_PROP_CONVERT_RGB布尔标志,指示是否应将图像转换为RGB。

详细讲解用Python把动漫视频生成字符的完整步骤

在这里插入图片描述

一、OpenCV的操作图像

首先我们需要安装OpenCV,执行下面语句:

pip install opencv-python

之后要用到。

1、读取和显示

我们直接看代码:

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

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

2、灰度转换

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

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

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

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

在这里插入图片描述

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函数,第一个参数传入图片,第二个参数传入修改后的尺寸。

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
)

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

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

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

6、写入视频

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

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

在这里插入图片描述

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

二、像素映射成字符

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

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

在这里插入图片描述

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

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

我们可以得到下列公式:

在这里插入图片描述

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

在这里插入图片描述

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

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)

效果如下:

在这里插入图片描述

四、生成字符视频

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

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.实现效果图:

卡卡西经典战役的字符视频片段

在这里插入图片描述

2.完整代码如下:

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

在这里插入图片描述

点击领取.福利干货满满

①兼职交流,行业咨询、大佬在线专业解答有
②Python开发环境安装教程有
③Python400集自学视频有
④软件开发常用词汇有
⑤Python学习路线图有
⑥3000多本Python电子书有
如果你用得到的话可以直接拿走,在我的QQ技术交流群里群号:767030506(纯技术交流和资源共享,广告勿入)以自助拿走

文章到这里就结束了,更多有关Python精彩内容可以关注小编看小编主页。

以上是关于用Python Opencv实现视频快进的主要内容,如果未能解决你的问题,请参考以下文章

Opencv 3.0 加载人脸级联时出错

视频中的Opencv马赛克

opencv 提取avi视频中的帧,逐帧播放

Python+opencv+pyaudio实现带声音屏幕录制

用java读取本地磁盘视频资源,OutputStream输出的视频文件在html的video标签播放时不能点快进

详细讲解用Python把动漫视频生成字符的完整步骤