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를 수정했을 때 원본 이미지도 수정되기 때문에 조심해야 한다.