안녕하세요. 갭동입니다.
이번 포스팅에선 opencv 4.6.0버전 이상에서 사용가능한 cv::Mat의 채널 포맷 구조를 변경할 수 있는 transposeND() 함수에 대해 알아보고자 합니다.
OpenCV를 사용하는 방법을 알고 싶으시다면 아래 링크를 참고해 주세요
2023.08.29 - [개발/OpenCV] - [OpenCV/C++] OpenCV 설치 및 Visual Studio에서 OpenCV 사용하는 방법 - 프로젝트 설정
목적
AI 추론엔진 / 모델에 데이터를 넣어주기 위해 NCHW나 NHWC의 포맷으로 데이터를 만들어야 하는데, 데이터를 복사해서 새로운 객체등을 만들기가 어렵기도 하고 번거롭기도 합니다.
특히 C++에서는 4차원(4 dimensions)이상의 다차원 데이터 cv::Mat은 rows나 cols가 -1로 설정되어 데이터를 가공하는게 어렵습니다. transposeND 함수를 사용해서 간단하게 바꿔보도록 하겠습니다.
cv::transposeND() 함수 설명
cv::transposeND 함수를 살펴보면 inputArray, MatShape, OutputArray를 넣으라고 되어있습니다.
저희는 inputarray / outputarray에 cv::Mat을 넣어줄 겁니다.
input에 담겨져 나오길 원하신다면 input과 output에 같은 cv::Mat을 넣어줘도 됩니다.
MatShape이 문제인데 살펴보면 outputarray은 인풋과 같은 타입으로 나온다고 합니다.
즉 4차원이면 4차원으로 나온다는 겁니다. 4차원을 다른 차원으로 바꾸지는 않는 것 같습니다.
그리고 0~N-1 까지의 축의 순서를 정하라고 나오는데 밑에 예시 코드를 보면서 이해하시면 될 것 같습니다.
코드(사용법)
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
int main()
{
cv::Mat img = cv::imread("testimage.jpg"); /* 이미지 파일 경로 */
/* 추론 엔진에 넣기 위한 blob */
cv::Mat blob = cv::dnn::blobFromImage(img, 1.0, cv::Size(img.cols, img.rows), cv::Scalar(), true, false, CV_32F);
/* blob 채널 크기 표시 */
std::cout << "----------------before----------------" << std::endl;
for (int i = 0; i < 4; i++)
{
std::cout << "blob [" << i << "] = " << blob.size[i] << std::endl;
}
/* 채널 순서 바꾸기 */
// 0 = N (batchsize)
// 1 = C (channel)
// 2 = H (height)
// 3 = W (width)
std::vector<int> order = { 0,2,3,1 }; /* N, H, W, C */
cv::transposeND(blob, order, blob);
std::cout << "----------------after----------------" << std::endl;
for (int i = 0; i < 4; i++)
{
std::cout << "blob [" << i << "] = " << blob.size[i] << std::endl;
}
return 0;
}
가로 630 x 세로 945의 testimage.jpg로 테스트해보겠습니다.
함수 동작 결과 및 원리 설명
위의 코드를 실행하면 blob의 transposeND 전/후 구조가 나옵니다.
transposeND이전의 cv::Mat의 구조는 0~3까지 순서로 NCHW로 나옵니다.
N : 1 / C: 3 / H : 945 / W : 630
코드에서 std::vector<int> order로 이 순서를 {0, 2, 3, 1}의 순서로 바꾸겠다라고 함수에 전달하면
cv::Mat의 포맷이 아래 그림과 같이 바뀌게 됩니다.
N : 1 / H : 945 / W : 630 / C: 3
order에 의해 변경되는걸 다음과 같이 표현할 수 있겠습니다.
기존의 0,1,2,3이던 포맷을 0,2,3,1 순서로 변경하게 됩니다.
따라서 NCHW to NHWC로 포맷이 변경되었습니다.
같은 원리로 NHWC to NCHW의 변환도 가능합니다.