본문 바로가기
코딩/OpenCV

[C++ opencv] 동영상 불러오기 VideoCapture()

by DIYver 2020. 6. 24.

본문 목표

 

OpenCV 를 사용하다 보면, 웹캠으로 실시간 영상을 받아와서 영상처리를 해야할 때도 있지만, 저장되어 있는 동영상 파일에서도 영상처리를 필요로 할 때가 많다.

이번에는 동영상 파일에서 프레임을 추출해 연산처리를 할 수 있는 방법을 알아본다.

 

키워드 : VideoCapture

 

 

 

 

 

 

 

알아볼 함수 원형

- 동영상 캡쳐 또는 불러오기 ( VideoCapture )

#include <opencv2/opencv.hpp>

...
VideoCapture cap("test.mp4");
	
if (!cap.isOpened())
{
	printf("Can't open the video");
	return -1;
}

...

 

VideoCapture '변수 이름'( "동영상 이름" ) : '변수 이름'은 "동영상 이름"에 해당하는 동영상 화면(frame)을 읽어온다.

 

이 전에 웹캠으로부터 영상정보를 받아오는 방법과 매우 유사한 것을 알 수 있다.

 

사실 거의 같다고 보면 된다.

 

이 경우에는 카메라를 사용하는 것이 아니라, 컴퓨터에 저장되어 있는 동영상을 불러오는 것이 된다.

 

동영상 이름에는 확장자까지 포함이 되어야 정상적으로 불러올 수 있음에 주의한다.

 

동영상을 여러개 불러온다고 한다면 VideoCapture 변수를 여러개 사용하면 된다.

 

대신에 그만큼 연산처리 속도는 느려지게 될 것이다.

 

 

비디오 이름이 잘 못 되었거나, 없는 파일일 수 있다.

 

따라서 이에대한 안전장치를 해두는 것이 좋다.

 

코드에서도 나와있듯이 isOpened( ) 함수를 이용하여 동영상 파일이 제대로 읽혔는지 확인하는 습관을 가지자.

 

이왕 복붙 (복사 & 붙여넣기) 해서 사용할 꺼면 굳이 지우지 말고 그대로 사용하기를 권장한다.

 

 

 

 

 

 

 

 

코드 테스트 결과

- CODE

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main(int ac, char** av) {

	VideoCapture cap("test.mp4");
	//cap.set(CV_CAP_PROP_FRAME_WIDTH, 1920);
	//cap.set(CV_CAP_PROP_FRAME_HEIGHT, 1080);

	if (!cap.isOpened())
	{
		printf("Can't open the camera");
		return -1;
	}

	Mat img;

	while (1)
	{
		cap >> img;
        
		if (img.empty())
		{
			printf("empty image");
			return 0;
		}
        
		imshow("camera img", img);

		if (waitKey(25) == 27)
			break;
	}


	return 0;
}

 

- RESULT

 

동영상 파일이 정상적으로 OpenCV에서 읽혀서 출력이 되는 것을 확인할 수 있었다.

 

코드를 그대로 복사해서 사용할 경우 제대로 출력이 안 될 수 있다. 

 

예를 들어, 속도가 너무 빠르거나 느리게 재생될 수 있다.

 

그 이유는 동영상의 해상도와, fps(초당 프레임), 컴퓨터 연산속도 이 모든것이 복합적으로 작용하기 때문이다.

 

그래서 이렇게 저장되어 있는 동영상을 실제 속도로 처리를 하려면 frame 을 받아오는 속도 조절이 필요하다.

 

가장 쉽게 하는 방법은 

위와같이 waitKey( 'delay time' ) 함수를 적절히 사용하는 것이다.

 

waitKey 함수는 delay 기능을 하는데, 지연 시간을 잘 조정하면 실제 동영상 재생 속도와 근접하게 frame을 불러올 수 있다.

 

필자가 사용한 영상과 해상도, 컴퓨터 연산처리 속도에는 23~25 정도가 실제와 비슷하게 재생되었다.

 

하지만 완전 똑같을 수는 없었다...

 

여러가지 시도를 해봤지만, 제일 현실적인 방법은 waitKey() 를 통한 재생속도 조절이었다.

 

나중에는 연산처리를 하게되면 자연스럽게 느려지게 되어있으므로, 크게 신경 쓸 필요는 없다.

 

 

 

 

 

그리고 단순히 동영상만 재생한다면 상관없겠지만,

 

오류가 나지 않고 계속 실행되어야 하는 경우 동영상이 끝나면 불러오는 작업도 끝내야 오류가 나지 않는다.

 

영상은 다 끝났는데, 계속 무한반복문에서 없는 이미지 불러오라고 하면 당연히 오류가 나게 되고

 

코드 전체가 멈추게 된다.

 

그래서 필요한 장치가

img.empty( )  함수를 사용한 동영상 정보의 유무 판단이다.

 

동영상 변수 cap 에서 img에 이미지 정보를 전달했을 때,

 

img 에 이미지 정보가 없으면 코드를 종료시킴으로써 오류가 발생하는 것을 방지해준다.

 

만약 위와 같은 장치 없이 imshow( ) 를 통해서 이미지를 출력하라고 하면

 

이미지가 없는데 어떻게 이미지를 출력하냐고 오류를 내뱉는다.

 

물론 코드가 전체적으로 중단된다...

 

따라서 나중에 사용자 정의함수를 만들어 사용한다면 꼭 이런 안전장치를 만들어놓고 사용하기를 바란다.

 

 

 

도움이 되었거나, 문제가 있는 경우 댓글로 알려주세요~!

감사의 댓글은 작성자에게 큰 힘이 됩니다 ^^

댓글