OpenCV对指定目录下所有视频批量生成九宫格缩略图

这篇具有很好参考价值的文章主要介绍了OpenCV对指定目录下所有视频批量生成九宫格缩略图。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近接到一个客户的订单,需要批量对电影片段截图,为了方便,于是我撸了一下午代码,写了这么一个辅助工具出来,希望对各位有相似需求的朋友们提供帮助。程序是用Python实现的。

大致思路:

1. 使用os.walk遍历当前目录(包括子目录)下所有文件,获得文件路径列表,再对列表中的文件分别处理。这里为了方便显示进度,我使用了tqdm来枚举列表。

2. 使用OpenCV的VideoCapture对视频等距截取9张图片。对视频截图的操作就像读文件时的操作,是存在一个视频帧的“指针”的,一帧图片截完了以后需要根据步长(ceil(总帧数/8)-1,减1是为了防止某些视频最后一帧为空而导致截图失败退出)更新指针。

3. 重点来了:将截取到的9张图片,每3张一组,使用np.concatenate横向拼接得到img0, img1, img2,最后将这三组图片用同样的方法纵向拼接得到img9,即为不带任何信息的纯九宫格图片。

关于numpy中矩阵拼接函数concatenate的用法,可以参考这篇博文:np.concatenate() 使用说明_Tchunren的博客-CSDN博客_np.concatenate([xi, x],axis=1

4. 使用cv2.copyMakeBorder在上述的img9的最上方画高为200的灰色边框,用于容纳视频的基本信息文字。然后获取视频的基本信息,包括文件大小、分辨率、时长、帧率等。

提示:opencv中获取分辨率使用cap.get(cv2.CAP_PROP_FRAME_HEIGHT),和cap.get(cv2.CAP_PROP_FRAME_WIDTH),分别取得帧的高和宽;

获取视频帧率使用cap.get(cv2.CAP_PROP_FPS);

获取视频时长,先使用cap.get(cv2.CAP_PROP_FRAME_COUNT)获取总帧数,再除以上述的帧率即可。

最后使用cv2.putText将上面的信息文字写入图片。

关于opencv中copyMakeBorder函数的用法,可以参考这篇博文:

OpenCV-Python: cv2.copyMakeBorder()函数详解_我是大黄同学呀的博客-CSDN博客_copymakeborder函数详解

关于opencv中putText函数的用法,可以参考这篇博文:

opencv中puttext()函数用法总结(03)_洛克家族的博客-CSDN博客_opencv puttext

最后附上效果图:

OpenCV对指定目录下所有视频批量生成九宫格缩略图文章来源地址https://www.toymoban.com/news/detail-432187.html

代码:

import cv2
import numpy as np
import os
from tqdm import tqdm

BLACK = [0, 0, 0]
GRAY = [135, 139, 142]

# Turn the large image into a small one, without changing the aspect ratio, and add black borders to make up for the
# shortage.
def my_resize(image, height, width):
    h, w, c = image.shape
    top, bottom, left, right = (0, 0, 0, 0)
    # assert h >= height and w >= width, 'ratio should less than 1'
    long_side = max(h, w)
    if h >= w:
        ratio = float(height) / long_side
    elif h < w:
        ratio = float(width) / long_side

    # resize the long side and add black border to the both size of the short side
    resi = cv2.resize(image, (0, 0), fx=ratio, fy=ratio, interpolation=cv2.INTER_NEAREST)
    res_height, res_width, res_c = resi.shape

    if h >= w:
        if res_width < width:
            dw = width - res_width
            left = dw // 2
            right = dw - left

    elif h < w:
        if res_height < height:
            dh = height - res_height
            top = dh // 2
            bottom = dh - top

    dst = cv2.copyMakeBorder(resi, top, bottom, left, right, cv2.BORDER_CONSTANT, value=BLACK)
    return dst

def get_hms(seconds):
    m, s = divmod(seconds, 60)
    h, m = divmod(m, 60)
    str = "%02d:%02d:%02d" % (h, m, s)
    return str

def escribir_info(img, fname, infos = ()):
    addtext = img.copy()
    msg0 = 'File Name: ' + fname
    msg1 = 'File Size: ' + str(infos[0]) + ' bytes (' + str(round(infos[0] / 1024.0 / 1024.0, 2)) + ' MB)'
    msg2 = 'Resolution: ' + str(int(infos[2])) + 'x' + str(int(infos[1]))
    msg3 = 'FPS: ' + str(round(infos[3], 2))
    seconds = round(infos[4] / infos[3], 3)
    msg4 = 'Duration: ' + get_hms(seconds) + ' (' + str(seconds) + ' s)'
    cv2.putText(addtext, msg0, (20, 30), cv2.FONT_HERSHEY_COMPLEX, 1.0, (255, 255, 255), 2)
    cv2.putText(addtext, msg1, (20, 70), cv2.FONT_HERSHEY_COMPLEX, 1.0, (255, 255, 255), 2)
    cv2.putText(addtext, msg2, (20, 110), cv2.FONT_HERSHEY_COMPLEX, 1.0, (255, 255, 255), 2)
    cv2.putText(addtext, msg3, (20, 150), cv2.FONT_HERSHEY_COMPLEX, 1.0, (255, 255, 255), 2)
    cv2.putText(addtext, msg4, (20, 190), cv2.FONT_HERSHEY_COMPLEX, 1.0, (255, 255, 255), 2)
    return addtext

def gen_captura(img_path, path_dir):
    cap = cv2.VideoCapture(img_path)
    frame_cnt = cap.get(cv2.CAP_PROP_FRAME_COUNT)
    frame_itv = int(frame_cnt // 8) - 1  # 9 pictures
    s_frame = 1
    flag = 1
    imgs = []

    while cap.isOpened():
        cap.set(cv2.CAP_PROP_POS_MSEC, flag)
        cap.set(cv2.CAP_PROP_POS_FRAMES, s_frame)
        ret, img = cap.read()
        try:
            dst = my_resize(img, 360, 640)
        except Exception as e:
            print('Error while capturing thumbnails: ' + str(e) + '\nNow we will use a black image to fill')
            dst = np.zeros((360, 640, 3), np.uint8)
            dst[:] = [0, 0, 0]
        finally:
            imgs.append(dst)
        flag += 1
        s_frame += frame_itv
        if s_frame >= frame_cnt:
            break

    # Stitching images into a nine-box grid
    img0 = np.concatenate(imgs[:3], 1)
    img1 = np.concatenate(imgs[3:6], 1)
    img2 = np.concatenate(imgs[6:], 1)
    img9 = np.concatenate([img0, img1, img2], 0)
    res = cv2.copyMakeBorder(img9, 200, 0, 0, 0, cv2.BORDER_CONSTANT, value=GRAY)
    pint = os.path.basename(img_path)
    res = escribir_info(res, pint, (os.path.getsize(img_path),
                                    cap.get(cv2.CAP_PROP_FRAME_HEIGHT), cap.get(cv2.CAP_PROP_FRAME_WIDTH),
                                    cap.get(cv2.CAP_PROP_FPS), cap.get(cv2.CAP_PROP_FRAME_COUNT)))

    cv2.imwrite(os.path.join(path_dir, os.path.splitext(pint)[0] + '_scr.jpg'), res)

    cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    path_dir = input('Please input directory path that contains video:')
    if not os.path.exists(path_dir):
        print('Directory does not exist!')
        exit(0)
    proc_list = []
    for r, d, files in os.walk(path_dir):
        for file in files:
            if file.endswith('mp4') or file.endswith('mkv') :
                padre = os.path.join(r, file)
                padre = padre.replace('\\', '/')
                proc_list.append((padre, r))
    for i, tp in tqdm(enumerate(proc_list)):
        print('Now processing video: ' + tp[0])
        gen_captura(tp[0], tp[1])

到了这里,关于OpenCV对指定目录下所有视频批量生成九宫格缩略图的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用FFmpeg生成视频的预览图缩略图

    使用ffprobe 命令获取到 video流的 nb_frames 这里使用json格式返回获取 使用ffmpeg 命令合帧,通过tile拼接成4X6的网格 简单介绍下上面的命令 上面命令也可以换成 这里使用thumbnail命令可以达到同样效果,区别是thumbnail根据官方介绍是会选择典型帧,而不是固定帧,测试下来确实是

    2024年02月06日
    浏览(41)
  • 批量clone gitlab 指定分组下所有仓库代码

    因分析某分组下所有的仓库代码,故批量clone gitlab 指定分组下所有的git仓库,用于分析或代码检查  如果出现了  ModuleNotFoundError: No module named \\\'gitlab\\\'  的错误提示,可能是因为没有安装  python-gitlab  库。可以通过运行以下命令来安装: 安装完毕后,再次运行脚本即可。

    2024年02月05日
    浏览(39)
  • python 解压指定目录的所有zip文件

    ========================================================== 修改了一下!!!递归所有文件夹里面的zip 附件为,打包好的exe,可以直接执行。(https://download.csdn.net/download/li13148023/88492399)

    2024年02月06日
    浏览(41)
  • PHP实现读取指定目录下的所有文件

    在php中读取指定目录下的文件主要用到了opendir和readdir函数 1:语法 2:参数说明 参数 描述 path 必需。规定要打开的目录路径。 context 可选。规定目录句柄的环境。context 是可修改目录流的行为的一套选项。 3:返回值 成功则返回目录句柄资源。失败则返回 FALSE。如果路径不是

    2024年02月05日
    浏览(45)
  • Python中获取指定目录下所有文件名的方法

    在《Python中文件名和路径的操作》中提到,os模块中的函数可以对文件进行操作。通过递归以及os模块中提供的函数,可以获取指定目录下所有的文件名。 通过递归获取指定目录下所有文件名的基本流程,如图1所示。 图1 基本流程 定义一个名为walk的函数,该函数有一个参数

    2024年02月12日
    浏览(58)
  • shell 脚本统计 http 文件服务器下指定目录及其子目录下所有文件的大小

    shell脚本如下: 首先 vi calculate_size.sh 写入下入内容 执行 sh calculate_size.sh http://example.com/some/dir/ 即可统计 http 文件服务器http://example.com/some/dir/ 中 dir 目录及其子目录下所有文件的大小。

    2024年02月15日
    浏览(59)
  • python遍历文件夹下的所有子文件夹,并将指定的文件复制到指定目录

    在1文件夹中有1,2两个文件夹 将这两个文件夹中的文件复制到 after_copy中 源文件 复制后: 参考1 源文件 复制后 参考2 如果复制bmp文件就将 suffix = \\\".json\\\" 改为 suffix = \\\".bmp\\\"

    2024年02月11日
    浏览(92)
  • 【文件IO】Linux 文件操作(一) —— 遍历指定目录下的所有文件

    目录 一、访问目录相关函数 1、打开/访问目录 (opendir / fdopendir) 2、读取目录内容 (readdir) 3、关闭目录 (closedir) 二、遍历指定目录下的所有文件 opendir / fdopendir 函数的作用是访问指定路径的目录,函数声明如下: (1) opendir opendir 函数是通过用户提供的目录路径来访问目录, 参

    2024年02月04日
    浏览(57)
  • shell脚本-批量获取目录下所有文件的md5值、大小、inode值

    MD5的全称是Message-Digest Algorithm 5,它一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5值等同于文件的ID,它的值是唯一的。 如果文件已被修改,其MD5值将发生变化。 运行结果: 文件储存在硬盘上,硬盘的

    2024年02月09日
    浏览(44)
  • [通知]rust跟我学八:获取指定目录下的所有文件全路径 已上线

    大家好,我是带剑书生,开源库get_local_info的作者。目前我的付费专栏已经上线,用于介绍在实现get_local_info过程中,遇到该问题所使用的解决方法,喜欢的朋友可以去订阅了,19.9元,非常便宜的价格,做开源不容易。希望能帮助您在学习Rust时,少走弯路,尽快进入项目。

    2024年01月19日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包