본문 바로가기

OpenCV

OpenCV 공부 - 그림판 처럼 사각형 그리기

https://github.com/sunkyoo/opencv4cvml/blob/master/ch04/mouse/main.cpp

 

위의 링크에 있는 OpenCV를 이용한 선긋기를 응용해보았다.

 

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

using namespace cv;
using namespace std;

Mat img, tempImg;
Point ptOld;
void on_mouse(int event, int x, int y, int flags, void*);

int main(void)
{
	img = imread("lena.jpg");
	tempImg = img.clone();

	if (img.empty()) {
		cerr << "Image load failed!" << endl;
		return -1;
	}
	
	namedWindow("img");
	setMouseCallback("img", on_mouse);

	imshow("img", img);
	while (waitKey() != 27) {
		
	}
	

	return 0;
}

void on_mouse(int event, int x, int y, int flags, void*)
{
	switch (event) {
	case EVENT_LBUTTONDOWN:
		ptOld = Point(x, y);
		cout << "EVENT_LBUTTONDOWN: " << x << ", " << y << endl;
		break;
	case EVENT_LBUTTONUP:
		cout << "EVENT_LBUTTONUP: " << x << ", " << y << endl;

		rectangle(img, ptOld, Point(x, y), Scalar(0, 255, 255), 2);
		ptOld = Point(x, y);
		imshow("img", img);
		tempImg = img.clone();

		break;
	case EVENT_MOUSEMOVE:
		if (flags & EVENT_FLAG_LBUTTON) {

			rectangle(tempImg, ptOld, Point(x, y), Scalar(0, 255, 255), 2);
			imshow("img", tempImg);
			tempImg = img.clone();

		}
		break;
	default:
		break;
	}
}

 


 

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

using namespace cv;
using namespace std;

#define SAVED_MAX_SIZE 100

Mat img, tempImg, prevImg[SAVED_MAX_SIZE];
Point ptOld;
int inputKey, savedPrevIndex;
void on_mouse(int event, int x, int y, int flags, void*);

int main(void)
{
	img = imread("lena.jpg");
	tempImg = img.clone();
	prevImg[0] = img.clone();

	if (img.empty()) {
		cerr << "Image load failed!" << endl;
		return -1;
	}
	
	namedWindow("img");
	setMouseCallback("img", on_mouse);

	imshow("img", img);
	while (inputKey != 27) { 
		inputKey = waitKey();
		// ctrl + z (SUB)
		if (inputKey == 26) {
			if (savedPrevIndex > 0) {
				--savedPrevIndex;
				img = prevImg[savedPrevIndex].clone();
				imshow("img", img);
				cout << "ctrl + z 눌림 " << endl;
			}
		}
	}

	return 0;
}

void on_mouse(int event, int x, int y, int flags, void*)
{
	switch (event) {
	case EVENT_LBUTTONDOWN:
		ptOld = Point(x, y);
		break;
	case EVENT_LBUTTONUP:
		rectangle(img, ptOld, Point(x, y), Scalar(0, 255, 255), 2);
		ptOld = Point(x, y);
		imshow("img", img);
		tempImg = img.clone();

		// 뒤로가기 용도
		if (savedPrevIndex == SAVED_MAX_SIZE) {
			savedPrevIndex = 0;
		}
		++savedPrevIndex;
		prevImg[savedPrevIndex] = img.clone();

		cout << "savedPrevIndex : " << savedPrevIndex << endl;
		break;
	case EVENT_MOUSEMOVE:
		if (flags & EVENT_FLAG_LBUTTON) {

			/* 
			왼쪽 마우스를 누르는 동안에는 tempImg에 사각형을 그려주고,
			tempImg를 보여주고, 다시 그리기전인 img를 tempImg에 대입시켜줌.

			그니깐 tempImg에 사각형을 그리고 삭제하고 그리고 삭제하는 형식임
			마우스 클릭을 뗐을 경우에만 img에 사각형을 저장함
			*/
			rectangle(tempImg, ptOld, Point(x, y), Scalar(0, 255, 255), 2);
			imshow("img", tempImg);
			tempImg = img.clone();

		}
		break;
	default:
		break;
	}
}

 

까먹을까 봐 주석 + 100개 정도 저장되는 되감기 추가.

 

100개 이상 추가하면 다시 1부터 시작해서 문제가 생김,,

 

이 부분은 나중에 시간이 남으면 vector 같은 걸로 구현해보아야겠음.

 

+ ctrl + z를 어떻게 감지하는지 찾아보면서 값이 뭔가 봤는데 ctrl + z는 값이 26이다.

   아스키코드표에 26이 SUB으로 돼있어서 몰랐다. ctrl + a를 해보면 1부터 시작한다.

 

 

http://www.ktword.co.kr/abbr_view.php?m_temp1=12

 

ASCII [정보통신기술용어해설]

 

www.ktword.co.kr

SUB에 대한 설명은 위의 사이트를 참고하였음.