opencv c++ copyTo() 함수를 이용한 이미지 복사

  • 최초 작성일: 2022년 11월 10일(목)

목차

[TOC]


목표

개발 도중 연산 처리에 사용되는 변수 값이 다른 변수 값에 영향을 줄 때가 많다.

영상처리에서도 마찬가지인데,

작은 실수로 인해 큰 문제를 야기할 수 있다.

그러므로 주소값과 데이터 값을 통해 영상처리에서 이미지 변수를 어떻게 사용해야하는지 이해해보자.



실습

함수 원형

copyTo (이미지 복사)

    Mat img = imread("deer.jpg", 0);

    Mat img_copy;
    img.copyTo(img_copy);

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

  • src: 입력 이미지
  • dst: 출력 이미지


설명

먼저, copyTo()가 왜 필요한가?


일반적으로 C언어에서 설명하자면,

    int a = 10;
    int b = a;
    b++;

위의 코드에서 a의 최종값은 뭐가 될까요?

10? 11?


C언어를 했던 사람이라면 답이 10 이라는 것을 바로 알 수 있을 것이다.

int b를 따로 선언하여 a 값을 복사해두고 b값을 1 증가시켰기 때문이다.

따라서, a와 b는 독립적으로 작용한다.


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

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

    Mat image1 = imread("deer.jpg");
    Mat image2;
    image2 = image1;

위와 같이 코드를 작성한 경우, image1 의 데이터가 image2 에 복사되는 것이 아니라,

image1 의 데이터 주소와 image2 의 데이터 주소가 같아지게 된다.


image


이게 무슨 의미나면,

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

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

img1 은 남겨두고 img2 만 수정이 되어야 하는데, img1 이 수정되는 것이니 오류이다.


그래서, 이러한 현상을 해결하기 위해 copyTo() 함수를 사용하는 것이다.

    Mat img1 = imread("deer.jpg");
    Mat img2;
    img1.copyTo(img2);

위와 같이 작성하면,

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

img2 에 연산을 하면 img2 에만 적용되고, img1 에는 영향을 끼치지 않는다.


image


메모리의 값은 같지만, 메모리 주소가 달라 독립적인 이미지가 되는 것이다.

C언어에서는 ‘=’ 을 “뒤에 오는 값을 앞의 변수에 저장한다” 는 뜻으로 사용되었다면,

opencv 에서 이미지 변수는 주소값을 나타내므로, “주소를 저장한다” 가 되는 것이다.


그래서 opencv에서는 ‘=’ 표현을 사용하지 않는 것이 좋다.

똑같은 이미지 변수를 중복적으로 사용해서 좋을 것이 없다.


소스 코드

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main(int ac, char** av)
{
	Mat img = imread("deer.jpg", 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_copy_2", img_copy_2);
	imshow("img", img);

	waitKey(0);
	return 0;
}

결과

image

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

원본 이미지인 deer.jpg 이미지가 그대로 출력되었다.


image image

img_copy_2 = img 연산 후, img_copy_2 에 임계값 처리를 했더니, 위와 같은 img_copy_2 결과를 확인할 수 있고, img 또한 같은 결과를 나타내는 것을 확인할 수 있다.

이것이 앞서 말한 ‘=’ 연산에 대한 오류 발생의 예시이다.


결론

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

Mat 변수를 사용할 때에는 수식이 아니면 ‘=’ 연산을 사용하지 않는 것이 좋다.