[python]OpenCV 공부노트 Mat3

글쓴이 Engineer Myoa 날짜

[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개의 댓글

답글 남기기

Avatar placeholder

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