본문 바로가기
코딩/OpenCV

[C++ opencv] "이미지 복사" 개념 이해하기 .copyTo

by DIYver 2020. 7. 21.

본문 목표

코드 개발을 하다보면 연산 처리에 쓰이는 변수 값이 다른 변수값에 영향을 줘야 할 때가 많다.

 

영상처리에 있어서도 그러한데, 

쉽게 생각하다가는 큰 실수가 되고, 결과에 치명적인 문제를 안겨주게 된다.

 

주소값과 데이터 값을 통해 영상처리에서 이미지 변수를 어떻게 사용하여야 정확하게 사용하는 것인지 알아보자.

 

 

 

키워드 : .copyTo

 

 

 

 

 

알아볼 함수 원형

- 이미지 복사 ( .copyTo  )

	Mat img = imread("Lenna.png", 0);

	Mat img_copy;
	img.copyTo(img_copy);

 

src.copyTo( dst :  src 이미지를 dst 에 복사

 

  ○ src : 복사 시킬 원본 이미지

 

  ○ dst : 복사 되어 저장 될 이미지 변수

 

 

 

 

 

 

 

 

 

우선 .copyTo(  ) 가 왜 필요한지 알아보자.

 

 

일반적으로 C 언어를 다룬다면

 

int A = 10;

 

int B = A;

 

B = B+2;

 

위의 코드에서 A의 최종값은 뭐가 되겠는가?

 

10 과 12  둘 중에 선택하시라~~

 

 

 

 

답은 10 이다.

 

C 언어만 했었다면 당연한 결과이다.

 

int B 를 선언했고 값은 A의 10 을 입력했기 때문이다.

 

A 와 B 는 독립으로 작용한다.

 

 

 

그런데,

 

opencv 에서 이미지(Mat)는 포인터 값을 띈다.

 

따라서 이미지 변수는 선언되고나서는 하나의 주소값이라고 보면 된다.

 

Mat img1 = imread("Lenna.png"); 

 

Mat img2;

 

img2 = img1; 

 

이렇게 코드를 작성한 경우에는 img1의 데이터가 img2에 복사되는 것이 아니라,

img1 의 데이터 주소와 img2 의 데이터 주소가 같아지게 된다.

이게 뭔 뜻이냐면,

 

img2 를 수정하면, img1 도 똑같이 수정되게 된다.

 

그러니깐, img2 를 수정한게 아니라, img2 가 가리키고 있는 img1 을 수정하게 된 것이다.

 

아주 큰 실수를 저지른 것이다.

 

img1 은 남겨두고 img2 만 수정이 되어야 하는데

 

img1 이 수정된 것이니 말이다.

 

 

 

 

이것을 해결해 주는 것이 바로 .copyTo( ) 함수이다.

 

Mat img1 = imread("Lenna.png");

 

Mat img2;

 

img1.copyTo(img2);

 

위의 코드처럼 작성한 경우 

 

img1 과 img2 는 처음에는 같은 값을 띄지만

 

img2 에 연산을 하면 img2 에만 적용이 될 뿐, 원본인 img1 에는 영향을 끼치지 않는다.

 

 

 

메모리 값이 같지만,

 

메모리 주소가 달라서 독립적인 이미지가 되는 것이다.

 

C언어에서는 너무나도 당연하게 사용했던 = 는 "뒤에 오는 값을 앞의 변수에 저장함" 이라는 뜻으로 사용되었다면

 

OpenCV 에서 이미지 변수는 주소값을 나타내므로, "주소를 저장함" 이 되는 것이다.

 

매우 조심해야 하는 표현이다.

 

 

 

쉽게 말해서 OpenCV 에서는 ' = ' 표현을 아예 안 하는것이 낫다.

 

똑같은 이미지 변수를 중복적으로 사용해서 이득볼 것이 없으니 말이다.

 

 

 

 

 

 

 

 

코드 테스트 결과

- CODE

#include <opencv2/opencv.hpp>


using namespace cv;
using namespace std;


int main(int ac, char** av)
{
	Mat img = imread("Lenna.png", 0);

	Mat img_copy_1, img_copy_2;
	img.copyTo(img_copy_1);
	img_copy_2 = img;

	threshold(img_copy_2, img_copy_2, 150, 255, THRESH_BINARY);

	imshow("img_copy", img_copy_1);
	imshow("img", img);
	
	waitKey(0);
	return 0;
}

 

- RESULT

 

img_copy  의 출력 결과는 위와 같다.

 

원본 이미지인 Lenna 이미지가 그대로 출력 된 것을 볼 수 있다.

 

 

 

 

img_copy_2 를 임계값 처리를 하였고,

 

img 를 출력시켰는데, img_copy_2 에 연산을 한 결과가 나와버렸다.

 

앞에서 언급한 것과 같이 img_copy_2 가 단순히 ' = ' 연산으로 img 와 같다고 해버렸으므로

 

컴퓨터 메모리 상에서 이미 img 와 img_copy_2 는 같은 변수가 되어버린 것이다.

 

img_copy_2 를 손보게되면 그대로 img 에 적용이 되어버린다.

 

 

 

 

 

 

결론.

OpenCV 에서는 Mat 변수가 포인터를 뜻하므로, 데이터를 이용할 때에는 .copyTo( ) 를 이용해야 한다.

 

Mat 변수를 사용할 때에는 수식이 아니면 ' = ' 연산을 사용하지 않으면 문제 될 일이 없다.

 

 

 

 

 

 

 

 

 

 

 

도움이 되었거나, 문제가 있는 경우 댓글로 알려주세요~!

감사의 댓글은 작성자에게 큰 힘이 됩니다 ^^

댓글