Mat 클래스 기초 사용법

강형우·2022년 11월 29일
0

OpenCV

목록 보기
11/17

영상의 생성과 초기화

Mat 클래스 객체의 생성과 초기화 예제 코드

void MatOp1()
{
	Mat img1; 	// empty matrix
	// 인자는 각각 행의 크기, 열의 크기, 타입을 지정.
	Mat img2(480, 640, CV_8UC1);		// unsigned char, 1-channel
	Mat img3(480, 640, CV_8UC3);		// unsigned char, 3-channels
	Mat img4(Size(640, 480), CV_8UC3);	// Size(width, height)
	// 4번째 인자는 Scalar라는 객체의 형태로 초기값을 지정
	Mat img5(480, 640, CV_8UC1, Scalar(128));		// initial values, 128
	Mat img6(480, 640, CV_8UC3, Scalar(0, 0, 255));	// initial values, red

	//Mat class의 생성자를 이용해서 새로운 영상데이터를 만들고 초기화 할 수 있다.
	
    // Mat class에서 제공하는 몇몇 정적 멤버함수를 이용하여 새로운 행렬객체를 만들 수 있다.
    // 인자는 각각 행의 크기, 열의 크기, 타입이다.
	Mat mat1 = Mat::zeros(3, 3, CV_32SC1);	// 0's matrix 0으로 채워져 있는 3x3행렬
	Mat mat2 = Mat::ones(3, 3, CV_32FC1);	// 1's matrix 1로 채워져 있는 3x3행렬
	Mat mat3 = Mat::eye(3, 3, CV_32FC1);	// identity matrix 3x3 단위행렬

	float data[] = {1, 2, 3, 4, 5, 6};
    // 4번째 인자는 주소값을 지정하게 되면 이 주소가 가리키고 있는 위치에서 이 행렬의 원소값을 참조해라 라는 형태로 동작하게 된다.
	Mat mat4(2, 3, CV_32FC1, data);
	// cout << mat4 << endl;[1,2,3
    //                       4,5,6];
    // data[0] = 100;
    // cout <<mat4 << endl; [100,2,3,
    //                        4,5,6];
    // 이런 식으로 짜면 서로 상호 동기화가 됨.
    // mat4의 값이 바뀌면 data의 값이 바뀌고, data의 값이 바뀌면 mat4의 값도 바뀌게 됨
    
    
	Mat mat5 = (Mat_<float>(2, 3) << 1, 2, 3, 4, 5, 6);
	Mat mat6 = Mat_<uchar>({2, 3}, {1, 2, 3, 4, 5, 6});
	
    
    // 초기값을 지정하는 4번째 인자는 지원하지 않음.
	mat4.create(256, 256, CV_8UC3);	// uchar, 3-channels
	mat5.create(4, 4, CV_32FC1);	// float, 1-channel
	
    // 추후에 설정해야함
	mat4 = Scalar(255, 0, 0);
	mat5.setTo(1.f);
}

영상의 참조와 복사

Mat 클래스 객체의 참조와 보갓

  • Mat객체에 대해 = 연산자는 참조(얕은 복사)를 수행
  • Mat::clone() 또는 Mat::copyTo() 함수를 이용하여 깊은 복사를 수행
void MatOp2()
{
	Mat img1 = imread("dog.bmp");

	// 이런식으로 할 경우 참조가 됨
	Mat img2 = img1;
	Mat img3;
	img3 = img1;


	// 이런식으로 할 경우 깊은복사가 됨
	Mat img4 = img1.clone();
	Mat img5;
	img1.copyTo(img5);

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

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

	waitKey();
	destroyAllWindows();
}
  • Mat 클래스 객체의 참조와 복사
  • 깊은복사의 경우 분리된 형태의 메모리 공간을 사용하기에 원본영상을 변경해도 영향을 미치지 않음

부분 영상 추출

Mat 클래스 객체에서 부분행렬 추출

  • Mat 객체에 대해 ()연산자를 이용하여 부분 영상 추출 가능
  • ()연산자 안에는 Rect 객체를 지정하여 부분 영상의 위치와 크기를 지정
  • 참조를 활용하여 ROI(Region of interest)연산 수행 가능

영상의 픽셀 값 참조

Mat 영상의 픽셀 값 접근하기

  • OpenCV에서 제공하는 기능이 아니라 자신만의 새로운 기능을 추가해야 하는 경우에 유용
  • 기본적으로 Mat:data 멤버 변수가 픽셀 데이터 메모리 공간을 가리키지만, Mat 클래스 멤버 함수를 사용하는 방법을 권장

Mat::at() 함수 사용방법

template<typename _Tp> _Tp& Mat::at(int y, int x)
  • y: 참조할 행 번호
  • x: 참조할 열 번호
  • 반환값: (_Tp& 타입으로 캐스팅 된)y행 x열 원소 값(참조).
  • 사용예제:
Mat mat1 = Mat::zeros(3,4,CV_8UC1):
for (int y=0; y < mat1.cols; x++)
{
	for (int x = 0; x < mat1.cols; x++)
    {
    	mat1.at<uchar>(y, x)++;
    }
}

Mat::ptr() 함수 사용방법

template<typename _Tp> _Tp* Mat::ptr(int y)
  • y: 참조할 행 번호
  • 반환값: (_Tp* 타입으로 캐스팅 된)y행의 시작 주소.
  • 사용예제:
for (int y=0; y < mat1.rows; y++)
{
	uchar* p = mat1.ptr<uchar>(y); // y값으로 행을 변경할 수 있다.
	for (int x = 0; x < mat1.cols; x++)
    {
    	p[x]++;
    }
}

Matlterator_<T>반복자 사용 방법

  • OpenCV는 Mat 클래스와 함께 사용할 수 있는 반복자 클래스 템플릿 Matlterator_ 를 제공
  • Matlterator_ 는 클래스 템플릿이므로 사용할 때에는 Mat 행렬 타입에 맞는 자료형을 명시해야함
  • Mat::begin() 함수는 행렬의 첫 번째 원소 위치를 반환
  • Mat::end() 함수는 행렬의 마지막 원소 바로 다음 위치를 반환
for (MatIterator_<uchar> it = mat1.begin<uchar>(); it != mat1.end<uchar>(); ++it)
{
	(*it)++;
}

  • 성능면에서 뛰어난 것이 아니므로 앞에서 사용한 at이나 ptr을 사용하는것이 유리하다.

기초 행렬 연산

Mat 클래스 기본 행렬 연산

void MatOp5()
{
	float data[] = {1, 1, 2, 3};
	Mat mat1(2, 2, CV_32FC1, data);
	cout << "mat1:\n" << mat1 << endl;
	// inv() = 역행열을 구하는 함수
	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;
}

0개의 댓글