Giới thiệu
Thông thường khi làm việc với OpenCV, đầu vào là hình ảnh hoặc các tập hình ảnh. Vậy làm sao lấy được các frame trong video thông qua camera hay đọc frame từ file video?
Khá hay là thư viện OpenCV có cung cấp 1 class là VideoCapture có chức năng capturing video từ camera, đọc video từ file video hay từ 1 tập các hình ảnh.
Lấy video frame từ camera với VideoCapture
//
// main.cpp
// OpenCVTest
//
// Created by NguyenNghia on 11/11/16.
// Copyright © 2016 nguyennghia. All rights reserved.
//
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, const char * argv[])
{
// class represent for capturing video from camera and reading video file or image sequences
VideoCapture videoCapture;
Mat videoFrame;
// open camera
videoCapture.open(0);
namedWindow("VideoCapture", WINDOW_AUTOSIZE);
// check open camera open sucessed or failed
if(!videoCapture.isOpened())
{
cout << "Can't open camera" << endl;
}
else
{
while (true)
{
//read video frame from camera and show in windows
videoCapture.read(videoFrame);
imshow("VideoCapture", videoFrame);
if(waitKey(30) >= 0) break;
}
}
return 0;
}Các bước làm việc với VideoCapture trong OpenCV
Bước 1: Khởi tạo đối tượng VideoCapture và mở camera với tham số truyền vào là flags với các giá trị dưới đây, được định nghĩa trong OpenCV. Nếu máy tính có 1 camera thì hãy truyền vào 0 để OpenCV tự nhận dạng và mở đúng camera đó.
// Camera API
enum
{
CAP_ANY = 0, // autodetect
CAP_VFW = 200, // platform native
CAP_V4L = 200,
CAP_V4L2 = CAP_V4L,
CAP_FIREWARE = 300, // IEEE 1394 drivers
CAP_FIREWIRE = CAP_FIREWARE,
CAP_IEEE1394 = CAP_FIREWARE,
CAP_DC1394 = CAP_FIREWARE,
CAP_CMU1394 = CAP_FIREWARE,
CAP_QT = 500, // QuickTime
CAP_UNICAP = 600, // Unicap drivers
CAP_DSHOW = 700, // DirectShow (via videoInput)
CAP_PVAPI = 800, // PvAPI, Prosilica GigE SDK
CAP_OPENNI = 900, // OpenNI (for Kinect)
CAP_OPENNI_ASUS = 910, // OpenNI (for Asus Xtion)
CAP_ANDROID = 1000, // Android - not used
CAP_XIAPI = 1100, // XIMEA Camera API
CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API)
CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK
CAP_MSMF = 1400, // Microsoft Media Foundation (via videoInput)
CAP_WINRT = 1410, // Microsoft Windows Runtime using Media Foundation
CAP_INTELPERC = 1500, // Intel Perceptual Computing SDK
CAP_OPENNI2 = 1600, // OpenNI2 (for Kinect)
CAP_OPENNI2_ASUS = 1610, // OpenNI2 (for Asus Xtion and Occipital Structure sensors)
CAP_GPHOTO2 = 1700, // gPhoto2 connection
CAP_GSTREAMER = 1800, // GStreamer
CAP_FFMPEG = 1900, // FFMPEG
CAP_IMAGES = 2000 // OpenCV Image Sequence (e.g. img_%02d.jpg)
};Bước 2: Kiểm tra đã mở camera thành công hay chưa thông qua phương thức isOpen.
Bước 3: Nếu mở video thành công thì dùng vòng lặp vô tận để lấy video frame từ camera thông qua phương thức read() để nhận video frame thông qua thể hiện của class Mat (cấu trúc dữ liệu lưu trữ dữ liệu hình ảnh trong OpenCV). Từ video frame này có thể áp dụng các thuật toán để xử lý theo ý muốn.
Bước 4. Kết thúc chương trình.
Đọc video từ file với VideoCapture
//
// main.cpp
// OpenCVTest
//
// Created by NguyenNghia on 11/11/16.
// Copyright © 2016 nguyennghia. All rights reserved.
//
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
#define INPUT "input_video.mp4"
int main(int argc, const char * argv[])
{
VideoCapture videoCapture;
Mat videoFrame;
videoCapture.open(INPUT);
namedWindow("VideoCapture", WINDOW_AUTOSIZE);
if(!videoCapture.isOpened())
{
cout << "Can't open camera" << endl;
}
else
{
while (true)
{
videoCapture.read(videoFrame);
imshow("VideoCapture", videoFrame);
if(waitKey(30) >= 0) break;
}
}
return 0;
}Cũng giống với việc lấy video frame từ camera nhưng với cách đọc video frame, truyền đối số vào phương thức open là tên của file video.
Các phương thức lấy ra các thuộc tính của video frame
Phương thứ get của VideoCapture cho phép lấy ra các thuộc tính của video frame.
double VideoCapture::get(int propId)
Với propID là các giá trị dưới đây (được giữ nguyên thủy phần chút thích bằng tiếng Anh).
CV_CAP_PROP_POS_MSECCurrent position of the video file in milliseconds or video capture timestamp.CV_CAP_PROP_POS_FRAMES0-based index of the frame to be decoded/captured next.CV_CAP_PROP_POS_AVI_RATIORelative position of the video file: 0 – start of the film, 1 – end of the film.CV_CAP_PROP_FRAME_WIDTHWidth of the frames in the video stream.CV_CAP_PROP_FRAME_HEIGHTHeight of the frames in the video stream.CV_CAP_PROP_FPSFrame rate.CV_CAP_PROP_FOURCC4-character code of codec.CV_CAP_PROP_FRAME_COUNTNumber of frames in the video file.CV_CAP_PROP_FORMATFormat of the Mat objects returned by retrieve() .CV_CAP_PROP_MODEBackend-specific value indicating the current capture mode.CV_CAP_PROP_BRIGHTNESSBrightness of the image (only for cameras).CV_CAP_PROP_CONTRASTContrast of the image (only for cameras).CV_CAP_PROP_SATURATIONSaturation of the image (only for cameras).CV_CAP_PROP_HUEHue of the image (only for cameras).CV_CAP_PROP_GAINGain of the image (only for cameras).CV_CAP_PROP_EXPOSUREExposure (only for cameras).CV_CAP_PROP_CONVERT_RGBBoolean flags indicating whether images should be converted to RGB.CV_CAP_PROP_WHITE_BALANCE_UThe U value of the whitebalance setting (note: only supported by DC1394 v 2.x backend currently).CV_CAP_PROP_WHITE_BALANCE_VThe V value of the whitebalance setting (note: only supported by DC1394 v 2.x backend currently).CV_CAP_PROP_RECTIFICATIONRectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently).CV_CAP_PROP_ISO_SPEEDThe ISO speed of the camera (note: only supported by DC1394 v 2.x backend currently).CV_CAP_PROP_BUFFERSIZEAmount of frames stored in internal buffer memory (note: only supported by DC1394 v 2.x backend currently).
Viết lại chương trình trên như sau:
//
// main.cpp
// OpenCVTest
//
// Created by NguyenNghia on 11/11/16.
// Copyright © 2016 nguyennghia. All rights reserved.
//
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
#define INPUT "input_video.mp4"
int main(int argc, const char * argv[])
{
VideoCapture videoCapture;
Mat videoFrame;
videoCapture.open(INPUT);
namedWindow("VideoCapture", WINDOW_AUTOSIZE);
if(!videoCapture.isOpened())
{
cout << "Can't open camera" << endl;
}
else
{
while (true)
{
videoCapture.read(videoFrame);
imshow("VideoCapture", videoFrame);
cout << "FPS: " << videoCapture.get(CV_CAP_PROP_FPS) << endl;
cout << "FRAME_COUNT: " << videoCapture.get(CV_CAP_PROP_FRAME_COUNT) << endl;
cout << "FRAME_WIDTH: " << videoCapture.get(CV_CAP_PROP_FRAME_WIDTH) << endl;
cout << "FRAME_HEIGHT: " <<videoCapture.get(CV_CAP_PROP_FRAME_HEIGHT) << endl;
cout << "CODEC: " << videoCapture.get(CV_CAP_PROP_FOURCC) << endl;
cout << "AVI_RATION: " <<videoCapture.get(CV_CAP_PROP_POS_AVI_RATIO) << endl;
if(waitKey(30) >= 0) break;
}
}
return 0;
}Và 1 đoạn log xuất ra như dưới đây:
FPS: 29.97 FRAME_COUNT: 10444.1 FRAME_WIDTH: 1152 FRAME_HEIGHT: 720 CODEC: 0 AVI_RATION: 0.00612786 FPS: 29.97 FRAME_COUNT: 10444.1 FRAME_WIDTH: 1152 FRAME_HEIGHT: 720 CODEC: 0 AVI_RATION: 0.0062236 FPS: 29.97 FRAME_COUNT: 10444.1 FRAME_WIDTH: 1152 FRAME_HEIGHT: 720 CODEC: 0 AVI_RATION: 0.00631935 FPS: 29.97 FRAME_COUNT: 10444.1 FRAME_WIDTH: 1152 FRAME_HEIGHT: 720 CODEC: 0 AVI_RATION: 0.0064151 FPS: 29.97 FRAME_COUNT: 10444.1 FRAME_WIDTH: 1152 FRAME_HEIGHT: 720 CODEC: 0 AVI_RATION: 0.00651085 FPS: 29.97 FRAME_COUNT: 10444.1 FRAME_WIDTH: 1152 FRAME_HEIGHT: 720 CODEC: 0 AVI_RATION: 0.0066066
* Ngoài ra 1 thư viện xử lý video rất phổ biến khác, được sử dụng rất nhiều là FFmpeg, có thể tìm hiểu thông qua trang chủ: https://ffmpeg.org/