유니티에서 OpenCV 사용하기 - 3.실전(이미지 전달,통신)

프로그래밍/OpenCV2019. 6. 20. 16:36

안녕하세요.

이번 포스팅에선 이제 본격적인 내용입니다. Visual Studio에서 C++로 작성된 함수를 dll파일을 만들고 이 함수를 유니티에서 호출하는 것이 목표입니다. 간단한 호출은 아니고 유니티(C#)과 DLL(C++)간의 데이터 통신을 포함합니다.

 

https://amin-ahmadi.com/2019/06/01/how-to-pass-images-between-opencv-and-unity/

영어로 되어 있긴 하지만 위의 글에 아주 정리가 잘 되어 있습니다. 위 글을 많이 참고 했으며 제가 내용을 좀 더 추가해서 쓰려고 합니다.

 

1. DLL 파일 만들기

 

비주얼 스튜디오에서 새 프로젝트를 만들어야합니다. 무료 버젼인 커뮤니티(Community) 버전에서 DLL 프로젝트가 안만들어지면 어쩌나 걱정했는데 만들 수 있습니다. 위 사진과 같이 DLL(동적 연결 라이브러리)를 선택해주세요. 프로젝트 이름은 적당히 하시면 됩니다. 저는 OpenCVDLL이라고 했습니다.

 

유니티에서 외부 DLL을 쓰려면 64비트로 만들어진 DLL만 쓸 수 있습니다. 그렇기에 비주얼 스튜디오에서 x86이 아닌 x64를 선택하도록 합니다.

 

자 이제 이 프로젝트에서 OpenCV관련 함수들을 사용할 수 있게 프로젝트 설정을 해야 합니다.

이 부분은 지난 포스팅을 참고해주세요.

 

2019/06/04 - [프로그래밍/OpenCV] - 유니티에서 OpenCV 사용하기 - 1.기본 환경 설정

2019/06/04 - [프로그래밍/OpenCV] - 유니티에서 OpenCV 사용하기 - 2.Visial C++ 기본 설정

 

프로젝트 설정이 제대로 됐다면 OpenCV관련 코드들을 사용해도 에러가 발생하지 않습니다.

 

프로젝트 이름은 OpenCVDLL로 했기에 OpenCVDLL.cpp파일이 생성되어 있습니다.

이 파일을 아래와 같이 수정해봅시다.

// OpenCVDLL.cpp : DLL 응용 프로그램을 위해 내보낸 함수를 정의합니다.
//

#include "stdafx.h"
#include "opencv2/core.hpp"
//#include <opencv2/opencv.hpp>

struct Color32
{
	uchar red;
	uchar green;
	uchar blue;
	uchar alpha;
};

extern "C"
{

	__declspec(dllexport) void FlipImage(Color32 **rawImage, int width, int height)
	{
		using namespace cv;

		Mat image(height, width, CV_8UC4, *rawImage);

		flip(image, image, -1);
	}
}

유니티에서 호출 가능한 DLL을 만들기 위해선 위와 같은 구조를 가져야 합니다. extern "C"와 __declspec(dllexport)가 추가된 것을 볼 수 있습니다.

 

빌드를 했을 때 위의 창과 같은 에러가 뜨는 정상적으로 빌드가 된 것입니다. dll파일은 윈도우에서 바로 실행이 안되기에 위와 같은 에러가 발생합니다.

 

생성된 파일은 프로젝트 폴더의 x64\Debug 폴더에 있습니다. OpenCVDLL.dll이라는 파일이 생성됐습니다. 이 파일과 이 dll에서 호출하는 것과 관련된 OpenCV dll파일을 유니티에 복사할 예정입니다.

 

 

 

2. 유니티 프로젝트 만들기

유니티에서 적당한 프로젝트를 만들어주세요. 저는 프로젝트 이름을 OpenCVDLLTest라고 지었습니다.

 

유니티에서 Assets 폴더 밑에 Plugin 폴더를 만들었습니다. 이 폴더에 opencv_core410d.dll파일과 OpenCVDLL.dll 파일을 드래그해서 복사했습니다.

 

black2.png
0.03MB

그리고 추가로 400x400 크기의 그냥 검은색 배경을 Assets 폴더에 복사했습니다.(위 파일)

 

추가된 black2파일을 클릭하면 Import Settings를 볼 수 있습니다. Advanced를 열어서 보면 Read/Write Enabled 옵션이 있습니다. 기본적으로는 체크가 되어있지 않습니다. 이 부분을 클릭하여 체크해줍니다. 그래야 이 유니티에서 이 파일 수정이 가능합니다. 수정 후 Apply 버튼을 클릭해주세요.

 

캔버스에 UI Image를 추가해줍니다. 추가된 Image의 속성에 Image(Script)속성이 있습니다. 여기의 Source Image에 방금 추가한 black2파일을 드래그하여 추가합니다.

 

이제 유니티쪽에서 간단하게 C# 코드를 짜보겠습니다. 새로운 스크립트를 생성합니다. 저는 MainScript라고 이름을 지었습니다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;


public class MainScript : MonoBehaviour
{
    public Button btnFlipImage;
    public Image imageBlack;

    [DllImport("OpenCVDLL")]
    private static extern void FlipImage(ref Color32[] rawImage, int width, int height);

    // Start is called before the first frame update
    void Start()
    {
        btnFlipImage.onClick.AddListener(CallFlipImage);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void CallFlipImage()
    {
        var blackImage = imageBlack.sprite.texture.GetPixels32();
        FlipImage(ref blackImage, 400, 400);
        imageBlack.sprite.texture.SetPixels32(blackImage);
        imageBlack.sprite.texture.Apply();
    }
}

생성된 C# 스크립트에는 위의 내용을 복사합니다.

 

저는 Main Camera에 방금 만든 C# 스크립트를 탑재?했습니다. 이렇게 해야 유니티 실행시 스크립트가 실행됩니다. 메인 카메라에 추가된 스크립트를 보면 C# 코드에서 public으로 선언한 Image와 Button이 있습니다. Image에는 아까 설정한 검은색 이미지를 드래그하여 채워 넣습니다. Button 부분에는 UI Button을 하나 생성하고 이를 연결해줍니다.

 

이제 실행하고 버튼을 눌러 봅시다. 버튼을 누를때마다 수평 뒤집기가 된다면 성공한 것입니다~!!

 

 

3. 문제 해결

혹시 위 사진과 같이

Plugins: Failed to load 'Assets/Plugin/OpenCVDLL.dll' with error '%1은(는) 올바른 Win32 응용 프로그램이 아닙니다.

에러가 발생하나요?

 

위 에러가 발생하면.. 비주얼 스튜디오에서 생성한 dll 파일에 문제가 있는 것입니다.

 

제 경우엔 위의 링커>일반>추가 라이브러리 디렉터리 쪽에 문제가 있더라구요.

정상적인 경우라면 위 사진처럼 %(AdditionalLibraryDirectories)가 있어야 합니다.

추가 라이브러리 디렉터리 수정 창을 띄워 부모 또는 프로젝트 기본값에서 상속에 체크를 해주면 문제가 해결됩니다.

 

관련 글

[유니티/안드로이드/Visual Studio] 안드로이드apk에서 unity 라이브러리 호출하기

작성자

Posted by 드리머즈

관련 글

댓글 영역