[python]OpenCV 공부노트 Mat2

글쓴이 Engineer Myoa 날짜

[python]OpenCV 공부노트 Mat

에 이어서 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개의 댓글

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다