ویژگیهای رابط کاربری در OpenCV
شروع کار با ویدیوها
هدف#
- یادگیری خواندن، نمایش و ذخیره ویدیو.
- یادگیری دریافت ویدیو از دوربین و نمایش آن.
- با این توابع آشنا خواهید شد: ()cv.VideoCapture، ()cv.VideoWriter
دریافت ویدیو از دوربین#
اغلب اوقات، ما نیاز داریم جریان زنده تصویر (Live Stream) را از دوربین ضبط کنیم. کتابخانه OpenCV رابط بسیار سادهای برای این کار فراهم میکند. بیایید ویدیویی از دوربین دریافت کنیم (من از وبکم داخلی لپتاپم استفاده میکنم)، آن را به ویدیوی خاکستری (Grayscale) تبدیل کرده و نمایش دهیم؛ یک کار ساده برای شروع.
برای دریافت ویدیو، ابتدا باید یک شیء از نوع VideoCapture بسازید. آرگومان آن میتواند اندیس دستگاه (Device Index) یا نام فایل ویدیویی باشد. اندیس دستگاه فقط عددی است که مشخص میکند کدام دوربین مد نظر است. معمولاً یک دوربین متصل است (مانند مورد من)، بنابراین من به سادگی مقدار 0 (یا 1-) را ارسال میکنم. میتوانید با ارسال عدد 1 دوربین دوم را انتخاب کنید و به همین ترتیب. پس از آن، میتوانید فریم به فریم ویدیو را دریافت کنید. اما در انتها، فراموش نکنید که شیء دریافت تصویر را آزاد (release) کنید.
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# Our operations on the frame come here
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# Display the resulting frame
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q'):
break
# When everything done, release the capture
cap.release()
cv.destroyAllWindows()
متد ()cap.read یک مقدار بولی (True/False) برمیگرداند. اگر فریم به درستی خوانده شود، مقدار آن True خواهد بود. بنابراین میتوانید با بررسی این مقدار بازگشتی، رسیدن به پایان ویدیو را متوجه شوید.
گاهی اوقات، ممکن است cap دریافت ویدیو را به درستی مقداردهی اولیه نکرده باشد. در این حالت، این کد خطا نشان میدهد. میتوانید با متد ()cap.isOpened بررسی کنید که آیا مقداردهی شده است یا خیر. اگر مقدار True باشد، همه چیز آماده است؛ در غیر این صورت آن را با استفاده از ()cap.open باز کنید.
همچنین میتوانید با استفاده از متد (cap.get(propId به برخی ویژگیهای این ویدیو دسترسی داشته باشید، که در آن propId عددی بین 0 تا 18 است. هر عدد نشاندهنده یکی از ویژگیهای ویدیو است (در صورتی که برای آن ویدیو قابل اعمال باشد). جزئیات کامل را میتوان در اینجا مشاهده کرد: ()cv::VideoCapture::get. برخی از این مقادیر را میتوان با استفاده از (cap.set(propId, value تغییر داد. مقدار value همان مقدار جدیدی است که میخواهید تنظیم کنید.
به عنوان مثال، میتوانم عرض و ارتفاع فریم را با (cap.get(cv.CAP_PROP_FRAME_WIDTH و (cap.get(cv.CAP_PROP_FRAME_HEIGHT بررسی کنم. به طور پیشفرض مقدار 640x480 را به من میدهد. اما من میخواهم آن را به 320x240 تغییر دهم. کافی است از ret = cap.set(cv.CAP_PROP_FRAME_WIDTH,320) و ret = cap.set(cv.CAP_PROP_FRAME_HEIGHT,240) استفاده کنید.
پخش ویدیو از فایل#
پخش ویدیو از یک فایل مشابه دریافت آن از دوربین است، تنها کافی است اندیس دوربین را به نام فایل ویدیو تغییر دهید. همچنین هنگام نمایش فریم، زمان مناسبی را برای ()cv.waitKey در نظر بگیرید. اگر زمان بیش از حد کم باشد، ویدیو بسیار سریع پخش خواهد شد و اگر بیش از حد زیاد باشد، ویدیو با سرعت آهسته حرکت خواهد کرد (در واقع، به همین روش میتوانید ویدیوها را در حالت اسلوموشن نمایش دهید). مقدار ۲۵ میلیثانیه در شرایط عادی مناسب خواهد بود.
import numpy as np
import cv2 as cv
cap = cv.VideoCapture('vtest.avi')
while cap.isOpened():
ret, frame = cap.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q'):
break
cap.release()
cv.destroyAllWindows()
ذخیره یک ویدیو#
بنابراین ما یک ویدیو را ضبط کرده و آن را فریم به فریم پردازش میکنیم، و میخواهیم آن ویدیو را ذخیره کنیم. برای تصاویر، این کار بسیار ساده است: فقط از ()cv.imwrite استفاده میکنیم. در اینجا، کمی کار بیشتری لازم است.
این بار ما یک شیء VideoWriter ایجاد میکنیم. باید نام فایل خروجی را مشخص کنیم (مثلاً: output.avi). سپس باید کد FourCC را تعیین کنیم (جزئیات در پاراگراف بعدی). سپس تعداد فریم در ثانیه (fps) و اندازه فریم باید ارسال شوند. و آخرین مورد فلگ isColor است. اگر True باشد، انکودر انتظار فریم رنگی دارد، در غیر این صورت با فریم در مقیاس خاکستری کار میکند.
کد FourCC یک شناسه ۴ بایتی است که برای مشخص کردن کدک ویدیویی استفاده میشود. فهرست کدهای موجود را میتوان در fourcc.org یافت. این کد وابسته به پلتفرم است. کدکهای زیر برای من به خوبی کار میکنند:
- در فدورا: DIVX, XVID, MJPG, X264, WMV1, WMV2. (کدک XVID ترجیح داده میشود. کدک MJPG منجر به حجم زیاد ویدیو میشود. کدک X264 حجم بسیار پایینی تولید میکند)
- در ویندوز: DIVX (موارد بیشتر باید تست و افزوده شوند)
- در OSX (مک): MJPG (.mp4), DIVX (.avi), X264 (.mkv).
کد FourCC به صورت ('cv.VideoWriter_fourcc('M','J','P','G یا
(*'cv.VideoWriter_fourcc(*'MJPG برای MJPG ارسال میشود.
کد زیر تصویر را از دوربین دریافت کرده، هر فریم را در راستای عمودی معکوس (flip) میکند و ویدیو را ذخیره مینماید.
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
# Get camera frame resolution
frame_width = int(cap.get(cv.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))
# Define the codec and create VideoWriter object
fourcc = cv.VideoWriter_fourcc(*'XVID')
out = cv.VideoWriter('output.avi', fourcc, 20.0, (frame_width, frame_height))
while cap.isOpened():
ret, frame = cap.read()
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
frame = cv.flip(frame, 0)
# write the flipped frame
out.write(frame)
cv.imshow('frame', frame)
if cv.waitKey(1) == ord('q'):
break
# Release everything if job is finished
cap.release()
out.release()
cv.destroyAllWindows()