Здравствуйте и снова добро пожаловать в еще одну часть серии руководств по OPEN-CV с Python. В предыдущей части мы увидели некоторые сложные и интуитивно понятные функции библиотеки Open-CV и выполнили несколько операций с кадрами изображений, включая запись видео с помощью Python.

В этой части руководства мы собираемся применить те принципы и методы, которые мы изучили в предыдущем руководстве, для создания таймлапс-видеос помощью Python. Это будет хороший пост с точки зрения применения Open-CV. Ниже приведен хороший пример замедленного видео, взятого непосредственно с Youtube.

Начнем с импорта всех необходимых библиотек для создания такого видео.

import os
import numpy as np
import cv2
import time
import datetime
import glob

Здесь мы видим, что мы импортировали на 3 библиотеки больше, чем обычно, это Time, datetime и glob. как следует из самого названия, время и дата-время являются встроенными модулями Python для манипулирования датой/временем. Модуль glob в python находит все пути, соответствующие указанному шаблону, в соответствии с правилами, используемыми оболочкой Unix.

Затем мы определяем словарь Python, который содержит все возможные разрешения с их соответствующими высотами и ширинами, как показано в предыдущей части этой серии руководств в программе «Запись видео». Мы также определяем еще один словарь, который содержит значения для разных типов видео.

STD_DIM = {
    "480p" : (640, 480),
    "720p" : (1280, 720),
    "1080p" : (1920, 1080),
    "4k" : (3840, 2160),
}
VIDEO_TYPE = {
    'avi' : cv2.VideoWriter_fourcc(*'XVID'),
    'mp4' : cv2.VideoWriter_fourcc(*'XVID'),
    'mp4' : cv2.VideoWriter_fourcc(*'H264'),
}

Мы создаем различные методы для установки размеров видео, типа файла видео, а также установки разрешения видео.

def change_resolution(cap, width, height):
    cap.set(3, width)
    cap.set(4, height)
def set_dimensions(cap, res = '1080p'):
    width, height = STD_DIM['480p']
    if res in STD_DIM:
        width, height = STD_DIM[res]
    change_resolution(cap, width, height)
    return width, height
def set_videotype(filename):
    filename, ext = os.path.splitext(filename)
    if ext in VIDEO_TYPE:
        return VIDEO_TYPE[ext]
    return (VIDEO_TYPE['avi'])

Следующий фрагмент кода изменяет размер изображения, снятого в течение всего процесса. Он в основном устанавливает высоту и ширину всех изображений и возвращает изображения с измененным размером по указанному пути к файлу.

# source: https://stackoverflow.com/a/44659589
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
    dim = None
    (h, w) = image.shape[:2]
    if width is None and height is None:
        return image
    
    # CHECK TO SEE IF THE WIDTH IS NONE
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))
resized = cv2.resize(image, dim, interpolation = inter)
    return resized

Затем мы устанавливаем различные параметры, такие как путь сохранения, имя файла, FPS и т. д., и передаем все эти параметры для вывода файла потоковой передачи в средство записи видео cv2. Наконец, мы дважды проверяем наличие пути сохранения

cap = cv2.VideoCapture(0)
frames_per_seconds = 20
save_path='saved-media/video.avi'
my_res = '480p'
filename = 'video.avi'
dims = set_dimensions(cap, res = my_res)
video_type = set_videotype(filename = filename)
out = cv2.VideoWriter(save_path, video_type, frames_per_seconds, dims)
timelapse_img_dir = 'images/timelapse'
seconds_duration = 20
seconds_between_shots = .25
if not os.path.exists(timelapse_img_dir):
    os.mkdir(timelapse_img_dir)
if not os.path.exists(save_path):
    os.mkdir(save_path)

В следующем фрагменте кода мы сначала определяем текущее значение времени системы. Затем мы берем другое значение времени, которое находится в будущем, и запускаем цикл, который сравнивает оба этих значения. Внутри этого цикла изображения захватываются с интервалом в 1/4 секунды.

Обратите внимание, что мы также предоставляем имя каждого захваченного изображения, чтобы все было просто и упорядоченно.

now = datetime.datetime.now()
finish_time = now + datetime.timedelta(seconds=seconds_duration)
i = 0
while datetime.datetime.now() < finish_time:
    ret, frame = cap.read()
    filename = "{}/{}.jpg".format(timelapse_img_dir, i)
    # filename = f"{timelapse_img_dir}/{i}.jpg"
    i += 1
    cv2.imwrite(filename, frame)
    time.sleep(seconds_between_shots)
    if cv2.waitKey(20) & 0xFF == ord('q'):
        break

С помощью этой функции мы сшиваем все отснятые изображения в один видеофайл. Сортировка файлов изображений осуществляется по возрастанию времени создания файла изображения. Наконец, мы удаляем все файлы изображений после создания видео. Мы можем избежать этого шага и сохранить все изображения.

def images_to_video(out, image_dir, clear_images=True):
    image_list = glob.glob(image_dir + "/*.jpg")
    sorted_images = sorted(image_list, key=os.path.getmtime)
    for file in sorted_images:
        image_frame  = cv2.imread(file)
        out.write(image_frame)
    if clear_images:
        for file in image_list:
            os.remove(file)
images_to_video(out, timelapse_img_dir)
cap.release()
out.release()
cv2.destroyAllWindows()

Вуаля !! Мы создали наше первое покадровое видео, используя Open-CV и Python с помощью одной программы.

Это будет все для этого сообщения в блоге, ребята !!! Поздравляем, что зашли так далеко.

Вот некоторые полезные ресурсы и ссылки:

  1. Гитхаб-репозиторий
  2. Официальная документация
  3. Youtube-CFE
  4. Ютуб-Сентдекс

Быть в курсе. До скорого…!