CV_<bit-depth>{U|S|F}
<bit-depth>에는 8, 16, 32, 64 지정 가능, 원소 값 하나의 비트 수 나타낸다
U에는 부호 없는 정수형
S에는 부호 있는 정수형
F에는 부동 소수형 의미한다
#define CV_8U 0 //uchar, unsigned char, 부호 없는 1바이트 정수
#define CV_8S 1 //schar, signed char, 부호 있는 1바이트 정수
#define CV_16U 2 //ushort, unsigned short, 부호 없는 2바이트 정수
#define CV_16S 3 //signed short, 부호 있는 2바이트 정수
#define CV_32S 4 //int, 부호 있는 4바이트 정수
#define CV_32F 5 //float, 부호 있는 2바이트 실수
#define CV_64F 6 //double, 부호 있는 8바이트 실수
#define CV_16F 7 //float16_t, 부호 있는 2바이트 실수, Open CV에서 정의한 자료형
Mat 클래스 : 행렬(matrix)을 나타내는 클래스로, Open CV에서 가장 많이 사용하는 클래스, 2차원 영상을 표현하는 용도로 많이 사용
Mat(int row, int cols, int type);
//row -> 새로 만들 행렬의 행 개수, 영상의 세로 크기
//cols -> 새로 만들 행렬의 열 개수, 영상의 가로 크기
//type -> 새로 만들 행렬의 타입
Mat(Size size, int type);
//size -> 새로 만들 행렬의 크기, Size(cols, rows) 또는 Size(width, height)
Mat(int rows, int cols, int type, const Scalar& s);
Mat(Size size, int type, const Scalar& s);
//s -> 행렬 원소 초기값
Mat img1; // empty matrix
Mat img2(480, 640, CV_8UC1); // unsigned char, 1-channel, 그레이스케일
Mat img3(480, 640, CV_8UC3); // unsigned char, 3-channels, 트루 컬러
Mat img4(Size(640, 480), CV_8UC3); // Size(width, height)
Mat img5(480, 640, CV_8UC1, Scalar(128)); // initial values, 픽셀 밝기 128
Mat img6(480, 640, CV_8UC3, Scalar(0, 0, 255)); // initial values, red
zero() 함수 : Open CV에서 모든 원소가 0으로 초기화된 행렬을 만드는 함수
zeros(int row, int cols, int type);
zeros(Size size, int type);
ones() 함수 : 모든 원소가 1로 초기화된 행렬을 만드는 함수
ones(int rows, int cols, int type);
ones(Size size, int type);
eye() 함수 : 단위 행렬을 만드는 함수
eye(int rows, int cols, int type);
eye(Size size, int type);
Mat mat1 = Mat::zeros(3, 3, CV_32SC1); // 0's matrix
Mat mat2 = Mat::ones(3, 3, CV_32FC1); // 1's matrix
Mat mat3 = Mat::eye(3, 3, CV_32FC1); // identity matrix
Mat(int row, int cols, int type, void* data, size_t step=AUTO_STEP);
Mat(Size size, int type, void* data, size_t step=AUTO_STEP);
//data -> 사용할 외부 행렬 데이터의 주소
//step -> 행렬 데이터에서 한 행이 차지하는 바이트 수
float data[] = { 1, 2, 3, 4, 5, 6 };
Mat mat4(2, 3, CV_32FC1, data);
/*
mat4 =
┌ ┐
│ 1 2 3 │
│ 4 5 6 │
└ ┘
*/
Mat mat5 = (Mat_<float>(2, 3) << 1, 2, 3, 4, 5, 6);
/*
mat5 =
┌ ┐
│ 1 2 3 │
│ 4 5 6 │
└ ┘
*/
Mat mat6 = Mat_<uchar>({ 2, 3 }, { 1, 2, 3, 4, 5, 6 });
create() 함수 : 비어 있는 Mat 객체 또는 이미 생성된 Mat 객체에 새로운 행렬을 할당하는 함수
create(int rows, int cols, int type);
create(Size size, int type);
setTo() 함수 : create() 함수를 이용하여 행렬을 생성한 후 행렬 전체 원소 값을 초기화하는 함수
operator = (const Scalar& s);
setTo(InputArray value, InputArray mask = noArray());
//value -> 행렬 원소에 설정한 값
//mack -> 마스크 행렬, 마스크 행렬의 원소가 0이 아닌 위치에서만 value 값이 설정
mat4.create(256, 256, CV_8UC3); // uchar, 3-channels
mat5.create(4, 4, CV_32FC1); // float, 1-channel
mat4 = Scalar(255, 0, 0); //모든 영상 픽셀을 파란색으로 설정
mat5.setTo(1.f); //모든 원소의 값 1.f로 설정
행렬의 복사
행렬을 복사하는 가장 간단한 방법은 복사 생성자 또는 대입 연산자를 사용하는 것입니다.
하지만 복사본 영상을 새로 생성할 때, 픽셀 데이터를 공유하는 것이 아니라 메모리 공간을 새로 할당하여 픽셀 데이터 전체를 복사하고 싶다면 clone() 함수나 copyTo() 함수를 사용해야 합니다
clone() 함수 : 자기 자신과 동일한 Mat 객체를 완전히 새로 만들어서 반환
clone() const;
copyTo() 함수 : 인자로 전달된 m 행렬에 자기 자신을 복사
copyTo(OutputArray m) const;
copyTo(OutputArray m, InputArray mask) const;
//m -> 복사본이 저장될 행렬
Mat img1 = imread("dog.bmp");
Mat img2 = img1; //복사 생성자, 얕은 복사
Mat img3;
img3 = img1; //대입 연산자, 얕은 복사
Mat img4 = img1.clone(); //깊은 복사
Mat img5;
img1.copyTo(img5); //깊은 복사
img1.setTo(Scalar(0, 255, 255)); // yellow
imshow("img1", img1);
imshow("img2", img2);
imshow("img3", img3);
imshow("img4", img4);
imshow("img5", img5);
waitKey();
destroyAllWindows();
얄은 복사를 한 img2와 img3는 원본이 바뀌니 전부 바뀌어 버렸고
깊은 복사를 한 img4와 img5는 원본이 바뀌어도 복사본은 그대로인것을 확인할 수 있다.
부분 행렬 추출
영상에서 사각형 모양의 부분 영상을 추출하거나 참조하는 방법
operator()(const Rect& roi) const;
operator()(Range rowRange, Range colRange) const;
//rio -> 사각형 관심 영역
//rowRange -> 관심 행 범위
//colRanger -> 관심 열 범위
Mat img1 = imread("cat.bmp");
Mat img2 = img1(Rect(220, 120, 340, 240)); //사각형 범위로 영상 추출
Mat img3 = img1(Rect(220, 120, 340, 240)).clone(); //사각형 범위로 클론 생성, 깊은 복사
img2 = ~img2; //색상 반전
imshow("img1", img1);
imshow("img2", img2);
imshow("img3", img3);
waitKey();
destroyAllWindows();
rowRange() 함수 : 지정한 범위의 행으로 구성된 행렬을 반환하는 함수
rowRange(int startrow, int endrow) const;
rowRange(const Range& r) const;
//startrow -> 추출할 행 범위 시작 번호 (포함)
//endrow -> 추출할 행 범위 끝 번호 (불포함)
//r -> 추출할 행 범위
colRange() 함수 : 지정한 범위의 열로 구성된 행렬을 반환하는 함수
colRange(int startcol, int endcol) const;
colRange(const Range& r) const;
//startcol -> 추출할 열 범위 시작 번호 (포함)
//endcol -> 추출할 열 범위 끝 번호 (불포함)
row(int y) const; //하나의 행 추출
col(int x) const; //하나의 열 추출
픽셀 값 접근 방법
at() 함수를 사용하는 방법 : 행과 열을 나타내는 두 개의 정수를 인자로 받아 해당 위치의 행렬 원소 값을 참조 형식으로 반환
template<typename _Tp> _Tp& Mat::at(int y, int x)
//y -> 참조할 행 번호
//x -> 참조할 열 번호
Mat mat1 = Mat::zeros(3, 4, CV_8UC1); //3x4 행렬, 모든 원소 0으로 초기화
for (int j = 0; j < mat1.rows; j++) {
for (int i = 0; i < mat1.cols; i++) {
mat1.at<uchar>(j, i)++; //값 1만큼 증가
}
}
ptr() 함수를 사용하는 방법 : Mat 행렬에서 특정 행의 첫 번쨰 원소 주소를 반환
template<typename _Tp> _Tp* Mat::ptr(int y)
for (int j = 0; j < mat1.rows; j++) {
uchar* p = mat1.ptr<uchar>(j);
for (int i = 0; i < mat1.cols; i++) {
p[i]++; //값 1만큼 증가
}
}
Matlterator 반복자 사용 방법 : Mat 행렬 원소 참조를 위한 반복자 변수를 만들어서 행렬 크기에 상관없이 행렬 전체 원소를 차례대로 참조하는 방식
for (MatIterator_<uchar> it = mat1.begin<uchar>(); it != mat1.end<uchar>(); ++it) {
(*it)++; //값 1만큼 증가
}
행렬의 정보 참조
channels() const; | 행렬의 태널 수를 반환 |
depth() const; | 행렬의 깊이를 반환 ex) CV_8U |
elemSize() const; | 한 개의 원소가 차지하는 메모리 크기를 바이트 단위로 반환 ex) CV_32SC3 = 4 x 3 = 12 |
elemSize1() const; | 하나의 채널에서 한 개의 원소가 차지하는 메모리 크기를 바이트 단위로 반환 ex) CV_32SC3 = 4 |
empty() const; | 비어 있는 행렬이면 true를 반환 |
isContinuous() const; | 각 행의 원소가 연속적으로 저장되어 있으면 true를 반환 |
isSubmatrix() const; | 행렬이 다른 행렬의 부분 행렬이면 ture를 반환 |
size() const; | 행렬 크기를 Size 타입으로 반환 |
total() const; | 전체 원소 개수를 반환 |
type() const; | 행렬의 타입을 반환 ex) CV_32FC1 |
Mat img1 = imread("lenna.bmp");
cout << "Width: " << img1.cols << endl; //Width: 512
cout << "Height: " << img1.rows << endl; //Height: 512
cout << "Channels: " << img1.channels() << endl; //Channels: 3
if (img1.type() == CV_8UC1)
cout << "img1 is a grayscale image." << endl;
else if (img1.type() == CV_8UC3)
cout << "img1 is a truecolor image." << endl;
//img1 is a turecolor image
float data[] = { 2.f, 1.414f, 3.f, 1.732f };
Mat mat1(2, 2, CV_32FC1, data);
cout << "mat1:\n" << mat1 << endl;
/*
[2, 1.414;
3, 1.732]
*/
행렬 연산
mul() 함수 : 두 행렬에서 같은 위치에 있는 원소끼리 곱셈 연산을 수행하는 함수
mul(InputArray m, double scale=1) const;
//m -> *this 행렬과 크기 및 타입이 같은 행렬
//scale -> 추가적으로 곱할 값
inv() 함수 : 역행렬을 구할 때 사용하는 함수
*역행렬 : 주어진 행렬의 곱셈에 대한 역원
inv(int method-DECOMP_LU) const;
//method -> 역행렬 계산 방법
DECOMP_LU | 가우스 소거법, 일반적인 행렬 |
DECOMP_SVD | 역행렬이 존재하지 않는경우, 특잇값 분해 방법을 이용해 의사 역행렬 구함 |
DECOMP_EIG | 고윳값 분해 |
DECOMP_CHOLESKY | 촐레스키 분해 |
t() 함수 : 행렬의 행과 열을 서로 교환해서 만드는 전치 행렬을 만드는 함수
t() const;
float data[] = { 1, 1, 2, 3 };
Mat mat1(2, 2, CV_32FC1, data);
cout << "mat1:\n" << mat1 << endl;
Mat mat2 = mat1.inv(); //역행렬
cout << "mat2:\n" << mat2 << endl;
cout << "mat1.t():\n" << mat1.t() << endl; //전치 행렬
cout << "mat1 + 3:\n" << mat1 + 3 << endl;
cout << "mat1 + mat2:\n" << mat1 + mat2 << endl;
cout << "mat1 * mat2:\n" << mat1 * mat2 << endl;
크기 및 타입 변환 함수
convertTo() 함수 : 행렬의 타입을 변경하는 함수
convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
//m -> 출력 행렬
//rtype -> 원하는 출력 행렬의 타입
//alpha -> 추가적으로 곱할 값
//beta -> 추가적으로 더할 값
reshape() 함수 : 행렬 원소 데이터를 복사하여 새로운 행렬을 만드는 것이 아닌 하나의 행렬 원소 데이터를 같이 참조하는 행렬을 반환
rechape(int cn, int rows=0) const;
//cn -> 새로운 체널 수
//rows -> 새로운 행의 수
resize() 함수 : 행렬의 모양을 변경시키는 것이 아니라 단순히 행렬의 행 크기를 변경
resize(size_t sz);
resize(size_t sz, const Scalar& s);
//sz -> 새로운 행 개수
//s -> 새로 추가되는 행 원소의 초기값
push_back() 함수 : 이미 존재하는 행렬에 원소 데이터를 추가하는 함수
push_back(const _TP& elem);
push_back(const Mat_<_TP>& elem);
push_back(const std::vector<_TP>& elem);
push_back(const Mat& m);
//elem -> 행렬의 맨 마지막 행에 추가할 원소 데이터
//m -> 행렬의 맨 마지막 행에 추가할 행렬
pop_back() 함수 : 행렬에서 맨 아래에 있는 행을 제거하는 함수
pop_back(size_t nelems=1);
//nelems -> 제거할 행 개수
Mat img1 = imread("lenna.bmp", IMREAD_GRAYSCALE);
Mat img1f;
img1.convertTo(img1f, CV_32FC1);
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);
cout << "mat1:\n" << mat1 << endl;
cout << "mat2:\n" << mat2 << endl;
mat1.resize(5, 100);
cout << "mat1:\n" << mat1 << endl;
Mat mat3 = Mat::ones(1, 4, CV_8UC1) * 255;
mat1.push_back(mat3);
cout << "mat1:\n" << mat1 << endl;
'런닝머신 (ML)' 카테고리의 다른 글
[컴퓨터 비전 & 머신러닝] InputArray와 OutputArray 클래스 (0) | 2023.03.20 |
---|---|
[컴퓨터 비전 & 머신러닝] Vec과 Scalar 클래스 (0) | 2023.03.20 |
[컴퓨터 비전 & 머신러닝] Open CV 기본 자료형 클래스 (0) | 2023.03.07 |
[컴퓨터 비전 & 머신러닝] Visual Studio OpenCV 설치 방법 및 주요 함수 (0) | 2023.02.21 |
[컴퓨터 비전 & 머신러닝] 나혼자 컴퓨터 비전 도전기 (0) | 2023.02.21 |