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 의 데이터 주소가 같아지게 된다.
이게 무슨 의미나면,
img2를 수정하면, img1도 똑같이 수정된다.
다시 말해, img2를 수정한 것이 아니라, img2가 가리키고 있는 img1을 수정하게 된 것이다.
img1 은 남겨두고 img2 만 수정이 되어야 하는데, img1 이 수정되는 것이니 오류이다.
그래서, 이러한 현상을 해결하기 위해 copyTo() 함수를 사용하는 것이다.
Mat img1 = imread("deer.jpg");
Mat img2;
img1.copyTo(img2);
위와 같이 작성하면,
img1 과 img2 는 처음에는 같은 값을 가지지만
img2 에 연산을 하면 img2 에만 적용되고, img1 에는 영향을 끼치지 않는다.
메모리의 값은 같지만, 메모리 주소가 달라 독립적인 이미지가 되는 것이다.
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;
}
결과
img_copy 의 출력 결과는 위와 같다.
원본 이미지인 deer.jpg 이미지가 그대로 출력되었다.
img_copy_2 = img 연산 후, img_copy_2 에 임계값 처리를 했더니, 위와 같은 img_copy_2 결과를 확인할 수 있고, img 또한 같은 결과를 나타내는 것을 확인할 수 있다.
이것이 앞서 말한 ‘=’ 연산에 대한 오류 발생의 예시이다.
결론
opencv 에서는 Mat 변수가 포인터를 뜻하므로, 데이터를 사용할 때에는 copyTo() 를 이용해야 한다.
Mat 변수를 사용할 때에는 수식이 아니면 ‘=’ 연산을 사용하지 않는 것이 좋다.