OpenCV

[Unity] OpenCV+Unity 사진에서 인물 감별

Dean83 2022. 3. 29. 17:39

사진을 통해 인물을 감별하는 예제코드. 딥러닝 파일이 특정 인물에 대한 파일이 있어 해당 인물이 누군지 감별함

Scene 명칭 : FaceDetectorScene

 

사용되는 딥러닝 결과 파일 

haarcascade_frontalface_default.xml

face-recognizer.xml

 

1. 스크립트 시작시, Awake에서 위 두개의 파일을 읽어 내용을 메모리에 할당함.

FileStorage storageFaces = new FileStorage(faces.text, FileStorage.Mode.Read | FileStorage.Mode.Memory);
cascadeFaces = new CascadeClassifier();

recognizer = FaceRecognizer.CreateFisherFaceRecognizer();
recognizer.Load(new FileStorage(recognizerXml.text, FileStorage.Mode.Read | FileStorage.Mode.Memory));

//인식할 사람들의 이름. recognizer 파일에 순차적으로 해당인물의 정보가 들어있다.
names = new string[] { "Cooper", "DeGeneres", "Nyongo", "Pitt", "Roberts", "Spacey"	};

 

2. Start 함수에서 얼굴인식 진행

    - 샘플이미지를 읽어 Mat 형태로 변경

    Mat image = Unity.TextureToMat(this.sample);

    - 이미지를 회색으로 변경 (인식률 향상을 위함) 후 얼굴 인식

var gray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
Cv2.EqualizeHist(gray, gray);

// detect matching regions (faces bounding)
OpenCvSharp.Rect[] rawFaces = cascadeFaces.DetectMultiScale(gray, 1.1, 6);

    - 인식한 얼굴형태의 데이터에서, recognizer를 이용하여 특정 인물 인식

var grayFace = new Mat(gray, faceRect);

//인물인식할 때 요구하는 사이즈로 리사이즈
if (requiredSize.Width > 0 && requiredSize.Height > 0)
    grayFace = grayFace.Resize(requiredSize);
    
int label = -1;
double confidence = 0.0;

//실제 인물을 인식
recognizer.Predict(grayFace, out label, out confidence);

bool found = confidence < 1200;
//결과값이 1200 미만일경우 초록색, 1200 이상일경우 빨간색 박스를 그린다.
//confidence 값이 낮을수록 좋은것이고, 높을수록 확률이 떨어짐.

Scalar frameColor = found ? Scalar.LightGreen : Scalar.Red;
Cv2.Rectangle((InputOutputArray)image, faceRect, frameColor, 2);

     - 모두 인식 후 화면에 표시 (Mat 를 texture로 변경)

var texture = Unity.MatToTexture(image);
var rawImage = gameObject.GetComponent<UnityEngine.UI.RawImage>();
rawImage.texture = texture;

var transform = gameObject.GetComponent<UnityEngine.RectTransform>();
transform.sizeDelta = new UnityEngine.Vector2(image.Width, image.Height);

 

인식된 얼굴에 다른 이미지 덧씌우기는 https://dean83.tistory.com/65 참조.

//반복문 안에 아래의 코드를 넣음. 
//testrect는 recttransform 으로서, 덮어쓸 이미지가 담기는 rawumage 임
//anchor가 센터 이므로, 실제 이미지의 좌우 사이즈 / 2 를 가지고 좌표이동을 함.

RectTransform trans = Instantiate(testrect);

trans.parent = testrect.parent;

float a = image.Width / 2;
float b = image.Height / 2;

trans.anchoredPosition = new Vector3(faceRect.X - a, -(faceRect.Y) + b);
trans.sizeDelta = new Vector2(faceRect.Width, faceRect.Height);
trans.localScale = testrect.parent.localScale;
trans.gameObject.SetActive(true);