OpenCV | Mat 클래스 정리

박나연·2021년 3월 16일
0

OpenCV

목록 보기
13/40

** 본내용은 OPENCV 4로 배우는 컴퓨터 비전과 머신러닝 도서 내용을 정리한 내용입니다.

📔 Mat 클래스

행렬을 표현하는 클래스로, 2차원 행렬뿐 아니라 고차원의 행렬또한 표현할 수 있다. 정수, 실수, 복소수 등으로 구성된 행렬 또는 벡터를 저장하거나, 그레이 스케일 또는 컬러 영상을 저장할 수도 있다. 2차원 영상데이터를 저장하고 처리하는 용도로 가장 많이 쓰이고 있다.

📔 Mat 클래스의 멤버변수

Mat::dims Mat행렬의 차원
Mat::rows 행개수(세로 픽셀 크기)
Mat::cols 열개수(가로 픽셀 크기)
Mat::size 3차원 이상 행렬의 크기 정보
Mat::data 행렬의 원소데이터가 저장된 메모리 공간을 가리키는 포인터형 멤버변수

📔 자료형 매크로 상수 표현법

Mat 클래스에서는 행렬이 어떤 자료형을 사용하는 지에 대한 정보를 깊이라고 부른다. 또한 Mat 행렬의 깊이를 다음과 같은 형식의 매크로 상수를 이용하여 표현한다.

CV_8U : uchar, usigned char
CV_8S : schar, signed char
CV_16U : ushort, unsigned short
CV_16S : signed short
CV_32S : int
CV_32F : float
CV_64F : double
CV_16F : float16_t

Mat행렬 원소를 구성할때, 각각의 값을 채널이라고 하는데, 여기서 여러개의 채널을 가질 수 있다. 예를 들어 그레이 스케일의 영상이라면 하나의 픽셀이 밝기정보 하나만 사용하므로 1채널 행렬이다. 트루컬러 영상은 하나의 픽셀이 파란색, 녹색, 빨간색 삼원색의 색상정보를 가지므로 3채널 행렬로 표현한다.

이를 CV_<bit-depth>{U|S|F}C(<number_of_channels>)
로 표현한다.

만약 B, G, R 세 색상 성분을 가지는 컬러영상은 unsigned char 자료형과 세개의 채널을 가지므로 CV_8UC3 타입이다.

📔 행렬의 생성과 초기화

Mat::Mat()

먼저 Mat img1; 로 행렬을 생성할 수 있다. img의 rows와 cols는 각각 0인 상태이다.
크기를 함께 설정하고자 하면Mat img1(int rows, int cols, int type); 로 행렬을 생성할 수 있다.
여기서 type은 위에서 정리한 매크로 상수를 전달하면 된다.

int 자료형 대신 size클래스를 사용하여 행렬의 크기를 나타낼 수도 있다.
Mat(Size size, int type); 으로 행렬을 선언하며,
예로 Mat img(Size(640,480), CV_8UC3); 로 작성 가능하다.

위 방식으로 행렬의 크기와 타입을 지정하여 행렬을 생성할 경우, 모든 원소는 임의의 값으로 채워지게 된다. 이 대신 모든 원소를 특정값으로 초기화하여 사용하고자 하면
Mat(int rows, int cols, int type, const Scalar& s); 를 통해 Scalar클래스를 이용해 줄 수 있는데,
이는 주로 영상의 픽셀 값을 표현하는 용도로 사용된다.

예를 들어 모든 픽셀값이 128로 초기화된 그레이스케일 영상은
Mat img(480, 640, CV_8UC1, Scalar(128));
모든 픽셀이 빨간색으로 설정된 컬러 영상은 Mat img(480,640, CV_8UC3, Scalar(0,0,255)); 로 표현가능하다.

Mat::zeros()

새로운 행렬을 생성할 때 모든 원소 값을 0으로 초기화하는 경우에 사용된다. 파라미터로 행과 열 또는 size, 그리고 type이 들어간다.

Mat::ones()

모든 원소가 1로 초기화된 행렬을 생성하는 경우에 사용된다.

Mat::eye()

단위 행렬을 생성할때 사용된다.

기존 행렬원소 값 사용

외부 메모리 공간을 활용하여 Mat 객체를 생성할 수 있다.

float data[] = {1, 2, 3, 4, 5, 6};
Mat mat(2,3, CV_32FC1, data);

Mat 행렬의 1행은 data배열의 1, 2, 3으로 채워지고, 2행은 4, 5, 6으로 채워지게 된다.

Mat_<float> mat_(2,3);
mat_ << 1, 2, 3, 4, 5, 6;
Mat mat = mat_;

위와 같이 << 연산자를 통해 지정할 수도 있다.

Mat::create()

비어있는 Mat 객체 또는 이미 생성된 Mat 객체에 새로운 행렬을 할당할때 사용한다. 새로 만들 행렬의 크기 또는 타입이 기존 행렬과 다른경우에 기존 메모리 공간을 해제한 후 새로운 행렬 데이터 저장을 위한 메모리 공간을 할당한다.

Mat::setTo()

행렬 원소에 설정할 값을 파라미터로 넘겨 설정할 수 있다.

📔 행렬의 복사

만약

Mat img1 = img2

혹은

Mat img3;
img3 = img1;

와 같은 얕은 복사를 하게 되면 픽셀 데이터만을 공유하게 된다.

복사본 영상을 새로 생성할때 메모리 공간을 새로 할당하여 픽셀 데이터 전체를 복사하고자 한다면 Mat::clone() 또는 Mat::copyTo() 함수를 사용한다.

Mat img = img1.clone();
Mat img;
img1.copyTo(img);

이를 통해 깊은 복사를 할 수 있다.

📔 부분 행렬 추출

Mat img2 = img1(Rect(100, 50, 10, 20);

img1 의 (100,50) 좌표에서 시작하여 10x20 사이즈의 부분을 추출하여 img2에 저장하는 코드이다.

Mat::rowRange()

지정한 범위의 행으로 구성된 행렬을 반환

Mat::colRange()

지정한 범위의 열로 구성된 행렬을 반환

Mat::row() , Mat::col()

1행 또는 1열짜리 행렬을 만들고자 할때 추출한 부분 행렬을 반환

📔 행렬 연산

+, -, *, / 연산기호를 사용하여 계산 가능하다.

Mat::mul()

같은 위치에 있는 원소끼리 곱셈 연산을 할때 사용한다.

Mat::inv()

행렬의 역행렬을 구할 때 사용한다.

Mat::t()

전치행렬을 구할 때 사용한다.

📔 크기 및 타입 변환

Mat::converTo()

행렬의 타입을 변경

img.converTo(img1f, CV_32FC1);

Mat::reshape()

행렬 원소 데이터를 같이 참조하는 행렬을 반환, 모양만 변경된 행렬을 반환한다.
새로운 행렬을 만드는 것이 아니다.

uchar data1[] = {1,2,3,4,5,6,7,8,9,10,11,12};
Mat mat1(3, 4, CV_8UC1, data1);
Mat mat2= mat1.reshape(0,1);

위 코드에서 mat2는 기존의 data1의 원소를 가져온 3x4 의 mat1 행렬에서 행의 수가 1인 행렬로 크기가 변경된다.

따라서 mat1 은 [1, 2, 3, 4 \ 5, 6, 7, 8 \ 9, 10, 11, 12] 이고,
mat2 는 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 이다.

Mat::resize()

행렬의 모양이 아닌 행 크기를 변경할때 사용한다.

mat1.resize(5, 100);

3x4크기에서 행의 개수가 5이고, 새롭게 추가된 행의 원소가 100으로 초기화된 행렬이 만들어 진다.

[1, 2, 3, 4 \ 5, 6, 7, 8 \ 9, 10, 11, 12 \ 100, 100, 100, 100 \ 100, 100, 100, 100]

Mat::push_back()

이미 존재하는 행렬에 맨마지막 행에 원소 데이터를 추가

Mat::pop_back()

맨 아래 행을 제거할때 사용

profile
Data Science / Computer Vision

0개의 댓글