3 minute read



3.1.1 VideoCapture Class


동영상은 일련의 정지 영상을 압축해 파일로 저장한 형태. 이때 각각의 정지 영상을 frame이라고 한다.

따라서 동영상을 처리하기 위해선 frame을 추출한 후 각 frame에 영상 처리를 적용해야 한다.

VideoCapture 클래스를 이용해 카메라 또는 동영상 파일로부터 영상 frame을 받아올 수 있다.


먼저 생성자부터,

VideoCapture::VideoCapture(const String& filename, int apiPreference = CAP_ANY);
VideoCapture::VideoCapture(int index, int apiPreference = CAP_ANY);
---
 - filename : 동영상 파일 이름
 - apiPreference : 사용할 비디오 캡쳐 API 백엔드
 - idx : 카메라와 장치 사용 방식 지정 번호

전자는 동영상 파일 이름을 지정하여 VideoCapture 객체를 생성할 때 사용되고, 후자는 컴퓨터에 연결된 카메라 장치를 사용할 때 쓰인다.


filename 인자에는 동영상 파일 이름을 전달. 폴더의 절대 경로나 상대 경로를 추가해 지정할 수도 있고, 숫자로 구분되는 일련의 파일들을 불러올 수도 있다. 또는 비디오 스트림 URL을 지정할 수도 있다.


apiPreference 인자는 동영상을 불러 오는 방법을 지정한다. 여기에는 VideoCaptureAPIs 열거형 상수 중 하나를 지정하는데, 대부분 생락하거나 default 값인 CAP_ANY를 지정. 시스템이 알아서 선택해 준다.


카메라를 연결할 때 전달되는 정수 값 idx는 다음 형태로 구성된다.

idx = camera_id + domain_offset_id

컴퓨터에 카메라가 한 대 연결되어 있다면 이 카메라의 camera_id는 0. 두 대 이상의 경우 각 카메라는 0보다 같거나 큰 id를 갖는다. domain_offset_id는 카메라의 사용방식을 표현하는 정수 값. VideoCaptureAPIs 열거형 상수 중 하나를 사용한다. 보통 CAP_ANY에 해당되는 0을 사용하므로 idx 값은 대체로 camera_id와 같게 설정된다.


VideoCapture::open() - 영상 불러오기

동영상 파일을 불러오려면 VideoCapture::open() 멤버 함수를 호출해야 한다.

bool VideoCapture::open(const String& filename, int apiPreference = CAP_ANY);
bool VideoCapture::open(int index, int apiPreference = CAP_ANY);
---
 - return : 열기가 성공하면 true, 실패하면 false

또, 영상 파일 열기를 수행한 후 제대로 열렸는지 확인하는 것이 좋다.

bool VideoCapture::isOpened() const;
---
 - return : 영상 파일이 사용 가능하면 true, 아니면 false


VideoCapture::release() - 메모리 해제

영상 파일의 사용이 끝나면 사용하던 메모리를 해제해야 한다. VideoCapture 클래스의 소멸자에도 마찬가지로 메모리를 해제하는 코드가 들어 있다.

virtual void VideoCapture::release();


VideoCapture::read() - 프레임 받아오기

영상 파일을 제대로 열었으면 프레임을 받아올 수 있다. 한 프레임을 받아오기 위해서는 VideoCapture::read() 멤버 함수를 사용한다. 또는 >> 연산자 재정의를 이용해도 된다.

bool VideoCapture::read(OutputArray image);
VideoCapture& VideoCapture::operator >> (Mat& image);
---
 - image : 다음 비디오 프레임.  가져올 프레임이 없으면 비어 있는 행렬로 설정.
 - return : 프레임을 받아올  없으면 false.


VideoCapture::get() - 영상 정보 받아오기

double VideoCapture::get(int propId) const;
---
 - propId : 속성 ID, VideoCaptureProperties 열거형  하나 지정
 - return : 지정한 속성 . 얻을  없으면 0 반환

현재 열려 있는 카메라 장치나 영상 파일에서 정보를 받아올 때 사용한다. 열거형 상수에는 여러 가지가 있으므로 OpenCV 사이트 참조.


예를 들어 시스템 기본 카메라를 열어 기본 프레임 크기를 확인하려면,

VideoCapture cap(0);

int w = cvRound(cap.get(CAP_PROP_FRAME_WIDTH));
int h = cvRound(cap.get(CAP_PROP_FRAME_HEIGHT));

CAP_PROP_FRAME_WIDTHCAP_PROP_FRAME_HEIGHT는 각각 비디오 프레임의 가로와 세로 크기를 나타내는 VideoCaptureProperties 열거형 상수. cvRound() 함수는 OpenCV에서 제공하는 반올림 함수이다. VideoCapture::get() 함수는 파일 속성을 double형으로 반환하기 때문.


VideoCapture::set() - 영상 정보 설정

VideoCapture::get()과 반대로 영상 속성을 설정할 때 사용하는 함수.

void VideoCapture::set(int propIdm double value) const;
---
 - propId : 속성 ID, VideoCaptureProperties 열거형  하나 지정
 - value : 지정할 속성 
 - return : 지정이 가능하면 true, 아니면 false.


만약 video.mp4 파일을 열어서 50번째 프레임으로 이동하고 싶다면, 현재 프레임 위치를 반환하는 열거형 상수 CAP_PROP_POS_FRAMES를 사용하여

VideoCapture cap("videp.mp4");
cap.set(CAP_PROP_POS_FRAMES, 50);



3.1.2 카메라 입력 처리


다음 예시는 while문을 사용해 매 프레임을 화면에 출력.

Line 9 : VideoCapture 객체 생성. 여기서는 컴퓨터/노트북에 연결된 기본 카메라를 사용.
Line 11 ~ 15 : 카메라가 열렸는지 확인.
Line 17 ~ 18 : 프레임 가로와 세로 크기를 콘솔 창에 출력.
Line 20 : Mat 타입의 변수 선언.
Line 24 ~ 26 : 카메라 장치로부터 한 프레임을 받아 와 frame 변수에 저장.
Line 28 : frame에 저장된 프레임을 반전, inversed에 저장.
Line 30 ~ 31 : frame과 inversed에 저장된 정지 영상을 화면에 출력.
Line 33 ~ 34 : 10ms 동안 사용자의 입력을 대기. 만일 키보드 입력이 존재하고 그 입력이 27(Esc)이면 while 루프를 빠져나간다.
Line 36 : 모든 창을 닫는다.
Line 37 : main 함수가 종료되면 cap 변수가 소멸, 자동으로 카메라 장치를 닫기 위해 cap.release(); 함수가 알아서 호출된다. 따라서 이 코드에서는 생략.