본문 바로가기
OpenCV

OpenCV , C++ ] 카메라와 동영상 파일 다루기

by eteo 2022. 8. 16.

예제 코드 출처 : OpenCV 4로 배우는 컴퓨터 비전과 머신러닝

 

 

 

1. 웹캠으로부터 정지 영상 프레임을 두 번 받아와 각기 다른 창에 띄우는 예제

void CaptureVideo() {

	VideoCapture cap(0);
	// OpenCV에서는 VideoCapture라는 클래스를 이용해 카메라 또는 동영상 파일로부터 정지 영상 프레임을 받아 올 수 있음
	// 동영상 파일을 불러올 때는 "파일 이름" 을 인자로 넣고, 파일이 다른 폴더에 있으면 절대경로 또는 상대경로 추가함
	// 카메라 장치를 열 때에는 카메라 장치 id 번호를 정수 값으로 전달. 0으로 해서 안되면 1, 2 시도

	if (!cap.isOpened()) {	// 예외처리
		cerr << "Camera open failed!" << endl;
		return;
	}

	int w = cvRound(cap.get(CAP_PROP_FRAME_WIDTH));
	int h = cvRound(cap.get(CAP_PROP_FRAME_HEIGHT));
	// get() 함수로 카메라 또는 동영상 파일로부터 여러 정보를 받아 올 수 있음. 매개변수는 열거형 상수 Properties 가 들어감

	cout << "Width : " << w << endl;
	cout << "Height : " << h << endl;

	Mat frame1, frame2;
	cap >> frame1;		// 1st frame
	cap.read(frame2);	// 2nd frame
	// >>() 연산자 재정의 또는 read() 함수를 사용하여 카메라 또는 동영상 파일로부터 한 프레임의 정지 영상을 받아옴
	// 내부적으로 read()함수는 grab() 과 retrieve() 함수를 호출하는 형태

	imshow("img1", frame1);
	imshow("img2", frame2);

	waitKey(0); // 매개변수가 0이면 무한 대기
}

 

 

 

 

 

 

 

 

 

 

 

2. 웹캠 실시간 불러오기

void cameraIn() {

	VideoCapture cap(0);

	if (!cap.isOpened()) {
		cerr << "Camera open failed!" << endl;
		return;
	}

	Mat frame, inversed;

	while (true) {

		cap >> frame;
		if (frame.empty())
			continue;
		inversed = ~frame;	// 반전

		//line(frame, Point(50, 50), Point(200, 50), Scalar(0, 0, 255));

		imshow("frame", frame);
		imshow("inversed", inversed);

		if (waitKey(10) == 27)	// 10ms 동안 키보드 입력 대기, 키보드 입력고 있고 해당 키값이 ESC 면 루프 나감
			break;
	}
	destroyAllWindows();

	// cameraIn() 함수 종료 시 소멸자 호출되며 자동으로 cap 변수 소멸
}

 

 

 

 

 

 

 

 

 

 

 

 

3. 동영상 파일을 읽어서 출력

void vedioIn() {

	VideoCapture cap("stopwatch.avi");
	// 동영상의 오디오는 출력하지 않음

	if (!cap.isOpened()) {
		cerr << "Camera open failed!" << endl;
		return;
	}

	cout << "Frame width: " << cvRound(cap.get(CAP_PROP_FRAME_WIDTH)) << endl;
	cout << "Frame height: " << cvRound(cap.get(CAP_PROP_FRAME_HEIGHT)) << endl;
	cout << "Frame count: " << cvRound(cap.get(CAP_PROP_FRAME_COUNT)) << endl;	// 동영상파일 전체 프레임 수

	double fps = cap.get(CAP_PROP_FPS);
	cout << "FPS: " << fps << endl;
	int delay = cvRound(1000 / fps);
	// 동영상 파일의 FPS값을 이용하여 매 프레임 사이의 시간간격을 ms 단위로 구함
	// 초당 30프레임을 재생하는 동영상의 경우 딜레이는 33ms 가 됨


	Mat frame, inversed;
	while (true) {
		cap >> frame;
		if (frame.empty())
			continue;
		inversed = ~frame;	// 반전

		imshow("frame", frame);
		imshow("inversed", inversed);

		if (waitKey(delay) == 27)	// ESC key delay 값을 10ms으로 줄이면 영상이 빨라짐
			break;
	}
	destroyAllWindows();

}

 

 

 

 

 

 

 

 

 

 

 

 

4. 웹캠 영상을 동영상 파일로 저장하기

void camera_in_video_out() {

	VideoCapture cap(0);

	if (!cap.isOpened()) {
		cerr << "Camera open failed!" << endl;
		return;
	}

	int w = cvRound(cap.get(CAP_PROP_FRAME_WIDTH));
	int h = cvRound(cap.get(CAP_PROP_FRAME_HEIGHT));
	//double fps = cap.get(CAP_PROP_FPS);		// 카메라 종류에 따라 지원하지 않는 경우도 있음. 그런 경우 30 대입
	double fps = 30;
	int delay = cvRound(1000 / fps);

	int fourcc = VideoWriter::fourcc('D', 'I', 'V', 'X');
	// VideoWriter 생성자 또는 open()함수의 두 번째 인자인 fourcc는 4-문자 코드(four character code)의 약자로
	// 동영상 파일의 코덱을 표현하는 네 개의 문자를 묶어서 fourcc를 생성함

	VideoWriter outputVideo("output.avi", fourcc, fps, Size(w, h));
	// 저장할 동영상 파일 생성

	if (!outputVideo.isOpened()) {
		cerr << "File open Failed!" << endl;
		return;
	}

	Mat frame, inversed;
	while (true) {
		cap >> frame;
		if (frame.empty())
			continue;

		inversed = ~frame;	// 반전

		outputVideo << inversed;
		// 열려 있는 동영상 파일에 새 프레임을 추가하기 위해서는 <<() 연산자 재정의 또는 VideoWriter::write() 함수를 사용
		// 다만 새로 추가하는 프레임 크기는 동영상 파일을 생성할 때 지정한 프레임 크기와 같아야함
		// 또한 컬러로 설정된 동영상 파일에 그레이스케일 영상을 추가하면 정상적으로 저장되지 않으므로 주의

		imshow("frame", frame);
		imshow("inversed", inversed);

		if (waitKey(delay) == 27)
			break;
	}
	destroyAllWindows();

}