Search
Duplicate

OpenCV C++/ OpenCvSharp의 Mat 데이터를 C++ DLL로 보내기

OpenCvSharp의 Mat 데이터를 C++로 보내기

UI 부분은 C#으로 구현하고, 성능과 관련된 부분은 C++로 구현하는 경우가 많다.
이런 환경에서 OpenCV를 사용해야 하는 경우, 다음과 같이 C#의 Mat 데이터 —OpenCvSharp이 제공하는— 를 C++ DLL로 보낼 수 있다.
우선 C#에서 Mat 데이터를 받아서 처리하는 로직을 가진 C++ 함수가 다음과 같이 생겼다고 하자.
// OpenCV의 uchar는 unsigned char의 축약형 표현이다. bool WriteImage(unsigned char* source, int width, int height, int type, int channels) { // height(rows), width(cols), type을 이용해서 빈 Mat을 만든다. Mat img(height, width, type); // width * height * channels을 이용해서 크기를 구한다. int size = width * height * channels; // C#에서 받은 source 데이터를 memcpy_s를 이용해서 비어 있는 Mat에 복사한다. // C#에서 받은 것은 수정이 불가능하기 때문에 이렇게 복사해서 사용한다. memcpy_s(img.data, size, source, size); // 적절한 위치에 복사하고 종료 return imwrite(path, img); }
C++
위의 C++ 함수를 사용하는 C# 코드는 아래와 같다.
// NAME_DLL은 C++ DLL의 경로 // C++의 unsigned char는 C#에서 byte와 동일하다. // 포인터 형태로 전달해야 하므로 unsafe 키워드를 사용한다. [DllImport(NAME_DLL)] unsafe internal extern static bool WriteImage(byte* source, int width, int height, int type, int channels); void WriteImage() { // 적절한 경로의 이미지를 읽는다. using (Mat source = Cv2.ImRead(path)) { // pointer를 사용해야 하므로 unsafe 블록을 설정한다. unsafe { // C++ 함수를 호출한다. source.Data 에 C++로 넘길 정보가 담겨 있다. bool result = NativeMethod.WriteImage(source: (byte*)source.Data, width: source.Width, height: source.Height, type: source.Type(), channels: source.Channels()); } } }
C#
C++에서 C#으로 Mat 데이터를 보내는 내용은 생략. 만일 C++에서 C#으로 보내야 한다면 다음 글을 참조할 것
참고로 C#에서 Mat 데이터를 수정한 후에 C++로 보내는 경우도 존재할 수 있는데, resize나 blur를 먹이는 것 등은 문제 없지만, C#에서 Sub Mat —이미지 내의 특정 영역만 추출하는— 을 구한 후에 C++로 전달하면 C++에서 데이터를 제대로 변환할 수 없다. 코드상에서 에러가 발생하지 않기 때문에 최종 결과를 보고 잘못된 부분을 찾는데 고생할 수 있음.
따라서 C++에서 처리해야 하는 이미지의 Sub Mat을 구해야 한다면, x, y, width, height만 보내서 C++에서 Sub Mat을 구하도록 하는 편이 낫다.

참조 자료