مدیریت فایل های ویدیویی

Handling Video File

گاهی اوقات لازم است دنباله ای از تصاویر را از یک فایل ویدئویی استاندارد، مانند فایل های .avi و .mov بخوانید.

در زمینه علمی، معمولاً بهتر است از این قالب ها به نفع فهرست ساده تصاویر یا TIF چند بعدی اجتناب کنید. فرمت های ویدئویی به سختی می توانند تکه تکه خوانده شوند، معمولاً از دسترسی تصادفی به فریم و یا متا داده های تحقیقاتی پشتیبانی نمی کنند و در صورت پیکربندی دقیق از فشرده سازی ضعیف استفاده می کنند. اما فایل های ویدئویی در حال استفاده گسترده هستند و به اشتراک گذاری آن ها آسان است، بنابراین راحت است که در صورت لزوم بتوانید آنها را بخوانید و بنویسید.

ابزارهای خواندن فایل های ویدئویی در سهولت نصب و استفاده، استفاده از دیسک و حافظه و سازگاری بین پلتفرم های مختلف متفاوت است. این یک راهنمای عملی از این ابزارها است.

راه حل: ویدئو را به دنباله تصویر تبدیل کنید

برای راه حل یکبار، ساده ترین و مطمئن ترین راه این است که فیلم را به مجموعه ای از فایل های تصویری با شماره متوالی تبدیل کنید که اغلب دنباله تصویر نامیده می شود. سپس فایل های تصاویر را می توان در skimage.io.imread_collection در ImageCollection خواند. تبدیل ویدئو به فریم را می توان به راحتی در ImageJ، یک برنامه چند پلتفرمی، مبتنی بر GUI از جامعه تصویربرداری زیستی یا FFmpeg، یک ابزار خط فرمان قدرتمند برای دستکاری فایل های ویدئویی، انجام داد.

در FFmpeg، دستور زیر یک فایل تصویری از هر فریم در یک ویدیو ایجاد می کند. فایل ها با پنج رقم شماره گذاری شده و در سمت چپ صفر قرار داده شده است.

ffmpeg -i "video.mov" -f image2 "video-frame%05d.png"

اطلاعات بیشتر در آموزش FFmpeg در مورد توالی های تصویر موجود است.

ایجاد یک دنباله تصویر دارای معایبی است: می تواند بزرگ و سخت باشد و ایجاد آنها ممکن است مدتی طول بکشد. به طور کلی ترجیح داده می شود مستقیماً با فایل ویدئویی اصلی کار کرد. برای یک راه حل مستقیم تر، باید FFmpeg یا LibAV را از پایتون اجرا کنیم تا فریم های ویدیو را بخوانیم. FFmpeg و LibAV دو پروژه بزرگ open source هستند که ویدیو را از انواع گسترده فرمت های مورد استفاده در طبیعت رمزگشایی می کنند. روش های مختلفی برای استفاده از آن ها در پایتون وجود دارد. متاسفانه هر کدام معایبی دارند.

کار با PyAV

در واقع PyAV از کتابخانه های FFmpeg (یا LibAV) برای خواندن داده های تصویر مستقیماً از فایل ویدئویی استفاده می کند. با استفاده از پیوندهای Cython آن ها را فراخوانی می کند، بنابراین بسیار سریع است.

import av
v = av.open('path/to/video.mov')

در واقع API PyAV نحوه ذخیره فریم ها در یک فایل ویدئویی را نشان می دهد.

for packet in container.demux():
    for frame in packet.decode():
        if frame.type == 'video':
            img = frame.to_image()  # PIL/Pillow image
            arr = np.asarray(img)  # numpy array
            # Do something!

افزودن دسترسی تصادفی به PyAV

کلاس Video در PIMS را PyAV فراخوانی می کند و قابلیت های بیشتری را برای حل یک مشکل رایج در برنامه های علمی، دسترسی به فیلم با شماره فریم، اضافه می کند. فرمت های فایل های ویدئویی طوری طراحی شده اند که به صورت تقریبی، در زمان جستجو شوند و از ابزار کارآمدی برای جستجوی تعداد فریم خاص پشتیبانی نمی کنند. PIMS با رمزگشایی کل ویدئو و ایجاد یک فهرست داخلی از محتویات که از نمایه سازی بر اساس فریم پشتیبانی می کند، این قابلیت مفقود شده را اضافه می کند.

import pims
v = pims.Video('path/to/video.mov')
v[-1]  # a 2D numpy array representing the last frame

کار با MoviePy

در واقع Moviepy FFmpeg را از طریق یک فرایند فرعی فراخوانی می کند، فیلم رمزگشایی شده از FFmpeg را به RAM پیوند می دهد و آن را می خواند. این رویکرد ساده است، اما می تواند شکننده باشد و برای فیلم های بزرگتر از RAM موجود قابل اجرا نیست. در صورت نصب FFmpeg روی همه سیستم عامل ها کار می کند.

از آنجا که به کتابخانه های اصلی FFmpeg پیوند ندارد، نصب آن آسان تر است اما تقریباً نصف آن سریعتر است.

from moviepy.editor import VideoFileClip
myclip = VideoFileClip("some_video.avi")

کار با Imageio

در واقع Imageio رویکرد مشابه MoviePy را دارد. همچنین از طیف گسترده ای از فرمت های دیگر فایل تصویری نیز پشتیبانی می کند.

import imageio
filename = '/tmp/file.mp4'
vid = imageio.get_reader(filename,  'ffmpeg')

for num, image in vid.iter_data():
    print(image.mean())

metadata = vid.get_meta_data()

کار با OpenCV

در نهایت، راه حل دیگر کلاس VideoReader در OpenCV است که دارای اتصالات FFmpeg است. اگر به دلایل دیگر به OpenCV نیاز دارید، این ممکن است بهترین روش باشد.

این بخش به پایان رسید اگر سوالی در ارتباط با هر یک از بخش های بالا دارید در بخش issueها از من بپرسید.

Last updated