python 实现将视频转换为图片

代码让人头秃,可是我喜欢上了代码的逻辑感和代码解决问题的力量。
(我要对这个专题的图片进行修改,缩小看和我导头像有点像QAQ)


代码展示V2.1

更新版本 更新点
V2.0 试着加入了from pathlib import Path,但是还是不熟练,不太会用,就和os.path混合着用了。你应该使用pathlib替代os.path
V2.1 1. 视频类型判断更加齐全;2. 打印说明更加详细

V2.2待优化部分:

  1. 选帧转换
"""
将视频转换为图片,可以为多个文件夹下的图片。
注:在程序使用前需先配置好main中的地址
视频路径:video_path_list = [path1, path2, ...](路径数量可以为[1,n],每个路径下的视频数也可为[1,m])
    paht1                path2             ....
     |------video1.avi      |-----video1.avi
     |------vidoe2.avi      |-----...
     |------....
图片存储路径:image_save_dir = save_path(存储方式则将按以下方式)
    save_path
     | -------path1_name
                |----video1
                        |----jpg1.jpg
                        |----jpg2,jpg
                |----video2
                ...
     |-------path2_name
     ...
"""

import cv2
import os
from pathlib import Path

VID_FORMATS = ('.mov', '.avi', '.mp4', '.mpg',  '.mpeg', '.m4v', '.wmv', '.mkv', '.mp3')


def videos2images(root_video_path, root_save_dir):
    for video_dir_path in root_video_path:
        # 1.检测读取文件路径是否正确
        path_video = Path(video_dir_path)
        if path_video.is_dir():
            print(video_dir_path + '\t ok')
            videos = os.listdir(video_dir_path)
        else:
            print('\033[31mLine36 error: \033[31m' + video_dir_path + 'is not exist!')
            return

        # 2. 生成存储文件夹
        save_name_dir = Path(path_video.name)
        save_name_dir = os.path.join(root_save_dir, save_name_dir)
        if not os.path.exists(save_name_dir):
            os.makedirs(save_name_dir)

        file_count = 0
        for video in videos:
            # 判断是否为视频文件,如果不是视频文件则跳过并进行说明
            if Path(video).suffix in VID_FORMATS:
                file_count += 1  # 视频文件数+1
                save_jpg_dir = os.path.join(save_name_dir, Path(video).stem)
                if not os.path.exists(save_jpg_dir):
                    os.makedirs(save_jpg_dir)
                each_video_path = os.path.join(path_video, video)
                save_dir = save_jpg_dir
            else:
                print('\033[33mLine56 warning: \033[33m' + os.path.basename(video) + ' is not a video file, so skip.')
                continue

            # 3. 开始转换。打印正在处理文件的序号和他的文件名,并开始转换
            print('\033[38m' + str(file_count) + ':' + Path(video).stem + '\033[38m')
            cap = cv2.VideoCapture(each_video_path)

            flag = cap.isOpened()
            if not flag:
                print("\033[31mLine 65 error\033[31m: open" + each_video_path + "error!")

            frame_count = 0  # 给每一帧标号
            while True:
                frame_count += 1
                flag, frame = cap.read()
                if not flag:  # 如果已经读取到最后一帧则退出
                    break
                if os.path.exists(
                        save_dir + str(frame_count) + '.jpg'):  # 在源视频不变的情况下,如果已经创建,则跳过
                    break
                cv2.imwrite(save_dir + '\\' + str(frame_count) + '.jpg', frame)

            cap.release()
            print('\033[38m' + Path(video).stem + ' save to ' + save_dir + 'finished. \033[38m')  # 表示一个视频片段已经转换完成


if __name__ == '__main__':
    # 需要转换的视频路径列表,直达视频文件(自定义修改)
    video_path_list = [r'E:\Code\feature_extraction_svm\video/', r'E:\Code\feature_extraction_svm\video2']

    # 预期存储在的主文件夹,即'result'文件夹下
    image_save_dir = r'E:\Code\feature_extraction_svm\result2'
    path_save = Path(image_save_dir)
    if not path_save.exists():
        path_save.mkdir()
    # 进行转换
    videos2images(video_path_list, image_save_dir)


V1.0
此段代码能够实现多个文件夹中多个视频片段的转换,代码的具体含义可以参考注释。
具体操作为将此段代码复制粘贴到创建好的py文件,配置好第63行的源文件路径,然后运行。

# 将四个文件夹中的多个视频文件转换为图片
import cv2
import os

number_in_dir = []  # 可以去掉,用来统计文件个数的
def videos2images(video_path, image_save_dir):
    # 1. 在存储路径下创建副文件夹(视频类型文件夹)。将图片的存储路径加上源文件的文件夹名,如'Coffee_room_01'等。
    if os.path.exists(video_path):  # 判断源路径是否正确
        print(video_path + '\t ok')
        if video_path.split('\\')[-2] != 'Videos':  # 这个根据我文件路径自行添加的
            image_save_dir += video_path.split('\\')[-2] + '\\'
        else:
            image_save_dir += video_path.split('\\')[-3] + '\\'

        number_in_dir.append(len(os.listdir(video_path)))  # 可以去掉
    else:
        print(video_path + ' \033[0;37;41merror\033[0m')
        return

    # 2. 读取源路径文件,并创建子文件夹(一段视频一个文件夹)。依次读取源文件里的文件,如果后缀名是‘avi'或 ’MP3',则创建一个关于文件名的子文件夹
    files_in_video_path_list = os.listdir(video_path)
    print(len(files_in_video_path_list))  # 获取当前文件夹下文件个数,用来判断是否有其他类型的文件
    file_count = 0  # 用于统计个数,验证是否全为视频文件,会与len(files_in_video_path_list)进行比较

    for file_in_video_path in files_in_video_path_list:
        file_name = os.path.basename(file_in_video_path)
        if file_name.split('.')[-1] == 'avi' or file_name.split('.')[-1] == 'mp3':
            file_count += 1  # 视频文件数+1
            every_video_save_dir = file_name.split('.')[0] + '\\'
            if not os.path.exists(image_save_dir + every_video_save_dir):  # 创建属于相应文件夹的存储路径
                os.makedirs(image_save_dir + every_video_save_dir)
        else:
            print(' \033[0;37;41merror\033[0m')
            break

        # 3. 开始转换。打印正在处理文件的序号和他的文件名,并开始转换
        print(str(file_count) + ':' + file_name)
        cap = cv2.VideoCapture(video_path + file_name)

        flag = cap.isOpened()
        if not flag:
            print("open" + video_path + file_name + "error!")

        frame_count = 0  # 给每一帧标号
        while True:
            frame_count += 1
            flag, frame = cap.read()
            if not flag:  # 如果已经读取到最后一帧则退出
                break
            if os.path.exists(image_save_dir + every_video_save_dir + str(frame_count) + '.jpg'):  # 在源视频不变的情况下,如果已经创建,则跳过
                break
            cv2.imwrite(image_save_dir + every_video_save_dir + str(frame_count) + '.jpg', frame)

        cap.release()
        print(file_name + ' save to ' + image_save_dir + every_video_save_dir + 'finished ')  # 表示一个视频片段已经转换完成
    if file_count != len(files_in_video_path_list):
        print(' \033[0;37;41Maybe loss something\033[0m')


if __name__ == '__main__':
    # 需要转换的视频路径列表,直达视频文件(自定义修改)
    video_path_list = ['E:\\Datasets_FallDetection\\2 LE2I\Coffee_room_01\\Coffee_room_01\\Videos\\',
                       'E:\\Datasets_FallDetection\\2 LE2I\Home_01\\Home_01\Videos\\',
                       'E:\\Datasets_FallDetection\\2 LE2I\Lecture_room\\Lecture room\\',
                       'E:\\Datasets_FallDetection\\2 LE2I\\Office\\Office\\']

    # 预期存储在的主文件夹,即'result'文件夹
    image_save_dir = '.\\result\\'

    # 进行转换
    for video_path in video_path_list:
        videos2images(video_path, image_save_dir)
        
        
# 修改说明
# A. 如果我只需要转换一个文件夹下的n个视频,那么我在'video_path_list'输入该文件夹的路径,然后注释掉10-15行
# B. 如果我需转换一个文件夹下的某一个视频,那么我在'video_path_list'输入该文件夹的路径,注释掉10-15行,
# 再将第21行改为files_in_video_path_list = [os.path.join(video_path, 'videoname')],如files_in_video_path_list = [os.path.join(video_path, 'video (1).avi')]

结果展示

  1. 将创建’result’主文件夹和副文件夹

  2. 每个副文件夹下都将生成与视频名相对应的子文件夹,并按视频帧数顺序转换为jpg图片。

  3. 终端上将提示正在处理的文件路径,正在对哪个视频进行转换和转换完成提示。

参考链接

python 如果文件夹不存在 创建文件夹
使用python实现视频与图片相互转换
Python zfill()方法
【Python】如何读取文件夹下的所有文件
python获取路径中的文件名
python如何从路径中获取文件名
Python print()输出颜色设置
python5行代码实现查看指定文件夹中的文件个数

来源:橙橙小狸猫

物联沃分享整理
物联沃-IOTWORD物联网 » python 实现将视频转换为图片

发表评论