Programing/OpenCV

#OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝 - 3

CouqueD'asse 2022. 5. 19. 16:29

3.2.2 행렬의 생성과 초기화

// 생성과 동시에 원소 값 저장을 위한 메모리 공간 할당에 대한 생성자
Mat::Mat(int rows, int cols, int type);
// 행렬의 크기 지정
Mat::Mat(Size size, int type);
// 생성과 동시에 모든 원소 값을 특정 값으로 초기화
Mat::Mat(int rows, int cols, int type, const Scalar& s);
Mat::Mat(Size size, int type, cpnst Scalar& s);
// Scalar 영상의 픽셀 값을 표현
Mat img1(480, 640, CV_8UC1, Scalar(128);
Mat img2(480, 640, CV_8UC3, Scalar(0, 0, 128);
// 모든 원소가 0으로 초기화된 행렬
static MatExpr Mat::zeros(int rows, int cols, int type);
static MatExpr Mat::zeros(Size size, int type);
// 0으로 초기화된 3x3 정수형 행렬
Mat mat1 = Mat::zeros(3,3, CV_32SC1);
// 비어 있는 Mat 객체 또는 이미 생성된 Mat 객체에 새로운 행렬을 할당
void Mat::create(int rows, int cols, int type);
void Mat::create(Size size, int type);
mat3.create(4,4 CV_32FC1);
mat4.cerate(256,256, CV_8UC3);
// 원소 값을 초기화
mat3.setTo(1.f);
mat4 = Scalar(255, 0, 0);
// Mat 객체 생성
void MatOp1()
{
	Mat img1;
	Mat img2(480, 640, CV_8UC1);
	Mat img3(480, 640, CV_8UC3);
	Mat img4(Size(640, 480), CV_8UC3);

	Mat img5(480, 640, CV_8UC1, Scalar(128));
	Mat img6(480, 640, CV_8UC3, Scalar(0, 0, 225));

	Mat mat1 = Mat::zeros(3, 3, CV_32SC1);
	Mat mat2 = Mat::ones(3, 3, CV_32FC1);
	Mat mat3 = Mat::eye(3, 3, CV_32FC1);

	float data[] = { 1, 2, 3, 4, 5, 6 };
	Mat mat4(2, 3, CV_32FC1, data);

	Mat mat5 = (Mat_<float>(2, 3) << 1, 2, 3, 4, 5, 6);
	Mat mat6 = Mat_<uchar>({ 2,3 }, { 1,2,3,4,5,6 });

	mat4.create(256, 256, CV_8UC3);
	mat5.create(4, 4, CV_32FC1);

	mat4 = Scalar(255, 0, 0);
	mat5.setTo(1.f);
}

 

3.2.3 헹렬의 복사

얕은 복사 : 픽셀 데이터 공유

깊은 복사 : 메모리 공간을 새로 할당하여 픽셀 데이터 전체를 복사

// 깊은 복사
Mat Mat::clone() const;
void Mat::copyTo(OutputArray m) const;
void Mat::copyTo(OutputArraym, InputArray mask) const;
void MatOp2()
{
	Mat img1 = imread("char.png");

	Mat img2 = img1;
	Mat img3;
	img3 = img1;

	Mat img4 = img1.clone();
	Mat img5;
	img1.copyTo(img5);

	img1.setTo(Scalar(0, 255, 255));

	imshow("img1", img1);
	imshow("img2", img2);
	imshow("img3", img3);
	imshow("img4", img4);
	imshow("img5", img5);

	waitKey();
	destroyAllWindows();
}

 

3.2.4 부분 행렬 추출

// 괄호 연산자 재정의 함수의 원형
Mat Mat::operator()(const Rect& roi) const;
Mat Mat::operator()(Range rowRange, Range colRange) const;
// 영상의 부분 영상 반전
void MatOp3()
{
	Mat img1 = imread("char.png");
	if (img1.empty())
	{
		cerr << "Img load Failed!" << endl;
		return;
	}

	Mat img2 = img1(Rect(120, 20, 50, 50));
	Mat img3 = img1(Rect(120, 20, 50, 50)).clone();

	img2 = ~img2;

	imshow("img1", img1);
	imshow("img2", img2);
	imshow("img3", img3);

	waitKey();
	destroyAllWindows();
}

 

3.2.5 행렬의 원소 값 참조

// 직관적인 행렬 원소 접근 방법
template<typename _Tp> _Tp& Mat::at(imt y, imt x);
// 특정 행의 첫번째 원소 주소를 반환
template<typename _Tp> _Tp* Mat::ptr(int y);
// 행렬의 원소 값 참조 방법을 이용하여 원소 값 증가
void MatOp4()
{
	Mat mat1 = Mat::zeros(3, 4, CV_8UC1);
	for (int j = 0; j < mat1.rows; j++)
	{
		for (int i = 0; i < mat1.cols; i++)
		{
			mat1.at<uchar>(j, i)++;
		}
	}

	for (int j = 0; j < mat1.rows; j++)
	{
		uchar* p = mat1.ptr<uchar>(j);
		for (int i = 0; i < mat1.cols; i++)
		{
			p[i]++;
		}
	}

	for (MatIterator_<uchar> it = mat1.begin<uchar>(); it != mat1.end<uchar>(); ++it)
	{
		(*it)++;
	}

	cout << "mat1:\n" << mat1 << endl;

}

 

3.2.6 행렬 정보 참조하기

void MatOp5()
{
	Mat img1 = imread("char.png");

	cout << "Width : " << img1.cols << endl;
	cout << "Height : " << img1.rows << endl;
	cout << "Channels : " << img1.channels() << endl;

	if (img1.type() == CV_8UC1)
	{
		cout << "img1 is grayscale img." << endl;
	}
	else if (img1.type() == CV_8UC3)
	{
		cout << "img1 is a truecolor img." << endl;
	}

	float data[] = { 2.f, 1.1414f, 3.f, 1.732f };
	Mat mat1(2, 2, CV_32FC1, data);
	cout << "mat1 : \n" << mat1 << endl;
}

 

3.2.7 행렬 연산

void MatOp6()
{
	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;
}

 

3.2.8 크기 및 타입 변환 함수

// 타입 변환
void Mat::comvertTo(OutputArray m, int rtype, double alpha=1, double beta=0) const;
// 주어진 행렬의 크기 또는 채널 수 변경
Mat Mat::reshape(int cn, int rows=0) const;
// 행렬의 행 크기 변경
void Mat::resize(size_t sz);
void Mat::resize(size_t sz, const Scalar& s);
void MatOp7()
{
	Mat img1 = imread("C:\\Users\\jinse\\Pictures\\char.png", 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;

	Mat mat3 = Mat::ones(1, 4, CV_8UC1) * 255;
	mat1.push_back(mat3);
	cout << "mat1:\n" << mat1 << endl;

	mat1.resize(6, 100);
	cout << "mat1:\n" << mat1 << endl;
}