brunch

You can make anything
by writing

C.S.Lewis

by 서준수 Mar 28. 2019

Google FaceTracker 예제

Mobile Vision

FaceTracker 예제 분석


구글에서 제공하는 Face Tracking API 예제에 대해서 간단히 살펴본 내용이다.

튜토리얼에서 설명하고 있는 코드와 실제 Git에서 받은 코드 내용은 조금 차이가 있다. (코드가 업데이트된 것 같음) 이 문서는 Git에 있는 코드를 기준으로 재작성한 것이다.


튜토리얼 : https://developers.google.com/vision/android/face-tracker-tutorial

Git : https://github.com/googlesamples/android-vision/tree/master/visionSamples/FaceTracker


Git에서 받은 예제를 실행하면 후면 카메라가 켜지고 얼굴이 인식된다.

Change 버튼은 예제에는 없다. 개인적으로 추가한 버튼으로 전면 카메라로 전환시켜주는 역할을 한다.


속도 모드 / 정확도 모드


이 예제는 여러 명의 얼굴을 동시에 인식할 수 있다. 인식된 각 얼굴의 대략적인 위치와 크기를 사각형으로 표시해준다. 또한 좌우 눈을 뜨고 있는지 감고 있는지에 대판 판별, 웃고 있는지에 대한 판별, 각 얼굴에 대한 ID를 표시해준다.


FaceDetector 객체 생성하기 


FaceDetector detector = new FaceDetector.Builder(context)
         .setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)
         .build();



이때 FaceDetector에 대한 설정 값을 지정할 수 있다.


landmarks = 0 : int 값이며 기본값은 0임. 눈코입 등을 인식에 관련된 것이므로 해당 예제에서는 사용하지 않음. 따라서 이 기능을 끄면 얼굴 추적이 빨라진다.


prominent face only = false : 주요 얼굴 하나만 추적할 경우 true로 설정함. 하나만 추적할 경우 추적 속도가 빨라짐. 해당 예제에서는 여러 얼굴을 추적할 것이므로 false로 설정함.


classifications = FaceDetector.ALL_CLASSIFICATIONS(=1) : 좌우   눈을 뜨고 있는지 감고 있는지에 대판 판별, 웃고 있는지에 대한 판별 기능을 켜기 위해서 1을 설정함. 이 기능을 끄면 얼굴 추적이 빨라짐.


tracking = true : 각 얼굴에 대해 일관된 ID를   유지하는 데 사용. false로 설정하면 동일한 얼굴에 대한 ID 값이   변경될 수 있음. true로 설정해도 ID가 변경되는 경우가 존재함.


- 오버레이(사각형)가 깜박이면서 색상이 변하는 경우. 이것은 감지할 수 있는 한계에 근접한 감지가 발생했다는 것을 의미한다. 쉬운 예를 들면 감지가 풀렸다가 다시 감지되는 경우.


- 얼굴을 가리거나 카메라에서 촬영범위를 벗어났다가 다시 인식되는 경우. 즉 얼굴이 보이지 않은 동안에 tracking 정보를 재설정함.


mode = 0 : 정확도(mode=1)보다 속도(mode=0)를 우선시하도록 설정함. 값을 1로 세팅하면 카메라를 쳐다보지 않은 옆모습도 인식을 함.


min face size : 인식할 얼굴의 최소 크기를 지정할 수 있음. 범위는 0.0F ~ 1.0F임. 큰 값을 지정할수록 얼굴이 카메라 가까이 위치하여 크게 보여야 인식됨.



FaceDetector의 기본 설정값은 다음과 같다.


public static class Builder {
     private final Context mContext;
     private int aEN = 0; // landmarks
     private boolean aEO = false; // prominent face only
     private int aEP = 0; // classifications
     private boolean aEQ = true; // tracking
     private int Dr = 0; // mode
     private float aER = -1.0F; // min face size

...

...

}



설정값을 변경하는 함수는 다음과 같다.


setLandmarkType(int var1)

setProminentFaceOnly(boolean var1)

setClassificationType(int var1)

setTrackingEnabled(boolean var1)

setMode(int var1)

setMinFaceSize(float var1)



FaceDetector 객체가 생성되면 얼굴 인식 결과를 수신하기 위한 관련 프로세서 파이프 라인을 생성할 수 있다.


detector.setProcessor(
         new MultiProcessor.Builder<>(new GraphicFaceTrackerFactory())
                 .build());



CameraSource 생성하기

그 후, 카메라로부터 비디오 이미지를 얻기 위한 CameraSource를 만들고, Detector 및 관련 프로세서 파이프 라인으로 해당 이미지를 연속적으로 스트리밍 한다.


mCameraSource = new CameraSource.Builder(context, detector)
         .setRequestedPreviewSize(640, 480)
         .setFacing(CameraSource.CAMERA_FACING_BACK)

        .setRequestedFps(30.0f)
         .build();



예제 코드에서는 사용자에게 카메라 비디오 및 그래픽 오버레이를 보여주기 위해서 CameraSourcePreview UI를 사용한다.

다음과 같이 UI를 초기화하고 카메라를 시작한다.


mPreview.start(mCameraSource, mGraphicOverlay);



여기까지의 코드로 작성된 파이프 라인은 다음과 같다.


카메라와 Face Tracker 파이프라인

이미지 출처 : 구글 문서


카메라가 시작되면 계속해서 미리 보기 이미지를 파이프 라인으로 보낸다.

CameraSource 구성 요소는 이러한 이미지를 수신하고 앞서 설정한 것처럼 초당 30 프레임으로 이미지를 Detector에 전달한다. (참고 : 카메라 프레임이 Detector가 처리할 수 있는 속도보다 빨리 도달하면 카메라 소스가 속도를 따라가기 위해서 프레임을 드롭한다.)


 FaceDetector는 카메라로부터 수신된 각각의 이미지 프레임에서 다수의 얼굴을 검출할 수 있다. 각 얼굴은 위의 tracking 설정(true)으로 지정된 구별할 수 있는 얼굴 ID에 해당한다.


MultiProcessor는 보이는 얼굴 ID마다 Tracker <Face> 인스턴스를 만든다.


예제 코드에서 제공하는 GraphicFaceTrackerFactory를 사용하여 필요에 따라 새로운 face tracker 인스턴스를 만든다. (참고 : MultiProcessor는 임의의 수의 탐지된 항목(얼굴)을 처리하기 위한 구성 요소다.)


private class GraphicFaceTrackerFactory implements MultiProcessor.Factory<Face> {
     @Override
  public Tracker<Face> create(Face face) {
         return new GraphicFaceTracker(mGraphicOverlay);
     }
 }



새로운 얼굴이 나타나면 멀티 프로세서는 각 얼굴에 대한 새로운 GraphicFaceTracker 인스턴스를 만들기 위해서 GraphicFaceTrackerFactory를 사용할 것이다.


시간에 따라 얼굴이 움직이면 업데이트가 각 face tracker 인스턴스로 전달된다. 얼굴이 더 이상 보이지 않으면 멀티 프로세서는 연관된 face tracker 인스턴스를 없앨 것이다. 이 방법으로 앱에서 마주치는 각 얼굴에 대한 개별 face tracker를 동적으로 생성 / 추적 / 파괴한다.


아래는 각각의 얼굴과 관련된 상태를 유지하는 GraphicFaceTracker을 구현한 것이다.


private class GraphicFaceTracker extends Tracker<Face> {
       private GraphicOverlay   mOverlay;
       private FaceGraphic   mFaceGraphic;
   
       GraphicFaceTracker(GraphicOverlay   overlay) {
           mOverlay = overlay;
           mFaceGraphic = new FaceGraphic(overlay);
       }
   
       /**
        * Start tracking the detected face   instance within the face overlay.
        */
       @Override
       public void onNewItem(int faceId,   Face item) {
           mFaceGraphic.setId(faceId);
       }
   
       /**
        * Update the   position/characteristics of the face within the overlay.
        */
       @Override
       public void onUpdate(FaceDetector.Detections<Face>   detectionResults, Face face) {
           mOverlay.add(mFaceGraphic);
           mFaceGraphic.updateFace(face);
       }
   
       /**
        * Hide the graphic when the   corresponding face was not detected.    This can happen for
        * intermediate frames temporarily   (e.g., if the face was momentarily blocked from
        * view).
        */
       @Override
       public void onMissing(FaceDetector.Detections<Face>   detectionResults) {
           mOverlay.remove(mFaceGraphic);
       }
   
      /**
      * Called when the face is assumed to be gone for good. Remove the graphic annotation from
      * the overlay.
      */
       @Override
       public void onDone()   {
           mOverlay.remove(mFaceGraphic);
       }
   }



각 GraphicFaceTracker 인스턴스는 연관된 FaceGraphic 인스턴스를 유지 관리한다. FaceGraphic 인스턴스는 카메라 비디오의 오버레이의 일부로 추가되는 그래픽 객체다.

 FaceGraphic 인스턴스는 얼굴이 처음 나타났을 때 처음으로 생성되고, 얼굴이 변경되면 업데이트되며, 얼굴이 일시적으로 사라졌을 때 숨겨지고, 더 이상 얼굴이 보이지 않을 때 제거된다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari