-
OpenCV Mat class 기초 사용법OpenCV/OpenCV_C++ 2023. 12. 12. 17:33
OpenCV에서 Mat은 자주 사용되며 행렬과 연관이 깊은 클래스이다.
https://mokchanic.tistory.com/91
OpenCV 주요 클래스
1. Point, Size, Rect Class - Point Class 2차원 점의 좌표 표현을 위한 템플릿 클래스 멤버 변수: x, y 멤버 함수: dot(), ddot(), cross(), inside() 등 다양한 사칙 연산에 대해 연산자 오버로딩과 std::cout 출력을 위
mokchanic.tistory.com
이번에는 예제를 직접 실행하며 Mat class에 대해 알아보자.
Example 1. 객체 생성 및 초기화
void MatOp1() { cv::Mat img1; // empty cv::Matrix cv::Mat img2(480, 640, CV_8UC1); // unsigned char, 1-channel cv::Mat img3(480, 640, CV_8UC3); // unsigned char, 3-channels cv::Mat img4(cv::Size(640, 480), CV_8UC3); // cv::Size(width, height) cv::Mat img5(480, 640, CV_8UC1, cv::Scalar(128)); // initial values, 128 cv::Mat img6(480, 640, CV_8UC3, cv::Scalar(0, 0, 255)); // initial values, red cv::Mat Mat1 = cv::Mat::zeros(3, 3, CV_32SC1); // 0's cv::Matrix cv::Mat Mat2 = cv::Mat::ones(3, 3, CV_32FC1); // 1's cv::Matrix cv::Mat Mat3 = cv::Mat::eye(3, 3, CV_32FC1); // identity cv::Matrix float data[] = { 1, 2, 3, 4, 5, 6 }; cv::Mat Mat4(2, 3, CV_32FC1, data); // 2rows, 3cols Matrix, float. data변수와 동기화됨. cv::Mat Mat5 = (cv::Mat_<float>(2, 3) << 1, 2, 3, 4, 5, 6); cv::Mat Mat6 = cv::Mat_<uchar>({ 2, 3 }, { 1, 2, 3, 4, 5, 6 }); Mat4.create(256, 256, CV_8UC3); // uchar, 3-channels Mat5.create(4, 4, CV_32FC1); // float, 1-channel Mat4 = cv::Scalar(255, 0, 0); Mat5.setTo(1.f); }
OpenCV에서는 RGB가 아닌 BGR을 기본 순서로 사용한다.
zeros는 0행렬, ones는 1행렬, eye는 단위 행렬(identity matrix)을 만들어준다.
create는 기존의 것을 지우고 새로 만들어준다. 대신 초기 값 지정할 수 있는 4번째 값은 지원하지 않는다.
Example 2. 객체의 참조와 복사
void MatOp2() { cv::Mat img1 = cv::imread("dog.bmp"); // 얕은 복사 cv::Mat img2 = img1; cv::Mat img3; img3 = img1; // img3(img1)과 같음. //깊은 복사 cv::Mat img4 = img1.clone(); cv::Mat img5; img1.copyTo(img5); img1.setTo(cv::Scalar(0, 255, 255)); // yellow imshow("img1", img1); imshow("img2", img2); imshow("img3", img3); imshow("img4", img4); imshow("img5", img5); cv::waitKey(); cv::destroyAllWindows(); }
Mat 객체에 대해 = 연산자는 참조(얕은 복사)를 수행한다.
Mat::clone() 또는 Mat::copyTo()함수를 이용하여 깊은 복사를 수행한다.
프로그램을 실행하면 img1이 노란색으로 바뀌는 것과 동시에 img2, img3도 노란색으로 바뀌지만, img4, img5는 그렇지 않음을 볼 수 있다.
Example 3. 부분 행렬 추출
void MatOp3() { cv::Mat img1 = cv::imread("cat.bmp"); if (img1.empty()) { std::cerr << "Image load failed!" << std::endl; return; } cv::Mat img2 = img1(cv::Rect(220, 120, 340, 240)); cv::Mat img3 = img1(cv::Rect(220, 120, 340, 240)).clone(); img2 = ~img2; // 이미지 반전 imshow("img1", img1); imshow("img2", img2); imshow("img3", img3); cv::waitKey(); cv::destroyAllWindows(); }
Rect로 img를 부분적으로 추출할 수 있다.
~는 Not연산으로 이미지 색상 반전을 해준다.
img2에서 반전이 되며, img1 부분도 해당 부분이 반전된 것을 볼 수 있다.
결과
Example 4. 영상의 픽셀 값 참조
영상의 픽셀 값에 접근할 수 있으며 OpenCV에서 제공하는 기능이 아닌, 자신만의 새로운 기능을 추가해야 하는 경우에 유용하다.
영상의 픽셀은 다음과 같이 접근할 수 있다.
Mat::data 사용 방법 메모리 연산이 잘못될 경우 프로그램이 비정상적으로 종료할 수 있다. Mat::at() 함수 사용 방법 좌표 지정이 직관적이며 임의 좌표에 접근할 수 있다. Mat::ptr() 함수 사용 방법 Mat::at()보다 빠르게 동작하며 행 단위 연산을 수행할 때 유리하다. Matiterator_ 반복자 사용 방법 좌표를 지정하지 않아서 안전하다. 성능은 느리다. 기본적으로 Mat::data 멤버 변수가 픽셀 데이터 메모리 공간을 가리키지만, Mat 클래스 멤버 함수를 사용하는 방법을 권장한다.
void MatOp4() { cv::Mat Mat1 = cv::Mat::zeros(3, 4, CV_8UC1); for (int y = 0; y < Mat1.rows; y++) { for (int x = 0; x < Mat1.cols; x++) { Mat1.at<uchar>(y, x)++; // at 접근 } } for (int y = 0; y < Mat1.rows; y++) { uchar* p = Mat1.ptr<uchar>(y); // ptr 접근 for (int x = 0; x < Mat1.cols; x++) { p[x]++; } } for (cv::MatIterator_<uchar> it = Mat1.begin<uchar>(); it != Mat1.end<uchar>(); ++it) { (*it)++; // 반복자 접근 } std::cout << "cv::Mat1:\n" << Mat1 << std::endl; }
Example 5. 행렬 연산
행렬의 연산은 다음과 같이 할 수 있으며 inverse, transpose등의 연산도 가능하다.
void MatOp5() { float data[] = { 1, 1, 2, 3 }; cv::Mat Mat1(2, 2, CV_32FC1, data); std::cout << "cv::Mat1:\n" << Mat1 << std::endl; cv::Mat Mat2 = Mat1.inv(); // inverse 연산 std::cout << "cv::Mat2:\n" << Mat2 << std::endl; std::cout << "cv::Mat1.t():\n" << Mat1.t() << std::endl; // transpose 연산 std::cout << "cv::Mat1 + 3:\n" << Mat1 + 3 << std::endl; std::cout << "cv::Mat1 + cv::Mat2:\n" << Mat1 + Mat2 << std::endl; std::cout << "cv::Mat1 * cv::Mat2:\n" << Mat1 * Mat2 << std::endl; }
결과
'OpenCV > OpenCV_C++' 카테고리의 다른 글
OpenCV 유용한 함수 (2) 2023.12.21 OpenCV Draw & Event (0) 2023.12.14 OpenCV VideoCapture class (0) 2023.12.13 OpenCV 주요 클래스 (1) 2023.11.27 OpenCV 기초 및 편하게 사용하기 (2) 2023.11.26