컴퓨터 비전 study

OpenCV Mat 클래스(1)

CIRI 2020. 2. 14. 11:49

1.1 Mat 클래스

: OpenCV에서 가장 많이 사용하며, 고차원 행렬을 표현할 수 있고 한 개 이상의 채널을 가질 수 있다.

정수,실수,복소수 등으로 구성된 행렬 또는 벡터 / 그레이 스케일 / 컬러 영상 / 벡터필드, 포인트 클라우드, 텐서, 히스토그램 등의 정보 를 저장할 수 있다. 

> But, 2차원 영상 데이터를 저장하고 처리하는 용도로 가장 많이 쓰인다. 

 

Mat::dims                > Mat 행렬의 차원 (영상과 같은 2차원 행렬의 dims = 2)

  >int dims;

Mat::rows , Mat::cols   > 2차원 행렬의 크기(rows 는 행 개수=세로 픽셀크기, cols 는 열 개수=가로 픽셀크기)

                             > 2차원 행렬에서만 의미있는 값을 가지며, 3차원 이상의 행렬에서는 -1이 저장된다.

                                3차원 이상의 행렬의 크기는 Mat::size 변수를 이용하여 참조할 수 있다.

  > int rows, cols;      /   > MatSize size;

Mat::data                 > 행렬의 원소 데이터가 저장되어 있는 메모리 공간을 가리키는 포인터형 멤버 변수

                                행렬에 아무것도 저장되어 있지 않다면 0(NULL)값을 가진다.

  > uchar* data;

 

* 이외의 멤버 변수들은 활용성이 높지 않으므로 생략

* OpenCV는 unsigned char, signed char, unsigned short, signed short, int, float, double 자료형을 사용하는 Mat 행렬 지원

 

schar 부호있는 1바이트 정수

uchar 부호없는 1바이트 정수 (=unsigned char를 재정의한 이름)

short 부호있는 2바이트 정수(C/C++기본자료형)

ushort 부호없는 2바이트 정수

int 부호있는 4바이트 정수(C/C++기본자료형)

uint 부호없는 4바이트 정수

int64 부호있는 8바이트 정수

uint64 부호없는 8바이트 정수

float64_t (부호있는)2바이트 실수

float (부호있는)4바이트 실수(C/C++기본자료형)

double (부호있는)8바이트 실수(C/C++기본자료형)

 

깊이(Depth) : 행렬이 어떤 자료형을 사용하는지에 대한 정보

>CV_<bit-depth>{U|S|F}

U는 부호없는 정수형, S는 부호있는 정수형, F는 부동 소수형 의미

ex. #define CV_8U   0 -> uchar, unsigned char  <unsigned char 자료형을 사용한다는 의미

    #define CV_32F   5  -> float  >행렬의 원소를 float 자료형으로 표현하려면 깊이가 CV_32F인 행렬을 사용해야한다. 

 

채널(channel) : Mat 행렬 원소를 구성하는 각각의 값    > 하나의 채널을 가질 수도, 여러 개의 채널을 가질 수도 있다.

 하나의 행렬을 구성하는 각 채널은 모두 같은 자료형을 사용해야 한다.

 ex. 그레이 스케일 영상 > 하나의 픽셀이 밝기정보 하나만 사용 > 1채널 행렬

      트루컬러 영상 > 하나의 픽셀이 파란색(B), 녹색(G), 빨간색(R) 세 개의 색상 정보를 가지고 있으므로 3채널 행렬

 

타입(type) : Mat 행렬의 깊이 정보와 채널 수 정보를 합친 것

>CV_<bit-depth>{U|S|F}C(<number of channels>)

 ex. CV_8UC1  - 8비트 unsigned char 자료형을 사용하고 채널이 한 개인 행렬또는 영상을 의미한다. 다만, 채널이 한 개 인경우 C1은 생략할 수 있다.

  R,G,B 세 개의 색상 성분을 가지고 있는 컬러영상은 unsigned char 자료형을 사용하고 세개의 채널을 갖고있으므로 CV_8UC3타입 / 복소수처럼 두개의 실수 성분을 사용하는 행렬 = CV_32FC2 타입

 

1.2 행렬의 생성과 초기화

Mat 객체 생성 방법 

1) Mat 클래스의 기본 생성자 이용

> Mat img1;

  > 비어있는 행렬 

> Mat::Mat(int rows, int cols, int type);

 rows   새로만들 행렬의 행 개수(영상의 세로크기)

 cols    새로만들 행렬의 열 개수(영상의 가로크기)

 type    새로만들 행렬의 타입

Mat img2(480,640, CV_8UC1);     // unsgined char , 1-channel    -> 순서가 세로크기,가로크기인 점 주의

 -> 그레이 스케일 영상에서 주로 사용함.

 

2) Size 클래스 이용

Mat::Mat(Size size, int type);

size 새로 만들 행렬의 크기, Size(cols,rows) or Size(Width, height)

type 새로 만들 행렬의 타입

> Mat img4(Size(640,480), CV_8UC3);     // Size(width,height)    -> 위의 방법과 다르게 가로크기,세로크기 순서

-> 가로 640, 세로 480인 3채널 컬러영상

 

Mat 객체의 행렬의 크기와 타입만 지정할 경우 모든 원소는 임의의 값으로 채워지므로 모든 원소값을 초기화하는게 안전

> Mat::Mat(int rows, int cols, int type, const Scalar& s);

> Mat::Mat(Size size, int type, const Scalar& s);

s 행렬 원소 초깃값

Scalar 클래스는 네 개의 실수값을 저장할 수 있는 OpenCV클래스이며, 주로 영상의 픽셀 값을 표현하는 용도로 사용

> Mat img5(480,640,CV_8UC1,Scalar(128));    // 그레이스케일 영상 img5의 모든 픽셀 밝기가 128로 설정된다

Scalar 클래스를 이용하여 컬러 영상의 색상을 지정할때에는 (B,G,R) 순서대로 값을 지정한다.

 

행렬 생성 시 모든 원소 값을 0으로 초기화하는 방법

1. Mat 클래스의 행렬 원소 초깃값에 Scalar(0)을 지정

2. Mat::zeros() 함수를 이용하여 모든 원소가 0으로 초기화된 행렬 생성

 

static MatExpr Mat::zeros(int rows, int cols, int type);

static MatExpr Mat::zeros(sSize size, int type);

-> 반환값 : 모든 원소가 0으로 초기화된 행렬 표현식 / zeros() 함수는 Mat 클래스의 정적멤버 함수이기에 실제코드에서 Mat::를 붙여서 사용해야한다. zeros()함수의 반환형인 MatExpr은 행렬의 대수 연산을 표현하는 클래스이며 자동으로 Mat클래스 형으로 변환된다.

 

모든원소가 1로 초기화된 행렬 표현식은 위와 같은 방법으로 static MatExpr Mat::ones() 함수를 사용한다.

단위 행렬 표현식 또한, static MatExpr Mat::eye() 함수를 사용한다.

 

Mat 객체를 생성할때, 기존에 이미 할당되어 있는 메모리 공간의 데이터를 행렬 원소값으로 사용할 수 있으며, 자체적인 메모리 할당을 수행하지 않고 외부 메모리를 참조하는 방식이기에 객체 생성이 빠르다는 장점이 있다.

 

Mat::Mat(int rows,int cols, int type, void*data, size_t step=AUTO_STEP);

data : 외부 행렬 데이터의 주소

step : 외부 행렬 데이터에서 한 행이 차지하는 바이트 수, 기본값을 사용한다면 패딩 바이트가 없다고 간주

 

비어있는 Mat 객체 또는 이미 생성된 Mat 객체에 새로운 행렬을 할당하려면 Mat::create() 함수 사용

void Mat::create(int rows, int cols, int type);

void Mat::create(Size size, int type);

 

하지만 Mat::create() 함수는 초기화 기능이 없으므로 별도의 함수를 이용해야한다.

 =연산자 재정의 또는 Mat::setTo()멤버 함수를 이용하여 전체 원소값을 한번에 설정할 수 있다.

Mat& Mat::operator=(const Scalar&s);

s:원소에 설정할 값

 

Mat& Mat::setTo(InputArray value, InputArray mask=noArray());

value : 행렬 원소에 설정할 값

mask : 마스크 행렬, 마스크 행렬의 원소가 0이 아닌 위치에서만 value 값 설정, 전체 원소값 설정하려면 noArray 또는 Mat 지정