반응형

 

 

간단히 Camshift  이론을 설명하고 webcam과 video 영상에 ROI를 지정하여 동작하도록 C++로 작성된 Camshift 예제 코드를 동작시켜 봅니다. 

 

 

 

 

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;


// 아래 줄을 주석처리하면 비디오 영상에 대해 동작 
//#define WEBCAM 



bool mouse_is_pressing = false;
int start_x, start_y, end_x, end_y;
int step = 0;
Mat img_color;
Rect roi;


void swap(int* v1, int* v2) {
	int temp = *v1;
	*v1 = *v2;
	*v2 = temp;
}


void mouse_callback(int event, int x, int y, int flags, void* userdata)
{
	Mat img_result = img_color.clone();


	if (event == EVENT_LBUTTONDOWN) {
		step = 1;

		mouse_is_pressing = true;
		start_x = x;
		start_y = y;



	}
	else if (event == EVENT_MOUSEMOVE) {

		if (mouse_is_pressing) {

			end_x = x;
			end_y = y;

			step = 2;
		}

	}
	else if (event == EVENT_LBUTTONUP) {

		mouse_is_pressing = false;

		end_x = x;
		end_y = y;

		step = 3;
	}
}


int main()
{
	Mat img_hsv, img_mask, img_ROI, mask_ROI;
	Mat objectHistogram;


	int channels[] = { 0 };
	int hsize[] = { 64};
	float range1[] = { 0, 180 };
	const float* histRange[] = { range1 };


#ifdef WEBCAM 
	VideoCapture cap(0);
#else
	VideoCapture cap("train.mp4");
#endif

	if (!cap.isOpened()) {
		cerr << "video 에러 - 카메라 또는 영상을 열 수 없습니다.\n";
		return -1;
	}

	namedWindow("Color", 1);
	setMouseCallback("Color", mouse_callback);

#ifndef WEBCAM
	Mat img_sceen;
	cap.read(img_sceen);
#endif


	while (1)
	{

#ifdef WEBCAM
		cap.read(img_color);
#else
		if (step == 4)
			cap.read(img_color);
		else
			img_sceen.copyTo(img_color);
#endif

		if (img_color.empty()) {
			cerr << "빈 영상이 캡쳐되었습니다.\n";
			break;
		}

		switch (step)
		{

		case 1:
			circle(img_color, Point(start_x, start_y), 10, Scalar(0, 255, 0), -1);

			break;

		case 2:
			rectangle(img_color, Point(start_x, start_y), Point(end_x, end_y), Scalar(0, 255, 0), 3);

			break;

		case 3:

			if (start_x > end_x) {
				swap(&start_x, &end_x);
				swap(&start_y, &end_y);
			}

			roi = Rect(start_x, start_y, end_x - start_x, end_y - start_y);
			cvtColor(img_color, img_hsv, COLOR_BGR2HSV);
			inRange(img_hsv, Scalar(0., 30., 30.), Scalar(180., 255., 255.), img_mask);

			img_ROI = Mat(img_hsv, roi);
			mask_ROI = Mat(img_mask, roi);

			imshow("ROI", img_ROI);

			calcHist(&img_ROI, 1, channels, mask_ROI, objectHistogram, 1, hsize, histRange);

			normalize(objectHistogram, objectHistogram, 0, 255, NORM_MINMAX);

			step++;

			break;

		case 4:

			Mat bp;
			cvtColor(img_color, img_hsv, COLOR_BGR2HSV);
			
			calcBackProject(&img_hsv, 1, channels, objectHistogram, bp, histRange);
			//calcBackProject(&img_hsv, 1, 0, objectHistogram, bp, histRange);
			//dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)
			bp &= img_mask;
			// Tracking
			//bitwise_and(bp, img_mask, bp);
			RotatedRect rot_rect = CamShift(bp, roi, TermCriteria(TermCriteria::EPS | TermCriteria::COUNT, 10, 1));

            if( roi.area() <= 1 )
            {
                int cols = bp.cols, rows = bp.rows, r = (MIN(cols, rows) + 5)/6;
                roi = Rect(roi.x - r, roi.y - r,
                                   roi.x + r, roi.y + r) &
                              Rect(0, 0, cols, rows);
            }

			ellipse( img_color, rot_rect, Scalar(0,0,255), 3, LINE_AA );
			Point2f vertices[4];
			rot_rect.points(vertices);
			for (int i = 0; i < 4; i++)
				line(img_color, vertices[i], vertices[(i+1)%4], Scalar(0,255,0), 2);

			break;

		}


		//if (step < 4)
		cout << step << endl;

		imshow("Color", img_color);


		if (waitKey(25) >= 0)
			break;
	}


	return 0;
}
반응형

포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

여러분의 응원으로 좋은 컨텐츠가 만들어집니다.
지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

유튜브 구독하기


제가 쓴 책도 한번 검토해보세요.

  1. 플래쉬 2020.01.13 15:18

    TermCriteria는 무엇이고 언제 사용되나요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.01.14 12:14 신고

      지정한 조건을 만족하면 종료하는 조건이라는데 정확한 의미는 모르겠네요..

      캠시프트를 계산할 필요가 없는 상황에 대한 조건을 얘기하는 듯합니다.

  2. 2020.04.25 03:56

    비밀댓글입니다

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.04.25 06:31 신고

      vertices에 사각형의 4꼭지점이 저장됩니다. 물체 중심을 구하여 출력하면 됩니다.

+ Recent posts