[python]OpenCV 공부노트 Mat2
에 이어서 Mat::create() 부터 TIL
#pragma warning(disable: 4819) #include "opencv.hpp" using namespace cv; using namespace std; int main() { Mat A(2, 3, CV_32FC1, Scalar(0)); cout << A << endl << endl; A.create(2, 3, CV_32FC1); // 같은 사이즈 이므로 새로 메모리를 할당받지 않는다. cout << A << endl << endl; A.create(3, 3, CV_32FC1); // 3x3이 돼서 메모리를 개방한 후 새로 할당한다. 새로운 공간이라 쓰레기 값이 들어가있음. cout << A << endl << endl; A.create(Size(3, 3), CV_8UC1); // 자료형이 달라져서 또 다시 할당. cout << A << endl << endl; Mat B; int sizes[] = { 3,3 }; B.create(2, sizes, CV_8UC1); // 2차원의 3x3. Dimensions 명시적으로 표기 cout << "B= " << B << endl; return 0; }
참고해야 할 것은 사이즈나, 데이터 타입이 바뀔 경우 Mat::release()가 호출되어 이전의 메모리 할당을 해제하고, 새로운 메모리 공간을 할당받는다.
생성된 Mat클래스 객체를 imshow로 보이도록한다.
그냥 보이면 밋밋하니 색정보를 랜덤으로하여 출력한다.
#pragma warning(disable: 4819) #include "opencv.hpp" using namespace cv; using namespace std; int main() { Mat srcImage(512, 512, CV_8UC3); for (int i = 0; i < srcImage.rows; i++) { for (int j = 0; j < srcImage.cols; j++) { srcImage.at<Vec3b>(i, j) = Vec3b(rand() % (200 - 50) + 50, rand() % (200 - 50) + 50, rand() % (200 - 50) + 50); } } imshow("srcImage", srcImage); waitKey(); return 0; }
난해하다.. 색이 강렬해지지 않게 범위를 줄였지만.. 여전히 이런 이미지는 난해하게 느껴진다.
Mat 클래스 객체에는 행렬에 관한 여러가지 정보들이 있는데
rows, cols, dims, data, step이 기본적인 멤버 변수고
(data는 uchar타입의 포인터객체로 위의 srcImage.data[0]에 접근하면 0번째 값을 uchar형식으로 변환하여 출력한다. 다만 ionmaip.h를 이용하면 int형으로 출력가능)
Mat A(4,5, CV_32FC3); 를 가정하고
size_t total() // mat전체의 요소 갯수를 리턴. 4*5 = 20
bool isContinuous() // 각 행에 마지막에 공백없이 연속으로 데이터가 저장되었는지
size_t elemSize() // CV_32FC3이면 32bit(4bytes) * 3 = 12bytes
size_t elemSize1() // CV_32FC3이면 32bit = 4bytes
int type() // CV_32FC3이면 21(CV_32FC3) 리턴
int depth() // CV_32F 의 경우 2^5 = 32 이므로 depth = 5
int channels() // CV_32FC3은 C3이므로 channels = 3
size_t step // 한 row의 bytes. 12×5 = 60bytes
size_t step1(int i=0) // 각 step의 elemSize1()을 출력. 60 / 4 = 15
bool empty() // 의미상 isEmpty().
Size size() // [ 5 x 4 ]. 4×5가 아님을 유의하자.
의 멤버 함수가 존재한다.
at에 의한 행렬 요소 접근
#pragma warning(disable: 4819) #include "opencv.hpp" using namespace cv; using namespace std; int main() { Mat A(3, 3, CV_32F, Scalar(2)); int idx[2]; for (int i = 0; i < A.rows; i++) { for (int j = 0; j < A.cols; j++) { A.at<float>(i, j) = i * A.cols + j; A.at<float>(Point(j, i)) = i * A.cols + j; } } cout << A << endl; int nSumPoint = 0; int nSum = 0; int nSumIdx = 0; for (int i = 0; i < A.rows; i++) { for (int j = 0; j < A.cols; j++) { nSum += A.at<float>(i, j); nSumPoint += A.at<float>(Point(j, i)); idx[0] = i; idx[1] = j; nSumIdx += A.at<float>(idx); } } cout << "nSum : " << nSum << endl; cout << "nSumPoint : " << nSumPoint << endl; cout << "nSumIdx : " << nSumIdx << endl; return 0; }
각 요소를 하드 인덱스로 접근하는 방법과, Point(j, i), idx배열을 활용한 접근 모두 같은 결과를 보여준다.
다음으로는 nChannels 행렬을 접근해보도록 한다.
#pragma warning(disable: 4819) #include "opencv.hpp" using namespace cv; using namespace std; int main() { Mat A(3, 3, CV_64FC2); for (int i = 0; i < A.rows; i++) { for (int j = 0; j < A.cols; j++) { A.at<Vec2d>(i, j) = Vec2d(i, i*A.cols + j); } } cout << "A: (i, index)" << endl; cout << A << endl << endl << endl; A.create(3, 3, CV_32FC3); for (int i = 0; i < A.rows; i++) { for (int j = 0; j < A.cols; j++) { A.at<Vec3f>(i, j) = Vec3f(i, j, i*A.cols + j); } } cout << "A: (i,j, index)" << endl; cout << A << endl; return 0; }
차원 자체는 2차원이지만 각 요소는 3개의 채널값을 가지므로 접근은 at<Vec(n)f>(i,j)로 하고, 데이터 기록은 Vec(n)f(i1, i2, i3 , … in) 으로 한다.
4개의 댓글