본문 목표
코드 개발을 하다보면 연산 처리에 쓰이는 변수 값이 다른 변수값에 영향을 줘야 할 때가 많다.
영상처리에 있어서도 그러한데,
쉽게 생각하다가는 큰 실수가 되고, 결과에 치명적인 문제를 안겨주게 된다.
주소값과 데이터 값을 통해 영상처리에서 이미지 변수를 어떻게 사용하여야 정확하게 사용하는 것인지 알아보자.
키워드 : .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 변수를 사용할 때에는 수식이 아니면 ' = ' 연산을 사용하지 않으면 문제 될 일이 없다.
도움이 되었거나, 문제가 있는 경우 댓글로 알려주세요~!
감사의 댓글은 작성자에게 큰 힘이 됩니다 ^^
'코딩 > OpenCV' 카테고리의 다른 글
[C++ opencv] 이미지에 사각형 그리기, rectangle( ) (0) | 2020.07.21 |
---|---|
[C++ opencv] 이미지에 선, 직선 그리기 (0) | 2020.07.21 |
[C++ opencv] High pass filter (HPF)로 윤곽선 검출, edge detection (1) | 2020.07.15 |
[C++ opencv] low pass filters (LPF)로 노이즈 제거하기 (0) | 2020.07.15 |
[C++ opencv] 이미지 사이즈 변경하기, resize( ) 함수 사용법 (0) | 2020.07.14 |
댓글