OpenCV

OpenCV - Mat 메모리 공유 vs 복사

donie 2021. 1. 18. 23:36

1. Mat 기본 예제

Mat함수

Scalar( B, G, R ) 이다.

 

코드 ex1.cpp

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat M0(100, 200, CV_8UC1, Scalar(50));
	Mat M1(100, 200, CV_8UC1, Scalar(100));
	Mat M2(100, 200, CV_8UC1, Scalar(150));
	Mat M3(Size(200, 100), CV_8UC3, Scalar(0,0,255));
	Mat M4(Size(200, 100), CV_8UC3, Scalar(255,0,0));
	Mat M5(Size(200, 100), CV_8UC3, Scalar(255,0,255));

	imshow("M0", M0);
	imshow("M1", M1);
	imshow("M2", M2);
	imshow("M3", M3);
	imshow("M4", M4);
	imshow("M5", M5);
	
	waitKey(0);
	destroyAllWindows();
	return 0;
}

 

컴파일

g++ -o ex1 ex1.cpp `pkg-config opencv-3.3.1-dev --cflags --libs`

 

실행

./ex1

 

실행 결과

 

Mat.type()

data type을 리턴한다. 상수값이 리턴됨. 

 

Mat.depth()

하나의 픽셀이 몇 바이트인지 리턴.

 

Mat.at<datatype>(row, col)[channel]

row, col위치에 해당하는 픽셀값의 몇 번째 채널을 볼 것인지.

 

2. Mat 메모리 공유 vs 복사

※ 주의할 점

Mat dst = src;
Mat dst(src);

위 코드는 둘 다 shallow copy로, 실제 body는 안 만들어지고 header 정보만 복사된다.

따라서 원본 이미지와 메모리를 공유하기 때문에 위험하다.

 

기억장소를 추가 할당 + 이미지 데이터 복사, 즉 deep copy를 하고 싶으면

dst = src.clone();
src.copyTo(dst2);

 

소스코드 ex2.cpp

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat img = imread("lena.jpg", IMREAD_COLOR);
	
	if (img.empty())
		return 0;
	
	Mat M1, M3, M4;
	// shallow copy
	M1 = img;
	Mat M2(img);
	// deep copy
	M3 = img.clone();
	img.copyTo(M4);
	
	// change img
	Mat sub(img, Rect(30,60,20,40));
	sub = Scalar(0,255,0);
	
	imshow("M1", M1);
	imshow("M2", M2);
	imshow("M3", M3);
	imshow("M4", M4);
	
	waitKey(0);
	destroyAllWindows();
	
	return 0;
}

 

컴파일 명령어

g++ -o ex2 ex2.cpp `pkg-config opencv-3.3.1-dev --cflags --libs`

 

실행 명령어

./ex2

 

실행 결과

위 결과에서 볼 수 있듯이, 1,2방법으로 복사를 하면 원본 이미지와 메모리를 공유한다.

원본 이미지를 수정했을 때 1,2가 바뀌기도 하지만, 반대로 1,2를 수정했을 때 원본 이미지도 수정되기 때문에 조심해야 한다.