QT 이미지 합성 , 관심영역 (ROI) 가져오기

lsh950223·2020년 5월 13일
1

안녕하세요 C++ 공부하고있는 대학생입니다.
이번에는 QT 이미지 합성하는것에 대해 정리해보려고 합니다.

우선 OpenCV를 통해 이미지를 불러오는 코드입니다.
(코드는 핵심만 적어두었습니다.)

	QString filePath = QFileDialog::getOpenFileName(this, "Open Image File", QDir::currentPath());
	QString fileName = filePath.section("/", -1);


	string stdstring;

	stdstring = filePath.toStdString();

	firstImage = imread(stdstring, IMREAD_UNCHANGED);
	if (firstImage.empty()) {
		messagebox.setText("none image");
		return;
	}
    
	imageCloneOrigin = firstImage.clone();
	//namedWindow("OriginImage");
	imshow("OriginImage", firstImage);
	setMouseCallback("OriginImage", onMouseEventOrigin, (void*)& firstImage);

QFileDialog를 통해서 창을띄워서 이미지를 가져 올 수 있습니다. 위치는, 실행되는파일의 현재 디렉토리를 기준으로 잡았습니다.
이미지를 불러오는데에 있어 실패했을시, 예외처리로 firstImage.empty()를 통하여 해 주었습니다.
QT 의 string을 cv의 string으로 변환하기위해서

	string stdstring;

	stdstring = filePath.toStdString();

을 사용하였습니다.

다음은 합성하고자 하는 이미지를 불러와서 이미지를 합성까지하는 코드입니다.

	QString filePath = QFileDialog::getOpenFileName(this, "Open Image File", QDir::currentPath());
	QString fileName = filePath.section("/", -1);

	string stdstring;

	stdstring = filePath.toStdString();

	secondImage = imread(stdstring, IMREAD_UNCHANGED);
	if (firstImage.empty() && secondImage.empty()) {
		messagebox.setText("none image");
		return;
	}
	imshow("PaintImage", secondImage);
	setMouseCallback("PaintImage", onMouseEventPaint, (void*)& secondImage);

	cv::addWeighted(firstImage, 0.8, secondImage, 0.6, 0, secondImageRst);
	imshow("result", secondImageRst);
	setMouseCallback("result", onMouseEvent, (void*)& secondImageRst);

	ROIImage = Mat::zeros(imageCloneOver.rows, imageCloneOver.cols, CV_8UC3);
	imwrite("over.jpg", imageCloneOver);

이미지 합성하는 함수는 addWeighted 함수를 사용해서 이미지를 합성하였습니다.
setMouseCallback 함수는 이미지위에 페인팅(그림)을 하기위한 함수입니다.

다음은 ROI(관심영역) 에 대한 함수입니다.

	for (int i = 0; i <secondImageRst.cols; i++) {
		for (int j = 0; j < secondImageRst.rows; j++) {
		
			if (imageCloneOver.at<Vec3b>(i, j)[0] != secondImageRst.at<Vec3b>(i, j)[0] &&
				imageCloneOver.at<Vec3b>(i, j)[1] != secondImageRst.at<Vec3b>(i, j)[1] &&
				imageCloneOver.at<Vec3b>(i, j)[2] != secondImageRst.at<Vec3b>(i, j)[2]) {
				ROIImage.at<Vec3b>(i, j)[0] = secondImageRst.at<Vec3b>(i, j)[0];
				ROIImage.at<Vec3b>(i, j)[1] = secondImageRst.at<Vec3b>(i, j)[1];
				ROIImage.at<Vec3b>(i, j)[2] = secondImageRst.at<Vec3b>(i, j)[2];
			}

		}

관심영역을 표시해서 나중에 기존 합성된 이미지에 덧칠하기위한 수단으로 ROIImage 라는 매트릭스 클래스를 0배열로 모두 초기화시킨다음에, 합성한 이미지의 기존에 바뀐배열 (페인팅에의한 값의 변환) 의 부분을 가지고, 모두 0으로 초기화 된 ROIImage mat class에 해당되는 위치에 같은 색상으로 입힌 과정입니다.

결과를 간단히 보여드리면,

이렇게 합성이 되고,

이런식으로 색을 칠해주고 roi를 해주면,

이런식으로 저장이됩니다.

이걸 해보게 된 이유는 예전에 opencv를 조금 다루어본적이 있어서, 기억이 되새기면서 그림판을 사용하면서 재밌어 보여서 한번 만들어보게 되었습니다. 생각보다 많이 어려웠고, 그림판이 정말 대단한 프로그램이구나 를 깨닫게 되었습니다. roi경우는 그림판의 채우기 기능이있는데, 이것을 따라해보려고 한번 해 보았습니다. 이미지 합성의경우는 과연 내 프로그램에서도 합성된 이미지에서 채우기 기능이 되는지 한번 보려고 해 보았습니다.

profile
C++ 공부하고있는 대학생입니다.

0개의 댓글