-
OpenCV VideoCapture classOpenCV/OpenCV_C++ 2023. 12. 13. 22:06
OpenCV에서 카메라와 동영상으로부터 프레임(Frame)을 받아오는 작업을 VidepCapture class 하나로 처리할 수 있다.
카메라와 동영상을 여는 작업이 수행되면, 매 프레임을 받아오는 작업을 수행한다.
- 카메라 열기
VideoCapture::VideoCapture(int index, int apiPreference = CAP_ANY); bool VideoCapture::open(int index, int apiPreference = CAP_ANY);
- index: 사용할 캡쳐 장치의 ID (camera_id, domain_offset_id). 시스템 기본 카메라는 0으로 지정됨.(여러대의 카메라는 0부터 순서대로 지정)
- apiPreference: 선호하는 카메라 처리 방법을 지정.
- return: VideoCapture 생성자는 VideoCapture 객체를 반환. VideoCapture::open()함수는 작업이 성공하면 True, 실패하면 False를 반환.
- 동영상 파일 열기
VideoCapture::VideoCapture(const String& filename, int apiPreference = CAP_ANY); bool VideoCapture::open(const String& filename, int apiPreference = CAP_ANY);
- filename: 동영상 파일 이름, 정지 영상 시퀀스, 비디오 스트림 URL 등을 받음.
- apiPreference: 선호하는 동영상 처리 방법을 지정
- return: VideoCapture 생성자는 VideoCapture 객체를 반환. VideoCapture::open()함수는 작업이 성공하면 True, 실패하면 False를 반환.
- 현재 프레임 받아오기
bool VideoCapture::read(OutputArray image); VideoCapture& VideoCapture::operator >> (Mat& image);
- image: 현재 프레임. 만약 현재 프레임을 받지 못하면 빈 영상으로 설정.
- return: VideoCapture::read()함수는 작업이 성공하면 True, 실패하면 False를 반환.
- 참고: '>>' 연산자오버로딩은 내부에서 read() 함수를 재호출하는 래퍼(wrapper) 함수이다.
그럼 직접 코드를 작성하며 살펴보자.
#include <iostream> #include "opencv2/opencv.hpp" int main() { cv::VideoCapture cap; cap.open(0); // 혹은 아래와 같이 사용 가능 // cv::VideoCapture cap(0); // 동영상 처리시 아래와 같이 사용 // cv::VideoCapture cap; // cap.open("동영상 경로"); // 카메라를 열지 못한 경우 아래의 오류를 출력하고 프로그램 종료. if (!cap.isOpened()) { std::cerr << "Camera open failed!" << std::endl; return -1; } int w = cvRound(cap.get(cv::CAP_PROP_FRAME_WIDTH)); // 영상의 Width 출력 int h = cvRound(cap.get(cv::CAP_PROP_FRAME_HEIGHT)); // 영상의 Height 출력 std::cout << "width: " << w << std::endl; std::cout << "height: " << h << std::endl; cv::Mat frame, edge; while (true) { cap >> frame; // VideoCapture 객체로부터 한 프레임을 받아 frame 변수에 저장. // 영상을 제대로 받지 않으면 Empty frame을 출력하고 while문 탈출 if (frame.empty()) { std::cerr << "Empty frame!" << std::endl; break; } Canny(frame, edge, 50, 150); // 50 ~ 150의 threshold를 갖는 Canny 이미지를 edge에 담음. imshow("frame", frame); imshow("edge", edge); // waitKey(1)은 1ms동안 wait if (cv::waitKey(1) == 27) // ESC를 누르면 while문 탈출 break; } cap.release(); cv::destroyAllWindows(); return 0; }
결과
여기서 FPS라는 용어가 나오는데 FPS는 Frame Per Second의 약자이다.
FPS는 1초에 몇장의 Frame을 받아올 수 있는지 알려준다.
만약 1초를 1000ms로 나타내고 1초에 30장을 처리한다고 하면 1장당 약 33ms를 처리한다.
- 카메라와 동영상 속성 값 참조와 설정
double VideoCapture::get(int propId) const; bool VideoCapture::set(int propId, double value);
- value: 속성 값. 필요한 경우 정수형으로 형변환하여 사용이 가능하다.
- propId: 속성 플래그(cv::VideoCaptureProperties or Additional flags for video I/O API backends의 상수에서 선택가능)
cv::VideoCaptureProperties 설명 CAP_PROP_FRAME_WIDTH 프레임 가로 크기 CAP_PROP_FRAME_HEIGHT 프레임 세로 크기 CAP_PROP_FPS 초당 프레임 수 CAP_PROP_FRAME_COUNT 비디오 파일의 총 프레임 수 CAP_PROP_POS_FRAMES 현재 프레임 번호 CAP_PROP_EXPOSURE 노출 기타등등 기타등등 이 명령어들로 내 현재 영상의 값을 받거나 해상도의 경우 정의를 해줄 수 있다.
cap.set(cv::CAP_PROP_FRAME_WIDTH, 1280); cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);
- VideoWriter
동영상 파일로 저장할 수 있는 VideoWriter class가 있다.
VideoWriter::VideoWriter(const String& filename, int fourcc, double fps, Size frameSize, bool isColor = true); bool VideoWriter::open(const String& filename, int fourcc, double fps, Size frameSize, bool isColor = true);
- filename: 저장할 동영상 파일 이름
- fourcc: 압축 방식을 나타내는 4개의 문자. VideoWriter::fourcc() 함수로 생성. (https://fourcc.org/codecs.php)
VideoWriter::fourcc('D', 'I', 'V', 'X') DIVX MPEG-4 코덱 VideoWriter::fourcc('X', 'V'. 'I'. 'D') XVID MPEG-4 코덱 VideoWriter::fourcc('X', '2', '6', '4') H.264/AVC 코덱 VideoWriter::fourcc('M', 'J', 'P', 'G') Motion-JPEG 코덱 - fps: 초당 프레임 수
- frameSize: 비디오 프레임 크기
- isColor: 컬러 동영상 플래그. false로 지정하면 그레이스케일.
한번 edge영상을 저장하는 코드를 간단히 작성해보자.
#include <iostream> #include "opencv2/opencv.hpp" int main() { cv::VideoCapture cap(0); if (!cap.isOpened()) { std::cerr << "Camera open failed!" << std::endl; return -1; } int fourcc = cv::VideoWriter::fourcc('X', 'V', 'I', 'D'); // XVID MPEG-4 코덱사용 double fps = 30; cv::Size sz((int)cap.get(cv::CAP_PROP_FRAME_WIDTH), (int)cap.get(cv::CAP_PROP_FRAME_HEIGHT)); std::cout << "FPS = " << fps << std::endl; std::cout << "Size = " << sz << std::endl; cv::VideoWriter output("output.avi", fourcc, fps, sz); // 저장파일명 및 설정 if (!output.isOpened()) { std::cerr << "output.avi open failed!" << std::endl; return -1; } int delay = cvRound(1000 / fps); cv::Mat frame, edge; while (true) { cap >> frame; if (frame.empty()) break; Canny(frame, edge, 50, 150); cvtColor(edge, edge, cv::COLOR_GRAY2BGR); // edge영상은 grayscale 이므로 bgr로 변환이 필요. output << edge; imshow("edge", edge); if (cv::waitKey(delay) == 27) break; } std::cout << "output.avi file is created!!!" << std::endl; output.release(); cap.release(); cv::destroyAllWindows(); return 0; }
결과
다음과 같이 영상이 생성됨을 볼 수 있다.
'OpenCV > OpenCV_C++' 카테고리의 다른 글
OpenCV 유용한 함수 (2) 2023.12.21 OpenCV Draw & Event (0) 2023.12.14 OpenCV Mat class 기초 사용법 (0) 2023.12.12 OpenCV 주요 클래스 (1) 2023.11.27 OpenCV 기초 및 편하게 사용하기 (2) 2023.11.26