유니티에서 Yolo를 이용한 웹캠 물체 인식
2023년 3월 12일 오후 6:27
유니티에서 Yolo를 이용하여 웹캠의 물체 인식을 하기 위해서는 먼저 Yolo를 설치해야 합니다. Yolo를 설치하고 나면, 다음과 같은 스크립트를 이용하여 물체 인식을 할 수 있습니다.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public class YoloObjectDetection : MonoBehaviour
{
[DllImport("yolo_cpp_dll", EntryPoint = "performDetect")]
public static extern void performDetect(
string cfgFilename, string weightFilename, string filename, float thresh, ref int numOutBoxes, ref Detection[] detections);
public string cfgFilePath;
public string weightsFilePath;
public RawImage imageDisplay;
public Texture2D defaultTexture;
public float detectionThreshold = 0.5f;
private Texture2D currentTexture;
private WebCamTexture webcamTexture;
private Color32[] colors;
private List<string> objectNames;
private Detection[] detections;
private int numOutBoxes;
void Start()
{
objectNames = new List<string>();
objectNames.Add("person");
objectNames.Add("bicycle");
objectNames.Add("car");
objectNames.Add("motorbike");
objectNames.Add("aeroplane");
objectNames.Add("bus");
objectNames.Add("train");
objectNames.Add("truck");
objectNames.Add("boat");
objectNames.Add("traffic light");
objectNames.Add("fire hydrant");
objectNames.Add("stop sign");
objectNames.Add("parking meter");
objectNames.Add("bench");
objectNames.Add("bird");
objectNames.Add("cat");
objectNames.Add("dog");
objectNames.Add("horse");
objectNames.Add("sheep");
objectNames.Add("cow");
objectNames.Add("elephant");
objectNames.Add("bear");
objectNames.Add("zebra");
objectNames.Add("giraffe");
objectNames.Add("backpack");
objectNames.Add("umbrella");
objectNames.Add("handbag");
objectNames.Add("tie");
objectNames.Add("suitcase");
objectNames.Add("frisbee");
objectNames.Add("skis");
objectNames.Add("snowboard");
objectNames.Add("sports ball");
objectNames.Add("kite");
objectNames.Add("baseball bat");
objectNames.Add("baseball glove");
objectNames.Add("skateboard");
objectNames.Add("surfboard");
objectNames.Add("tennis racket");
objectNames.Add("bottle");
objectNames.Add("wine glass");
objectNames.Add("cup");
objectNames.Add("fork");
objectNames.Add("knife");
objectNames.Add("spoon");
objectNames.Add("bowl");
objectNames.Add("banana");
objectNames.Add("apple");
objectNames.Add("sandwich");
objectNames.Add("orange");
objectNames.Add("broccoli");
objectNames.Add("carrot");
objectNames.Add("hot dog");
objectNames.Add("pizza");
objectNames.Add("donut");
objectNames.Add("cake");
objectNames.Add("chair");
objectNames.Add("sofa");
objectNames.Add("pottedplant");
objectNames.Add("bed");
objectNames.Add("diningtable");
objectNames.Add("toilet");
objectNames.Add("tvmonitor");
objectNames.Add("laptop");
objectNames.Add("mouse");
objectNames.Add("remote");
objectNames.Add("keyboard");
objectNames.Add("cell phone");
objectNames.Add("microwave");
objectNames.Add("oven");
objectNames.Add("toaster");
objectNames.Add("sink");
objectNames.Add("refrigerator");
objectNames.Add("book");
objectNames.Add("clock");
objectNames.Add("vase");
objectNames.Add("scissors");
objectNames.Add("teddy bear");
objectNames.Add("hair drier");
objectNames.Add("toothbrush");
currentTexture = defaultTexture;
webcamTexture = new WebCamTexture();
imageDisplay.texture = webcamTexture;
webcamTexture.Play();
colors = new Color32[416 * 416];
detections = new Detection[100];
}
void Update()
{
if (webcamTexture.width > 16 && webcamTexture.height > 16)
{
currentTexture.Resize(webcamTexture.width, webcamTexture.height);
currentTexture.SetPixels32(webcamTexture.GetPixels32());
currentTexture.Apply();
if (Input.GetKeyDown(KeyCode.Space))
{
performDetect(cfgFilePath, weightsFilePath, Application.dataPath + "/YOLO/" + "object_detection.jpg", detectionThreshold, ref numOutBoxes, ref detections);
for (int i = 0; i < numOutBoxes; ++i)
{
Detection det = detections[i];
string label = objectNames[det.classID];
int x = (int)det.bbox.x;
int y = (int)det.bbox.y;
int w = (int)det.bbox.w;
int h = (int)det.bbox.h;
DrawBox(currentTexture, x, y, w, h, label);
}
}
}
imageDisplay.texture = currentTexture;
}
void DrawBox(Texture2D tex, int x, int y, int w, int h, string label)
{
int labelWidth = 12 * label.Length;
int labelHeight = 16;
int labelX = x - labelWidth / 2;
int labelY = y - h - labelHeight / 2;
if (labelX < 0)
{
labelX = 0;
}
if (labelY < 0)
{
labelY = 0;
}
if (labelX + labelWidth > tex.width)
{
labelX = tex.width - labelWidth;
}
if (labelY + labelHeight > tex.height)
{
labelY = tex.height - labelHeight;
}
for (int i = x - w / 2; i < x + w / 2; i++)
{
tex.SetPixel(i, y - h / 2, Color.red);
tex.SetPixel(i, y + h / 2, Color.red);
}
for (int i = y - h / 2; i < y + h / 2; i++)
{
tex.SetPixel(x - w / 2, i, Color.red);
tex.SetPixel(x + w / 2, i, Color.red);
}
for (int i = labelX; i < labelX + labelWidth; i++)
{
for (int j = labelY; j < labelY + labelHeight; j++)
{
tex.SetPixel(i, j, Color.red);
}
}
GUI.Label(new Rect(labelX, labelY, labelWidth, labelHeight), label);
}
struct Detection
{
public float x, y, w, h, prob;
public int classID;
}
}
이 스크립트는 먼저 Yolo에서 인식할 물체들의 이름을 정의한 후, 웹캠에서 캡처한 화면에서 물체를 인식합니다. Space 키를 누르면 인식이 시작되며, 인식된 물체들은 빨간색 박스로 표시됩니다.
위의 스크립트를 유니티 프로젝트에 추가하고, Yolo의 cfg 파일과 weight 파일 경로를 지정해주면 웹캠에서 물체 인식을 할 수 있습니다.
다만, 이 방법은 학습을 하지 않고 물체 인식을 하는 방법이기 때문에 인식률이 낮을 수 있으며, 인식할 수 있는 물체도 미리 정의된 물체만 가능합니다. 따라서 정확한 물체 인식을 위해서는 Yolo를 학습시켜야 합니다.