Python

[OpenCV C++] 웹캠 크롭하기

담다디다 2020. 11. 11. 21:11

최근 손가락 검출 및 이벤트 맵핑 프로젝트를 진행했었는데 그 일부분을 정리해 하나씩 올려보고자 한다.

 

아래 코드는 피부색을 검출하기 전 단계로 피부색 검출 시 얼굴과 손이 동시에 검출되는 것을 막기 위해 ROI(Region Of Interest | 관심 영역)로 설정한 부분을 따로 크롭하여 분리한다.

이 방법은 쉽고 단순한 방법이며, Feature 기반 API를 활용하지 않고 사용할 수 있는 방법이다.

 

전체 코드는 맨 아래에 기술해두었다.


Mat frame, crop;	//frame : 웹캠 프레임, crop : 웹캠 프레임에서 크롭된 이미지
VideoCapture cap;	//웹캠

int deviceID = 0;	//디폴트 카메라
int apiID = CAP_ANY;	//디폴트 API

cap.open(deviceID, apiID);	//웹캠 열기

//웹캠 오류 확인
if (!cap.isOpened()) {
	cerr << "ERROR! Unable to open the camera\n";
	return -1;
}

우선 VideoCapture 객체를 선언한다.

open함수의 첫번째 인자로 0을 넣게 되면 디폴트로 설정된 카메라를 사용하게 된다.

 

 

VideoCapture는 웹캠뿐 아니라 비디오 파일도 불러올 수 있다.

 

VideoCapture cap("비디오파일.mp4") 으로 입력하면 exe파일 실행 시 같은 폴더 내에 보관된 지정된 이름의 비디오 파일을 불러오게 된다.(mp4는 예시이다) 

main함수 인자로 argc, argv를 입력하고 비디오파일 이름 대신 argv[1]을 넣게 되면 cmd창에 두 번째 인자로 입력한 비디오 파일을 불러온다. cmd창의 두 번째 인자를 경로와 함께 입력하면 꼭 exe파일과 같은 폴더 내에 있지 않아도 불러올 수 있다.

 

if문은 웹캠이 열리지 않았을 경우 예외처리를 해주는 부분인데, 예외처리를 해주는 편이 좋다.

 

 


Rect rect(350, 100, 200, 200);	//크롭 영역

//웹캠 출력
for (;;) {
	cap.read(frame);

	if (frame.empty()) {
		cerr << "ERROR! blank frame grabbed\n";
		break;
	}

	//좌우반전
	flip(frame, frame, 1);

	//영상 크롭
	crop = frame(rect);
    
	//크롭되는 영역 표시
	rectangle(frame, Point(350, 100), Point(550, 300), CV_RGB(255, 0, 0));

	imshow("Live", frame);
	imshow("crop", crop);

	//아무 키나 누르면 종료
	if (waitKey(5) >= 0) {
		break;
	}
}

웹캠을 포함해서 모든 비디오는 낱개의 이미지가 초당 몇장씩 연결해 보여주는 것으로 이해하면 된다.

for(;;) 또는 while(1)문으로 무한 루프를 돌리는 이유가 이 때문이다.

 

화면은 웹캠을 통해 받은 이미지를 Mat 변수에 따로 저장하여 imshow로 보여주면 된다.

 

역시 프레임을 받지 못했을 경우를 예외처리 해준다.

 

웹캠을 그냥 켜게 되면 좌우가 반대로 보이는데, 이 부분이 불편하니 우리가 일반적으로 거울을 보는 것처럼 보기 위해 좌우반전을 해준다.

 

Rect객체는 인자로

(왼쪽 위 x포인트, 왼쪽 위 y포인트, 사각형 가로 크기, 사각형 세로 크기)

이렇게 넣어주면 된다.

 

rectangle 함수는 ROI 영역을 명시적으로 보여주기 위해 그려준다. 이 영역 안에 손을 올리면 된다.

 

아무 키나 누르면 무한루프를 빠져나오도록 구현했다.

 

 

 

전체 코드


#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main() {
	Mat frame, crop;	//frame : 웹캠 프레임, crop : 웹캠 프레임에서 크롭된 프레임
	VideoCapture cap;	//웹캠	
	Rect rect(350, 100, 200, 200);	//크롭 영역

	
	int deviceID = 0;		//디폴트 카메라
	int apiID = CAP_ANY;	//디폴트 API

	//웹캠 열기
	cap.open(deviceID, apiID);

	namedWindow("Live");
	namedWindow("crop");

	//웹캠 오류 확인
	if (!cap.isOpened()) {
		cerr << "ERROR! Unable to open the camera\n";
		return -1;
	}

	//웹캠 출력
	for (;;) {
		cap.read(frame);

		if (frame.empty()) {
			cerr << "ERROR! blank frame grabbed\n";
			break;
		}

		//좌우반전
		flip(frame, frame, 1);


		//영상 크롭
		crop = frame(rect);

		//크롭되는 영역 표시
		rectangle(frame, Point(350, 100), Point(550, 300), CV_RGB(255, 0, 0));

		imshow("Live", frame);
		imshow("crop", crop);

		//아무 키나 누르면 종료
		if (waitKey(5) >= 0) {
			break;
		}
	}

	return 0;

}

 

 

 

 

혹시나 틀린 부분이 있다면 지적 환영합니다:)

응원 댓글은 작성자에게 큰 힘이 됩니다!

반응형