[python]OpenCV 공부노트 Mat3
[python]OpenCV 공부노트 Mat2 에 이어서
at함수 대신 ptr로 Mat에 접근하는 방법을 익혀본다.
#pragma warning(disable: 4819) #include "opencv.hpp" using namespace cv; using namespace std; int main() { Mat A(3, 3, CV_32FC1); for (int i = 0; i < A.rows; i++) { float* ptrA = A.ptr<float>(i); // row ptr 접근 for (int j = 0; j < A.cols; j++) { ptrA[j] = i* A.cols + j; // ptr로 접근 index번호 대입 } } cout << A << endl << endl; Mat B(3, 3, CV_32FC3); for (int i = 0; i < A.rows; i++) { Vec3f* ptrB = B.ptr<Vec3f>(i); for (int j = 0; j < A.cols; j++) { ptrB[j] = Vec3f(i* A.cols + j, 255, 128); } } cout << B << endl << endl; return 0; }
Header
행렬의 헤더를 하는것은 행렬 데이터를 새로 생성하지 않고 공유한다(referenced)는 것.
#pragma warning(disable: 4819) #include "opencv.hpp" using namespace cv; using namespace std; int main() { Mat A(3, 3, CV_32FC1); for (int i = 0; i < A.rows; i++) { for (int j = 0; j < A.cols; j++) { A.at<float>(i, j) = (float)(i*A.cols+j); } } Mat B1 = A.row(0); Mat B2 = A.col(0); Mat C1 = A.rowRange(0,2); Mat C2 = A.colRange(0,2); cout << "A : " << A << endl << endl; cout << "B1 : " << B1 << endl << endl; cout << "B2 : " << B2 << endl << endl; cout << "C1 : " << C1 << endl << endl; cout << "C2 : " << C2 << endl << endl; cout << endl << "===============================" << endl; A.row(0) = A.row(0) * 10; A.row(1) = A.row(1) * 100; A.row(2) *= 1000; cout << "A : " << A << endl << endl; cout << endl << "===============================" << endl; A.row(1) = A.row(2); // not work. cout << "A : " << A << endl << "will not work... " << endl << endl; A.row(2).copyTo(A.row(1)); cout << "A : " << A << endl << "will work!!.. " << endl << endl; cout << "B1 : " << B1 << endl << endl; cout << "B2 : " << B2 << endl << endl; cout << "C1 : " << C1 << endl << endl; cout << "C2 : " << C2 << endl << endl; return 0; }
A가 바뀜에 따라 헤더들(B1, B2, C1, C2)도 같이 값이 달라진 것을 알 수 있다. 이를 통해 헤더는 A의 요소를 참조하고 있음을 보여준다.
#pragma warning(disable: 4819) #include "opencv.hpp" using namespace cv; using namespace std; int main() { Mat A(3, 3, CV_32FC1); for (int i = 0; i < A.rows; i++) { for (int j = 0; j < A.cols; j++) { A.at<float>(i, j) = (float)(i * A.cols + j); } } Mat B = A.clone(); Mat C1, C2, C3; A.copyTo(C1); A.row(1).copyTo(C2); Mat mask(3, 3, CV_8UC1, Scalar(0)); mask.row(1).setTo(Scalar::all(1)); A.copyTo(C3, mask); A.at<float>(0, 0) = (float)(99.9f); cout << "A = " << A << endl << endl; cout << "B = " << B << endl << endl; cout << "mask : " << mask << endl << endl; cout << "C1 = " << C1 << endl << endl; cout << "C2 = " << C2 << endl << endl; cout << "C3 = " << C3 << endl << endl;
원본에서 복사할 마스크형태를 지정할 수 있는데, mask는 8UC(N)형식이어야 하며 non-zero 행렬이어야 한다.
Mat D1, D2; A.convertTo(D1, CV_8UC1); A.convertTo(D2, CV_8UC1, 10.0, 1.0); // alpha, beta cout << "D1 = " << D1 << endl << endl; cout << "D2 = " << D2 << endl << endl; Mat E1, E2; A.assignTo(E1); A.assignTo(E2, CV_8UC1); cout << "E1 = " << E1 << endl << endl; cout << "E2 = " << E2 << endl << endl; cout << " ============================================== " << endl; A.setTo(Scalar::all(0)); cout << "A filled 0 = " << A << endl << endl; cout << "D1 = " << D1 << endl << endl; cout << "D2 = " << D2 << endl << endl; cout << "E1 = " << E1 << endl << endl; cout << "E2 = " << E2 << endl << endl;
convertTo는 특정 형태의 타입으로 변환하여 저장할 수 있다.
convertTo(Mat destination, float alpha, float beta); 형태의 오버로드 함수를 사용할 때는
(element * alpha) + beta 로 가중치를 주어 변환할 수 있다.
assignTo는 기본적으로 변환형 함수이지만 타입형을 주지않으면 copyTo의 효과를 볼 수 있다.
타입형을 주면 convertTo처럼 작동하게된다.
다만 이전에서 본 것처럼 크기와 타입이 변하지 않은 위의 경우 (3×3, CV_8UC1 -> 3×3, CV_8UC1)
메모리를 재할당하지않고 reference를 전달하므로 A의 값이 바뀌자 D1, E1의 값도 바뀐것을 알 수 있다.
Mat F1, F2, F3; F1 = A.reshape(0, 1); F2 = A.reshape(0, 9); F3 = A.reshape(3, 3); cout << "F1 (0,1)= " << F1 << endl << F1.size() << endl << endl; cout << "F2 (0,9)= " << F2 << endl << F2.size() << endl << endl; cout << "F3 (3,3)= " << F3 << endl << F3.size() << endl << endl; A.setTo(Scalar::all(0)); cout << "F1 (0,1)= " << F1 << endl << F1.size() << endl << endl; cout << "F2 (0,9)= " << F2 << endl << F2.size() << endl << endl; cout << "F3 (3,3)= " << F3 << endl << F3.size() << endl << endl; return 0; }
reshape는 직관적으로 입력한 모양으로 Mat을 변환해준다.
다만 0x1, 0x9, 3×3이 아니라
reshape(int cn, int rows)로 cn은 채널값 (0은 변경없음), rows가 구조를 변경할 row를 입력한다.
다만 주의할 것은 참조이기때문에 A가 변하면 F1,F2,F3값도 변하여 표시된다.
3개의 댓글