14 minute read



2.2.1 Mat Class


Mat 클래스는 행렬을 나타낸다. 고차원 행렬도 표현 가능.


멤버 변수 설명
Mat::dims Mat 행렬의 차원. 영상과 같은 2D 행렬의 경우 2.
Mat::rows 행렬의 행 개수. 영상이 저장되어 있다면 세로 픽셀 크기. 3D 이상의 경우 -1.
Mat::cols 행렬의 열 개수. 영상이 저장되어 있다면 가로 픽셀 크기. 3D 이상의 경우 -1.
Mat::size 3차원 이상의 행렬 크기 정보를 참조하는 변수.
Mat::dims 행렬의 원소 데이터가 저장된 메모리 공간을 가리키는 포인터형 변수. 빈 행렬의 경우 NULL.


Mat 클래스는 다양한 자료형을 사용 가능. 행렬이 사용하는 자료형을 나타내는 정보를 depth라고 한다. OpenCV에서 Mat 행렬의 depth는 다음 매크로 상수로 표현.

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

<bit-depth>에는 8, 16, 32, 64의 숫자를 지정할 수 있다. 이는 원소 하나가 차지하는 비트 수. 그 다음으로는 U, S, F 중 하나를 지정 가능하다. Uunsigned(부호 없는 정수형), Ssigned(부호 있는 정수형), Ffloat(부동 소수형)를 의미.

OpenCV 라이브러리는 다음처럼 매크로 상수로 행렬의 depth 표현이 정의되어 있다.

매크로 상수 나타내는 자료형
#define CV_8U 0 uchar, unsigned char
#define CV_8S 1 schar, signed char
#define CV_16U 2 ushort, unsigned short
#define CV_16S 3 signed short
#define CV_32S 4 int
#define CV_32F 5 float
#define CV_64F 6 double
#define CV_16F 7 float16_t


Mat 행렬 원소를 구성하는 각각의 값을 channel이라고 한다. 하나의 행렬을 구성하는 각 channel은 모두 같은 자료형을 사용해야 한다.

그레이스케일 영상은 한 픽셀당 하나의 정보(밝기)만을 사용하므로 1 channel matrix, 트루컬러 영상은 한 픽셀당 세 색상 정보(BGR)를 가지므로 3 channels matrix.

Mat 행렬의 depth와 channel 정보를 합쳐서 Mat 객체의 type이라고 부른다. Mat 행렬의 type은 다음 매크로 상수로 표현된다.

CV_<bit-depth>{U|S|F}C(<number_of_channels>)

BGR 컬러 영상은 unsigned char 자료형을 사용하고 세 개의 channel을 사용하므로 CV_8UC3 type.

복소 행렬은 두 실수값을 사용하므로 CV_32FC2 type.



2.2.2 행렬의 생성 및 초기화


// 기본 생성자
Mat img;
---
비어 있는 행렬 생성.
img.rows  img.cols 값은 0 이며 img.data 에는 NULL 저장된다.

빈 행렬을 생성했으므로 이를 다른 함수의 입력값으로 쓰거나, 원소 값을 참조하려고 하면 에러가 발생한다.


생성과 동시에 원소 값을 저장하기 위해 메모리를 할당하고자 한다면 다음 생성자를 사용.

// 행, 열, type을 인자로 받는 생성자
Mat::Mat(int rows, int cols, int type);

// 크기와 type을 인자로 받는 생성자
Mat::Mat(Size size, int type);
---
 - rows :  개수(영상의 세로 크기)
 - cols :  개수(영상의 가로 크기)
 - type : 행렬 타입(매크로 상수)
 - size : 행렬 크기. Size(cols, rows) 또는 Size(width, height)

Size 클래스는 가로와 세로 순서로 인자를 받는 반면, Mat 클래스는 세로와 가로 순서로 인자를 받는다.

Mat img2(480, 640, CV_8UC3);  // unsigned char, 3-channels
Mat img3(Size(640, 480), CV_8UC3);


이렇게 행렬을 생성했을 때 문제가 하나 있다. Mat 행렬의 모든 값이 쓰레기 값으로 지정되고 만다. Mat 객체를 생성함과 동시에 모든 원소 값을 초기화시키고 싶다.

// 특정 초기값을 사용해 초기화
Mat::Mat(int rows, int cols, int type, const Scalar& s);
Mat::Mat(Size size, int type, const Scalar& s);
---
 - s : 행렬 원소 초기값

초기값으로 사용되는 s의 타입은 Sclar 클래스. 네 개의 실수 값을 저장할 수 있는 OpenCV 클래스이다. 주로 영상의 픽셀 값을 표현한다. 그레이스케일 영상의 픽셀 값을 표현할 때는 하나의 멤버 변수만을, 3-channels 컬러 영상을 표현할 때는 세 개의 멤버 변수를 사용.

Mat img4(480, 640, CV_8UC1, Scalar(128));             // unsigned char, 1-channel greyscale, 128
Mat img5(Size(640, 480), CV_8UC3, Scalar(0, 0, 255)); // unsinged char, 3-channels color, red


Mat::zero() - 영행렬 초기화

보통은 행렬을 생성할 때 모든 원소 값을 0으로 초기화한다. 그래서 0으로 초기화된 행렬을 생성해주는 함수를 별도로 만들어 두었다. Mat::zero()라는 함수이다.

static MatExpr Mat::zeros(int rows, int cols, int type);
static MatExpr Mat::zeros(Size size, int type);
---
- return : 모든 원소가 0으로 초기화된 행렬 표현식

주의할 점은 Mat::zero() 함수는 정적 멤버 함수이므로 Mat::를 붙여서 사용해야 한다. 반환 타입인 MatExpr은 행렬의 대수 연산을 표현하는 클래스. 자동으로 Mat 클래스로 변환된다.

Mat mat1 = Mat::zeros(3, 3, CV_32SC1);  // int, 1-channel, 3 x 3 zero matrix 


Mat::ones() - 일행렬 초기화

마찬가지로 모든 원소가 1로 초기화된 행렬, 단위 행렬을 생성하는 함수도 존재.

static MatExpr Mat::ones(int rows, int cols, int type);
static MatExpr Mat::ones(Size size, int type);
---
- return : 모든 원소가 1 초기화된 행렬 표현식
static MatExpr Mat::eye(int rows, int cols, int type);
static MatExpr Mat::eye(Size size, int type);
---
- return : 단위 행렬 표현식


Mat 행렬 생성 시 새로 메모리 공간을 할당하지 않고 이미 할당된 메모리 공간의 데이터를 행렬의 값으로 사용할 수 있다. 외부 메모리를 참조하므로 행렬 생성이 빨라진다.

// 기존 메모리 공간을 참조하여 생성
Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP);
---
 - data : 사용할 외부 행렬 데이터 주소.
 - step : 외부 행렬 데이터에서  행이 차지하는 byte . 외부 행렬 데이터의  행에 여분의 padding byte 있으면 명시적으로 지정할 필요가 있다. 기본값 AUTO_STEP padding byte 없다고 가정.

만일 다음 float형 array를 먼저 정의하고 이 배열을 행렬 원소로 사용하는 Mat 객체를 생성하고자 한다면,

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

이렇게 외부 배열 크기와 생성할 행렬 원소의 수가 같아야 하고, 사용되는 자료형도 같아야 한다. 이렇게 생성된 mat2 행렬은 다음 형태.

\[\textrm{mat2}= \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{bmatrix}\]

외부 메모리 공간을 참조해 Mat 객체를 생성할 경우, Mat 객체의 원소 값과 외부 메모리 공간의 데이터 값은 서로 연동된다. 외부 메모리 값을 변경하면 mat2의 원소 값도 변경되고 그 반대도 마찬가지이다.


Mat_클래스를 사용하는 방법도 있다. Mat_ 클래스는 Mat 클래스를 상속해서 만든 template class이며 두 클래스는 상호 변환이 가능.

Mat_ 클래스에서는 << 연산자와 ,를 이용해 간단히 행렬 원소값을 설정할 수 있다.

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

위 예시는 먼저 Mat_ 객체를 생성. Template class이므로 저장할 원소의 자료형을 명시하고 rowscols를 사용해 객체를 생성했다. 그 다음으로 << 연산자와 ,를 이용해 mat3_ 행렬의 전체 여섯 원소 값을 순서대로 지정. 마지막 line에서 mat3_ 행렬을 복사하여 Mat 클래스 타입의 객체 mat3를 선언.

이렇게 만들어진 mat3 행렬은 $2 \times 3$의 크기를 갖고, 타입은 CV_32FC1이며 mat3_ 행렬과 같은 원소를 공유한다. 이를 한 줄로 나타내면,

Mat mat4 = (Mat_<float>(2, 3) << 1, 2, 3, 4, 5, 6);
Mat mat5 = Mat_<float>({2, 3}, { 1, 2, 3, 4, 5, 6 }); // 초기화 리스트 사용


Mat::create(), Mat::setTo() - 행렬 할당

비어 있는 Mat 객체 또는 이미 생성된 Mat 객체에 새로운 행렬을 할당하는 멤버 함수는 Mat::create()이다.

// 이미 생성된 객체에 새 행렬 할당
void Mat::create(int rows, int cols, int type);
void Mat::create(Size size, int type);

만약 Mat::create() 함수의 인자로 지정한 행렬 크기와 타입이 기존 행렬과 다르면, Mat::create() 함수는 기존 메모리 공간을 해제하고 새로운 메모리 공간을 할당한다.

Mat::create() 함수는 새로 만든 행렬의 원소 값을 초기화하는 기능이 없다. 이때는 = 연산자 재정의 또는 `Mat::setTo()’ 멤버 함수를 이용한다.

Mat& Mat::operator = (const Scalar& s);
---
- s : 원소에 설정할 
- return : 값이 설정된 Mat 객체의 참조
Mat& Mat::setTo(InputArray value, InputArray mask = noArray());
---
 - value : 원소에 설정할 
 - mask : 마스크 행렬. 마스크 행렬의 원소가 0 아닌 위치에서만 value 값이 설정된다. 행렬 전체 원소 값을 설정하려면 noArray() 또는 Mat() 지정.(생략 가능)
 - return : Mat 객체의 참조

이를 이용해 mat5의 모든 원소 값을 일괄적으로 설정하면,

mat5.setTo(1.f);  // 모든 원소 값이 1.f로 설정



2.2.3 행렬 복사


Sec. 1.2에서 썼던 사진을 다시 불러오자.

Mat img1 = imread("asset/example.jpg");

행렬 객체를 다른 행렬 객체에 대입하는 가장 간단한 방법은 복사 생성자와 대입 연산자. 둘 다 얕은 복사이다.

Mat img2 = img1;  // 복사 생성자

Mat img3;
img3 = img1;      // 대입 연산자

Mat 클래스의 복사 생성자와 대입 연산자는 원소 데이터를 공유한다.


Mat::clone(), Mat::copyTo() - 깊은 복사

그렇지 앟고 메모리 공간을 새로 할당한 뒤에 픽셀 데이터 전체를 복사하고 싶다면? 깊은 복사.

Mat Mat::clone() const;
---
 - return : *this 행렬의 복사본
void Mat::copyTo(OutputArray m) const;
void Mat::copyTo(OutputArray m, InputArray mask) const;
---
 - m : 복사본이 저장될 행렬. 만약 *this 행렬과 size  type 다르면 메모리를 새로 할당한다.
 - mask : 마스크 행렬. 마스크 행렬의 원소 값이 0 아닌 좌표에서만 복사.

Mat::clone() 함수는 자신과 동일한 Mat 객체를 완전히 새로 만들어 반환한다. 반면 Mat::copyTo() 함수는 인자로 전달된 m 행렬에 자기 자신을 복사.

Mat img4 = img1.clone();

Mat img5;
img1.copyTo(img5);


이하는 실습 코드.

Line 8 : example.jpg 불러와 img1 저장
Line 11~13 : 복사 생성자와 대입 연산자를 이용한 얕은 복사
Line 16~18 : Mat::clone() Mat::copyTo() 이용한 깊은 복사
Line 20 : img1 모든 픽셀을 Scalar(0, 0, 255) 해당하는 노란색으로 설정
Line 22~26 : img1 ~ img5 모두  창으로 출력


얕은 복사를 취한 img2, img3img1과 데이터를 공유하므로 노란색 배경으로 바뀐다. 그러나 img4, img5는 깊은 복사를 취했기 때문에 영상을 그대로 보존하고 있다.



2.2.4 부분 행렬 추출


영상에서 사각형 모양의 부분 영상을 추출하자. Mat 클래스에는 괄호 연산자가 재정의 되어있다.

Mat Mat::operator() (const Rect& roi) const;
Mat Mat::operator() (Range rowRange, Range colRange) const;
---
 - roi : 사각형 관심 영역(Region of Interext)
 - rowRange : 관심  범위
 - colRange : 관심  범위
 - return : 추출한 부분 행렬 또는 영상. 기존 영상과 픽셀 데이터를 공유.

example.jpg 영상의 일부를 추출해 보자. example.jpg의 크기는 500 x 384이다. Rect 클래스는 x, y, width, height를 인자로 받는 것을 기억하자.

Line 10 : img1 영상의 (150, 80) 좌표부터 200 x 150 크기만큼의 사각형 부분 영상을 추출해 img2 변수에 저장.
Line 11 : Mat::clone() 멤버 함수를 사용해 독립된 메모리 영역을 할당, 부분 영상 추출.


만약 사각형이 아닌 임의의 모양의 ROI를 설정하고 싶다면 마크스 연산을 사용해야 한다. 이건 나중에.


Mat::rowRange(), Mat::colRange() - 부분 행렬 추출

특정 범위의 행과 열을 부분 행렬로 추출하고자 한다면 Mat::rowRange()Mat::colRange() 함수를 사용한다. 범위는 두 int 값으로 지정할 수도 있고 Range 클래스 객체를 이용할 수도 있다.

Mat Mat::rowRange(int startrow, int endrow) const;
Mat Mat::rowRange(const Range& r) const;
---
 - startrow : 추출할  범위 시작 번호(포함)
 - endrow : 추출할  범위  번호(미포함)
 - r : 추출할  범위(Range 객체)
 - return : 지정한  범위에 해당하는 행렬
Mat Mat::colRange(int startcol, int endcol) const;
Mat Mat::colRange(const Range& r) const;
---
 - startcol : 추출할  범위 시작 번호(포함)
 - endcol : 추출할  범위  번호(미포함)
 - r : 추출할  범위(Range 객체)
 - return : 지정한  범위에 해당하는 행렬


Mat::row(), Mat::col() - 행, 열 추출

하나의 열 또는 하나의 행만을 추출하고자 한다면 Mat::row(), Mat::col().

Mat Mat::row(int y) const;
Mat Mat::col(int x) const;
---
 - y : 추출할  번호
 - x : 추출할  번호
 - return : 추출한 부분 행렬

Mat::rowRange(), Mat::colRange(), Mat::row(), Mat::col()는 모두 얕은 복사 형태로 반환한다. 메모리를 따로 할당하여 저장하려면 Mat::clone() 함수와 함께 사용하자.



2.2.5 행렬 반전


간단한 영상 처리 방법으로 색상 반전을 수행할 수 있다. ~ 연산자를 앞에 붙이면 된다.

img2 = ~img2;
Line 11 : img2 영상을 반전하여  결과를 다시 img2 저장.




2.2.6 행렬 원소 참조


Mat::at() - 위치 참조

가장 직관적인 행렬 원소 참조 방법은 Mat::at() 함수.

template<typename _Tp> _Tp& Mat::at(int y, int x)
---
 - y : 참조할  번호
 - x : 참조할  번호
 - return : (_Tp& 타입으로  변환된) y 번째 , x 번째 열의 원소 

Mat::at() 함수는 템플릿 함수. 행렬 원소 자료형을 명시적으로 지정해야 한다. CV_32FC1 타입의 행렬이라면 float 자료형을 지정해야 한다.

예를 들어, Mat 타입 변수 img에 그레이스케일 영상을 저장했을 때, $(x, y)$ 좌표의 픽셀을 참조하고자 한다면 img.at<uchar>(y, x)라고 작성. 인자 좌표 $(x, y)$가 행렬 크기를 벗어나면 에러가 발생하므로 주의.


Line 8 : 모든 원소 값이 0으로 초기화된 CV_8UC1 타입의 행렬 mat1 정의.
Line 14 : Mat::at() 함수를 사용.  픽셀의 값을 1 증가.

위 예시에서 mat1은 0으로 초기화된 $3 \times 4$ 행렬. 각 원소는 uchar 자료형을 사용.


Mat::ptr() - 행 포인터 참조

Mat::ptr() 함수는 Mat 행렬에서 특정 행의 첫 번째 원소 주소를 반환한다.

template<typename _Tp> _Tp* Mat::ptr(int y)
---
 - y : 참조할  번호
 - return : (_Tp* 타입으로  변환된) y 번째 행의 시작 주소

마찬가지로 템플릿으로 정의된 함수이므로 자료형을 명시적으로 지정.

다음 예시는 Mat::ptr() 함수를 사용해 행렬의 모든 원소 값을 1씩 증가시키는 예시이다.

$j$행의 맨 마지막 열의 원소에 접근하려면 p[mat1.cols-1] 형태.


변수 puchar* 타입으로 선언된 포인터 변수. mat1.ptr<uchar>(0)는 0번째 행의 시작 주소를 가리킨다. 0번째 행의 $i$번째 원소는 p[i] 또는 *(p+i) 형태로 접근 가능.

참고로 for문을 사용해 모든 원소를 참조하고자 한다면 Mat::ptr()Mat::at()보다 빠르다.


MatIterator_ - 반복자

Mat 클래스의 반복자 클래스는 MatIterator_. 사용법은 C++에서의 일반적인 반복자와 같다.

이 코드에는 mat1의 가로 또는 세로 크기를 참조하는 내용이 없다. 행렬의 크기에 상관없이 참조가 가능!

다만 Mat::ptr()보다 느리며, Mat::at()처럼 임의의 위치에 자유롭게 접근할 수는 없다.



2.2.7 행렬 멤버 변수


행렬 객체 정보 참조


int Mat::channels() const;
---
 - return : 행렬의 채널 
int Mat::type() const;
---
 - return : 행렬의 타입
int Mat::depth() const;
---
 - return : 행렬의 깊이
size_t Mat::elemSize() const;
---
 - return :  개의 원소가 차지하는 메모리 크기를 Byte 단위로 반환.
 예를 들어, CV_32SC3 type 행렬이라면 4 X 3 = 12 반환.
size_t Mat::elemSize1() const;
---
 - return : 하나의 채널에서  개의 원소가 차지하는 메모리 크기를 Byte 단위로 반환.
 예를 들어, CV_32SC3 type 행렬이라면 4 반환.
bool Mat::empty() const;
---
 - return : 비어 있는 행렬이면 true 반환.
bool Mat::isContinuous() const;
---
 - return :  행의 원소가 연속적으로 저장되어 있으면 true 반환.
bool Mat::isSubmatrix() const;
---
 - return : 행렬이 다른 행렬의 부분행렬이면 true 반환.
Size Mat::size() const;
---
 - return : 행렬 크기를 Size 타입으로 반환.
size_t Mat::total() const;
---
 - return : 전체 원소 개수 반환.


<< 연산자 재정의


Mat 객체에 저장된 정보가 영상이라면 imshow() 함수로 화면에 출력할 수 있다.

그런데 Mat 객체에 저장된 자료형이 int, double type이라면? 이 행렬의 정보를 출력하고자 한다.


OpenCV에는 << 연산자가 재정의되어 있어서, std::cout으로 행렬에 저장된 원소를 출력할 수 있다.

static inline
std::ostream& operator << (std::ostream& out, const Mat& mtx)
---
 - out : C++ 표준 출력 스트림 객체
 - mtx : 출력할 행렬
 - return : C++ 표준 출력 스트림 객체의 참조


위와 같이 행렬의 원소가 출력된다. Mat 객체의 모든 원소는 대괄호 안에서 출력되며 각 원소는 ,로, 각 행은 ;로 구분된다.



2.2.8 행렬 연산

사칙연산


OpenCV에는 Mat 클래스를 위한 사칙연산이 재정의되어 있다.

MatExpr operator + (const Mat& a, const Mat& b);
MatExpr operator + (const Mat& a, const Scalar& s);
MatExpr operator + (const Scalar& s, const Mat& b);
---
 - 행렬과 행렬, 행렬과 스칼라 사이의 덧셈 연산 수행. 이때  행렬은 같은 타입.
---

MatExpr operator - (const Mat& a, const Mat& b);
MatExpr operator - (const Mat& a, const Scalar& s);
MatExpr operator - (const Scalar& s, const Mat& b);
---
 - 행렬과 행렬, 행렬과 스칼라 사이의 뺄셈 연산 수행. 이때  행렬은 같은 타입.
---

MatExpr operator - (const Mat& m);
---
 - 행렬의  원소에 -1  곱한다.
---

MatExpr operator * (const Mat& a, const Mat& b);
MatExpr operator * (const Mat& a, double s);
MatExpr operator * (double s, const Mat& b);
---
 - 행렬과 행렬, 행렬과 실수 사이의 곱셈 연산 수행.
---

MatExpr operator / (const Mat& a, const Mat& b);
MatExpr operator / (const Mat& a, double s);
MatExpr operator / (double s, const Mat& b);
---
 -  행렬의 같은 위치 원소끼리 나눗셈 연산, 또는 행렬과 실수 사이의 나눗셈 연산 수행.

MatExpr 타입은 행렬 표현식 클래스로, Mat 객체와 Scalar 객체, 그리고 C/C++ 기본 자료형으로 구성된 행렬 연산을 표현한다. 복사 생성자나 대입 연산자를 통해 Mat 객체로 변환이 가능하다.


* 연산자는 행렬곱. 그럼 같은 위치의 원소끼리 곱셈 연산을 하고 싶으면?

MatExpr Mat::mul(InputArray m, double scale=1) const;
---
 - m : *this 행렬과 크기와 타입이 같은 행렬, 또는 행렬식
 - scale : 추가로 곱할 
 - return :  행렬의 같은 위치의 원소끼리 곱해서 얻은 행렬 표현식


그리고 빼먹을 수 없는 중요한 두 연산들/

MatExpr Mat::inv(int method=DECOMP_LU) const;
---
 - method : 역행렬 계산 방법
 - return : 역행렬에 대한 행렬 표현식
MatExpr Mat::t() const;
---
 - return : transpose 대한 행렬 표현식

역행렬을 구하는 Mat::inv()에는 역행렬의 계산 방법을 지정하는 method 인자가 들어간다.

인자 역행렬 계산 방법
DECOMP_LU 가우스 소거법(default)
DECOMP_SVD 역행렬이 존재하지 않을 때 SVD를 사용한 pseudo-inverse
DECOMP_EIG 고유값 분해
DECOMP_CHOLESKY Cholesky 분해



2.2.9 행렬 타입 변환


void Mat::convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
---
 - m : 출력 행렬
 - rtype : 원하는 출력 행렬 타입. 만일 rtype 음수이면 출력 행렬은 입력 행렬과 같은 타입이다.
 - alpha : 추가로 곱할 
 - beta : 추가로 더할 


일반적인 영상은 각 픽셀 값이 uchar 자료형으로 표현된다. 그런데 복잡한 연산을 수행할 경우 연산의 정확성을 높이기 위해 floatdouble 타입으로 변환해야 할 필요가 있다.

위 코드는 그레이스케일 영상으로 불러 온 img1을 float 자료형으로 변환하여 행렬 img1f에 저장하는 예시.



2.2.10 행렬 크기/채널 변환


Mat::reshape() 함수는 행렬의 크기나 채널을 변경시킨다.

Mat Mat::reshape( int cn, int rows=0 ) const;
---
 - cn : 새로운 채널 . 0 이면 채널 수를 변경하지 않는다.
 - rows : 새로운  . 0 이면  수를 변경하지 않는다.
 - return : 모양이 변경된 행렬 반환

Mat::reshape() 함수는 행렬 데이터를 복사해 새로 행렬을 만드는 것이 아니라, 기존의 행렬 데이터를 참조하는 행렬을 반환한다. 그러므로 변환된 행렬의 원소를 변경하면 원래 행렬 데이터도 바뀌게 된다.

$3 \times 4$ 행렬로 만들어진 mat1이 $2 \times 6$ 행렬 mat2로 변경되었다.



Mat::resize() 함수는 행렬의 모양을 변경시키지 않고 단순히 행렬의 행 크기를 변경한다.

void Mat::resize(size_t sz);
void Mat::resize(size_t sz, const Scalar& s);
---
 - sz : 새로운  개수
 - s : 새로 추가되는  원소의 초깃값

만약 sz가 기존 행렬의 행 개수보다 작으면 아래쪽 행을 제거하고, 크면 행을 추가한다. 이때 추가하는 원소의 초깃값을 s로 설정한다.



이미 존재하는 행렬에 원소를 추가하고 싶으면 Mat::push_back() 함수. 마치 vector처럼 쓰면 된다. 다양한 형식으로 정의되어 있다.

template<typename _Tp> void Mat::push_back(const _Tp& elem);
template<typename _Tp> void Mat::push_back(const Mat_<_Tp>& elem);
template<typename _Tp> void Mat::push_back(const std::vector<_Tp>& elem);
void Mat::push_back(const Mat& m);
---
 - elem : 행렬의  마지막 행에 추가할 원소 데이터
 - m : 행렬의  마지막 행에 추가할 행렬. 이때 *this 행렬과 타입   개수가 같아야 한다.

인자로 _Tp& 또는 std::vector<_Tp>& 타입을 사용할 경우, *this 행렬은 1열짜리여야 한다.

반면 Mat_<_Tp>& 또는 Mat& 타입을 사용할 경우 *this 행렬과 같은 개수의 열을 가져야 한다.

물론 위 네 경우 모두 타입이 같아야 한다.


Mat::push_back() 함수와 반대로 맨 아래 행을 제거하는 함수는 Mat::pop_back().

void Mat::pop_back(size_t nelems=1);
---
 - nelems : 제거할  개수. *this 보다 크면  된다.

Tags:

Categories:

Updated: