목표
- openCV에서 메모리를 어떻게 관리하는지
- 영상의 각각의 픽셀을 어떻게 접근하는지
Memory Management
1. shallow copy
mat은 헤더 부분/ 데이터 부분으로 구성
헤더에 포함되있는 데이터의 주소값 부분만 copy됨
= 라는 기호를 등호로 사용해 copy
copyTo()라는 함수 이용. 특정한 경우에서는 shallow copy로 작용됨.
입력(source) matrix와 결과 matrix의 데이터타입과 크기가가 같을 경우 주소값만 복사되고, 그렇지 않은 경우에는 deep copy로 이루어진다.
m1 메트릭스가 데이터와, 데이터를 가르키는 주소값으로 구성되어있을 때, m1에 대한 shallow copy를 통해서 m2를 만들었다면 m2에 대한 데이터가 다시 만들어지는 것이 아니라 데이터를 가르키는 주소를 가리키는 방식으로 카피가 이루어진다.
2. deep copy
카피가 이루어지면 카피를 한 데이터를 다시 메모리 공간에 적게되는 식으로 카피하는것.
clone()을 이용 m2를 clone을 통해 만들어진다면 m2에 대한 메트릭스를 생성하고 난 후 m1에 대한 데이터를 m2로 카피하는 식으로 이루어진다.
int main() {
Mat m1 = (Mat_ < double >(3, 3)
<< 1, 2, 3, 4, 5, 6, 7, 8, 9);
Mat m_shallow = m1;
Mat m_deep = m1.clone();
cout << "m1 =\n" << m1 << endl << endl;
cout << "m_shallow =\n" << m_shallow << endl << endl;
cout << "m_deep =\n" << m_deep << endl << endl;
// Update m1
m1.at < double >(0, 0) = 100;
cout << "m1 =\n" << m1 << endl << endl;
cout << "m_shallow =\n" << m_shallow << endl << endl;
cout << "m_deep =\n" << m_deep << endl << endl;
waitKey(0);
}
영상에서 픽셀을 접근하는 방법
1. By using at operator
image.at<DATA_TYPE>(WANT_ROW, WANT_COL)
DATA_TYPE : 이미지를 고정하는 픽셀의 데이터 타입
WANT_ROW: 행. access하는 Y값
WANT_COL: 열. X값
느리다는 단점이 있다.
int main() {
Mat image, image_gray;
int value, value_B, value_G, value_R, channels;
image = imread("lena.png");
image_gray = imread("lena.png", 0);
//try both image & image_gray
//channels = image_gray.channels();
channels = image.channels();
//At operator
switch (channels) {
case 1: // chanels이 1인 경우
value = image.at<uchar>(50, 100); //(100,50)에 위치하는 픽셀값 읽어옴
cout << "value: " << value;
break;
case 3: // chanels이 3인 경우
value_B = image.at<Vec3b>(50, 100)[0];
value_G = image.at<Vec3b>(50, 100)[1];
value_R = image.at<Vec3b>(50, 100)[2];
cout << "value at (100,50): " << value_B
<< " " << value_G << " " << value_R << endl;
break;
}
waitKey(0);
}
2. By using pointer
at operator보다 빠르다.
int main() {
Mat image = imread("lena.png");
int value, value_B, value_G, value_R, channels;
channels = image.channels();
//Pointer
uchar* p;
p = image.ptr<uchar>(50); // image라는 matrix에 50번째 행에 해당하는 포인터를 접근
value_B = p[100 * channels + 0]; // 포인터의 위치에서 100번째 열.. 즉 (100,50)에 위치하는.
value_G = p[100 * channels + 1];
value_R = p[100 * channels + 2];
cout << "value at (100,50): " << value_B << " "
<< value_G << " " << value_R << endl;
waitKey(0);
}
3. By using data member function
포인터를 활용하는 방식과 유사함.
포인터는 행의 위치를 access를 한 다음에 진행한다는 점과 다르다
int main() {
Mat image;
int value, value_B, value_G, value_R, channels;
image = imread("lena.png");
channels = image.channels();
//Data member function
uchar* data = (uchar*)image.data;
value_B = data[(50 * image.cols + 100) * channels + 0];
value_G = data[(50 * image.cols + 100) * channels + 1];
value_R = data[(50 * image.cols + 100) * channels + 2];
cout << "value at (100,50): " << value_B << " "
<< value_G << " " << value_R << endl;
waitKey(0);
}
영상 내에 모든 픽셀값을 다 access하고 싶다면, 50,100에 해당하는 값을 적절히 바꿔간다거나,
모든 값을 print하고싶다면 값을 이중for문을 활용하는 방법이 있다.
4. By using MatIterator
보통 영상의 특정픽셀을 access하기보단 모든 픽셀의 값을 access하고 싶을 때 사용함
int main() {
Mat image = imread("lena.png");
Mat gray = imread("lena.png", 0);
int value, value_B, value_G, value_R;
// try both image & gray
int channels = image.channels();
MatIterator_ <uchar> it, end; // 1-channel 인 경우
MatIterator_<Vec3b> it3, end3; // 3-channel 인 경우
switch (channels) {
case 1: // 1-channel 일때 access하는 법
for (it = image.begin<uchar>(), image.end<uchar>(); it != end; ++it) {
// MatIterator의 위치(it)을 영상의 처음에 위치시키고, 영상의 끝에 도달할때까지 it값(위치)을 바꿔가면서 반복하는 for문
value = *it; // 각각의 픽셀값 받아옴
cout << "value: " << value << endl;
}
break;
case 3: // 3-channel 일때 access하는 법
for (it3 = image.begin<Vec3b>(), end3 = image.end<Vec3b>(); it3 != end3; ++it3) {
value_B = (*it3)[0];
value_G = (*it3)[1];
value_R = (*it3)[2];
cout << "B: " << value_B << ", G: " << value_G << ", R: " << value_R << endl;
}
break;
}
waitKey(0);
}
이 게시물은 한동대학교 황성수 교수님의 컴퓨터비전 강의를 공부하며 정리한 내용입니다.
'Computer Vision' 카테고리의 다른 글
[OpenCV] 히스토그램 평활화(Histogram Equalization) (0) | 2020.01.19 |
---|---|
[OpenCV] 밝기값 변환(Intensity Transformation) (0) | 2020.01.18 |
[OpenCV] Drawing 함수(Drawing Function) (0) | 2020.01.11 |
[OpenCV] Mat 연산자(Mat operator) (0) | 2020.01.11 |
[OpenCV] Open CV 기초 (0) | 2020.01.09 |