안 드 로 이 드 가 얼굴 인식 기술 을 실현 하 는 예제 코드

1.최 전방
인공지능 시대 가 빠르게 도래 했 는데 그 중에서 얼굴 인식 은 현재 비교적 인기 있 는 기술 로 국내 에서 도 점점 더 많이 활용 되 고 있다.예 를 들 어 얼굴 을 긁 고 카드 를 찍 고 얼굴 을 닦 는 앱,신분 식별,얼굴 통 금 등 이다.현재 의 안면 인식 기술 은 WEBAPI 와 SDK 호출 두 가지 방식 으로 나 뉘 는데 WEBAPI 는 실시 간 인터넷 이 필요 하고 SDK 호출 은 오프라인 으로 사용 할 수 있다.
이번에 사 용 된 홍 연 이 제공 하 는 얼굴 인식 SDK 는 응용 장면 에 따라 디자인 할 수 있어 목적 성 이 강하 다.안면 검사,안면 추적,안면 인식 을 포함해 오프라인 환경 에서 도 정상적으로 작 동 할 수 있다.
홍 연 회 사 는 실리콘밸리 배경 을 가 진 이미지 처리 회사 로 얼굴 기술 외 에 도 여러 가지 이미지 와 영상 처리 기술 이 있다.그들의 듀 얼 카메라 처리 알고리즘 과 얼굴 미화 알고리즘 은 OPPO VIVO,SUMAMNG 등 일련의 휴대 전화 업 체 를 포함한다.
2.프로젝트 의 목표
우 리 는 한 사람의 얼굴 인식 기능 을 실현 해 야 한다.쉽게 말 하면 기기 의 백 엔 드 카메라 로 카메라 에 실시 간 으로 찍 힌 사람의 얼굴 정 보 를 식별 하고 인 라 이브 러 리 에 등록 하면 등 록 된 이름 과 같은 인식 후의 얼굴 정 보 를 표시 한다.없 으 면 등록 되 지 않 았 음 을 알려 줍 니 다.
이 기능 은 여러 가지 응용 장면 을 가지 고 있다.예 를 들 어 기차 역 이나 카드 를 찍 거나 통 금 시스템 에서.
3.얼굴 인식 과정
얼굴 인식 은 두 가지 필수 과정,얼굴 등록 과 실시 간 식별 을 포함한다.
얼굴 등록 이란 얼굴의 특징 정 보 를 얼굴 정보 창고 에 등록 하 는 것 을 말한다.얼굴 등록 의 출처 는 여러 가지 가 있 을 수 있다.예 를 들 어
국가 신분증 창고
기업 자체 얼굴 인식 창고인터넷 데이터베이스
사람의 얼굴 특징 추출 은 거 스 를 수 없 는 과정 으로 사람의 얼굴 특징 정보 에서 사람의 얼굴 사진 을 복원 할 수 없다.
온라인 라 이브 러 리 를 사용 할 때 사진 정 보 를 전달 하거나 이미지 특징 값 을 추출 해 야 합 니 다.
오프라인 SDK 는 상대 적 으로 안전 하지만 온라인 SDK 는 보통 더 많은 접속 과 호출 방식 을 제공 하 는데 이것 은 실제 상황 과 결합 하여 선택해 야 한다.
4.얼굴 라 이브 러 리 의 관련 기능 을 정의 하고 실현
앞에서 말 한 바 와 같이 우 리 는 자신의 얼굴 라 이브 러 리 를 정의 하고 싶 습 니 다.얼굴 라 이브 러 리 는 프로그램 에서 List 를 사용 하여 저장 하고 시스템 에서 txt 파일 로 저장 하고 싶 습 니 다.
검색엔진 을 통 해 얼굴 정보 가 AFR 에 저장 되 어 있 음 을 알 수 있 습 니 다.FSDK Face 류 중 에이 주요 구 조 는?

 public static final int FEATURE_SIZE = 22020;
 byte[] mFeatureData;
얼굴 등록 을 하려 면 얼굴 정보 와 이름 을 연결 하 는 다른 종 류 를 정의 해 야 한다.

class FaceRegist {
    String mName;
    List<AFR_FSDKFace> mFaceList;

    public FaceRegist(String name) {
      mName = name;
      mFaceList = new ArrayList<>();
    }
  }
특징 정보의 길이 와 내용 을 포함 하 는 byte 그룹 입 니 다.
우 리 는 이러한 기능 을 클래스 FaceDB 에 정의 한다.FaceDB 는 엔진 정 의 를 포함 하고 초기 화 하 며 얼굴 정 보 를 버 전 라 이브 러 리 에 저장 하고 버 전 라 이브 러 리 에서 얼굴 정 보 를 읽 는 기능 이 필요 합 니 다.
5.엔진 초기 화
프로그램의 구조 적 고려 를 위해 우 리 는 얼굴 인식 과 관련 된 코드 를 하나의 FaceDB 로 독립 시 키 고 필요 한 변 수 를 정의 합 니 다.

public static String appid = "bCx99etK9Ns4Saou1EbFdC18xHdY9817EKw****";
public static String ft_key = "CopwZarSihp1VBu5AyGxfuLQdRMPyoGV2C2opc****";
public static String fd_key = "CopwZarSihp1VBu5AyGxfuLXnpccQbWAjd86S8****";
public static String fr_key = "CopwZarSihp1VBu5AyGxfuLexDsi8yyELdgsj4****";

String mDBPath;
List<FaceRegist> mRegister;
AFR_FSDKEngine mFREngine;
AFR_FSDKVersion mFRVersion;
엔진 을 초기 화하 기 위해 매개 변수 가 있 는 구조 함 수 를 정의 합 니 다.

public FaceDB(String path) {
    mDBPath = path;
    mRegister = new ArrayList<>();
    mFRVersion = new AFR_FSDKVersion();
    mUpgrade = false;
    mFREngine = new AFR_FSDKEngine();
    AFR_FSDKError error = mFREngine.AFR_FSDK_InitialEngine(FaceDB.appid, FaceDB.fr_key);
    if (error.getCode() != AFR_FSDKError.MOK) {
      Log.e(TAG, "AFR_FSDK_InitialEngine fail! error code :" + error.getCode());
    } else {
      mFREngine.AFR_FSDK_GetVersion(mFRVersion);
      Log.d(TAG, "AFR_FSDK_GetVersion=" + mFRVersion.toString());
    }
  }
분석 함수 방출 엔진 이 사용 하 는 시스템 자원 을 정의 합 니 다.

public void destroy() {
    if (mFREngine != null) {
      mFREngine.AFR_FSDK_UninitialEngine();
    }
  }
6.사람의 얼굴 증가 와 읽 기 기능 실현
보통 얼굴 라 이브 러 리 는 데이터베이스 에 저 장 됩 니 다.이번 에는 List 를 사용 하여 간단 한 시 뮬 레이 션 을 하고 텍스트 파일 에 저장 합 니 다.필요 할 때 텍스트 에서 읽 고 저장 할 때 파일 에 기록 합 니 다.
저 희 는 addFace 방법 을 사용 하여 등 록 된 사람의 얼굴 정 보 를 사람의 얼굴 라 이브 러 리 에 추가 합 니 다.

public void addFace(String name, AFR_FSDKFace face) {
    try {
      //check if already registered.
      boolean add = true;
      for (FaceRegist frface : mRegister) {
        if (frface.mName.equals(name)) {
          frface.mFaceList.add(face);
          add = false;
          break;
        }
      }
      if (add) { // not registered.
        FaceRegist frface = new FaceRegist(name);
        frface.mFaceList.add(face);
        mRegister.add(frface);
      }

      if (!new File(mDBPath + "/face.txt").exists()) {
        if (!saveInfo()) {
          Log.e(TAG, "save fail!");
        }
      }

      //save name
      FileOutputStream fs = new FileOutputStream(mDBPath + "/face.txt", true);
      ExtOutputStream bos = new ExtOutputStream(fs);
      bos.writeString(name);
      bos.close();
      fs.close();

      //save feature
      fs = new FileOutputStream(mDBPath + "/" + name + ".data", true);
      bos = new ExtOutputStream(fs);
      bos.writeBytes(face.getFeatureData());
      bos.close();
      fs.close();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

loadFaces 를 사용 하여 파일 에서 사람의 얼굴 을 읽 습 니 다.

public boolean loadFaces(){
    if (loadInfo()) {
      try {
        for (FaceRegist face : mRegister) {
          Log.d(TAG, "load name:" + face.mName + "'s face feature data.");
          FileInputStream fs = new FileInputStream(mDBPath + "/" + face.mName + ".data");
          ExtInputStream bos = new ExtInputStream(fs);
          AFR_FSDKFace afr = null;
          do {
            if (afr != null) {
              if (mUpgrade) {
                //upgrade data.
              }
              face.mFaceList.add(afr);
            }
            afr = new AFR_FSDKFace();
          } while (bos.readBytes(afr.getFeatureData()));
          bos.close();
          fs.close();
        }
        return true;
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
    } else {
      if (!saveInfo()) {
        Log.e(TAG, "save fail!");
      }
    }
    return false;
  }
7.업무 논리 실현
7.1 얼굴 등록 기능 실현
얼굴 인식 의 전제 조건 은 얼굴 정 보 를 먼저 얼굴 창고 에 등록 하고 얼굴 창고 에 등록 하 는 것 이다.
첫 번 째 단 계 는 당연히 등록 해 야 할 사진 을 얻 는 것 이다.우 리 는 카 메 라 를 사용 할 수도 있 고 사진 을 사용 할 수도 있다.저 희 는 AlertDialog 팝 업 선택 상 자 를 사용 합 니 다.

new AlertDialog.Builder(this)
            .setTitle("       ")
            .setIcon(android.R.drawable.ic_dialog_info)
            .setItems(new String[]{"    ", "    "}, this)
            .show();
대응 하 는 이벤트 처리 함수 에서 처리 합 니 다.

switch (which){
  case 1://   
    Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");
    ContentValues values = new ContentValues(1);
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
    mPath = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT, mPath);
    startActivityForResult(getImageByCamera, REQUEST_CODE_IMAGE_CAMERA);
    break;
  case 0://  
    Intent getImageByalbum = new Intent(Intent.ACTION_GET_CONTENT);
    getImageByalbum.addCategory(Intent.CATEGORY_OPENABLE);
    getImageByalbum.setType("image/jpeg");
    startActivityForResult(getImageByalbum, REQUEST_CODE_IMAGE_OP);
    break;
  default:;
}
사진 한 장 을 얻 은 후에 우 리 는 얼굴 검사 기능 을 실현 해 야 한다.

if (requestCode == REQUEST_CODE_IMAGE_OP && resultCode == RESULT_OK) {
      mPath = data.getData();
      String file = getPath(mPath);
      //TODO: add image coversion
    }
위의 코드 에서 우 리 는 우리 가 필요 로 하 는 이미지 데이터 bmp 를 얻 었 고 그림 을 꺼 냈 다.
우 리 는 응용 프로그램 클래스 에서 함수 decodeImage 로 이 코드 를 실현 합 니 다.

public static Bitmap decodeImage(String path) {
    Bitmap res;
    try {
      ExifInterface exif = new ExifInterface(path);
      int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

      BitmapFactory.Options op = new BitmapFactory.Options();
      op.inSampleSize = 1;
      op.inJustDecodeBounds = false;
      //op.inMutable = true;
      res = BitmapFactory.decodeFile(path, op);
      //rotate and scale.
      Matrix matrix = new Matrix();

      if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
        matrix.postRotate(90);
      } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
        matrix.postRotate(180);
      } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
        matrix.postRotate(270);
      }

      Bitmap temp = Bitmap.createBitmap(res, 0, 0, res.getWidth(), res.getHeight(), matrix, true);
      Log.d("com.arcsoft", "check target Image:" + temp.getWidth() + "X" + temp.getHeight());

      if (!temp.equals(res)) {
        res.recycle();
      }
      return temp;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }
AFD 호출FSDK_StillImage Face Detection 에서 검 측 된 사람의 얼굴 정 보 를 되 돌려 줍 니 다.
얼굴 등록,먼저 얼굴 을 검출 해 야 합 니 다.정적 이미지 에 대해 홍 연 얼굴 SDK 에 대응 하 는 것 은 FD 입 니 다.AFD 라 는 방법 이름 을 제공 합 니 다.FSDK_StillImageFaceDetection 。
매개 변수 목록 을 살 펴 보 겠 습 니 다.

주의 AFDFSDKFace 대상 엔진 내부 에서 중복 사용,저장 하려 면 AFD 를 복제 하 십시오FSDKFace 대상 또는 별도로 저장
AFD_FSDKFace 는 얼굴 인식 결과 로 다음 과 같이 정의 된다.

public class AFD_FSDKFace {
  Rect mRect;
  int mDegree;
  }
mRect 는 직사각형 상자 Rect 를 정의 합 니 다.
그 전에 홍채 소프트 페 이 스 SDK 가 사용 하 는 이미지 형식 은 NV 21 형식 이 므 로 가 져 온 이미 지 를 해당 하 는 형식 으로 바 꿔 야 합 니 다.안 드 로 이 드 에서extend.jar 에서 대응 하 는 변환 함 수 를 제공 합 니 다.

byte[] data = new byte[mBitmap.getWidth() * mBitmap.getHeight() * 3 / 2];
        ImageConverter convert = new ImageConverter();
        convert.initial(mBitmap.getWidth(), mBitmap.getHeight(), ImageConverter.CP_PAF_NV21);
        if (convert.convert(mBitmap, data)) {
          Log.d(TAG, "convert ok!");
        }
        convert.destroy();
지금 우 리 는 AFD 를 호출 할 수 있다.FSDK_StillImage Face Detection 방법 입 니 다.
8.얼굴 테두리 그리 기
List에는 검출 된 얼굴의 위치 정보 와 깊이 정보 가 저 장 됩 니 다.
우 리 는 검 측 된 사람의 얼굴 위치 정 보 를 그림 에 사각형 상자 로 그 려 서 검 측 된 사람의 얼굴 정 보 를 표시 할 수 있다.

Canvas canvas = mSurfaceHolder.lockCanvas();
  if (canvas != null) {
   Paint mPaint = new Paint();
   boolean fit_horizontal = canvas.getWidth() / (float)src.width() < canvas.getHeight() / (float)src.height() ? true : false;
   float scale = 1.0f;
   if (fit_horizontal) {
     scale = canvas.getWidth() / (float)src.width();
     dst.left = 0;
     dst.top = (canvas.getHeight() - (int)(src.height() * scale)) / 2;
     dst.right = dst.left + canvas.getWidth();
     dst.bottom = dst.top + (int)(src.height() * scale);
   } else {
     scale = canvas.getHeight() / (float)src.height();
     dst.left = (canvas.getWidth() - (int)(src.width() * scale)) / 2;
     dst.top = 0;
     dst.right = dst.left + (int)(src.width() * scale);
     dst.bottom = dst.top + canvas.getHeight();
   }
   canvas.drawBitmap(mBitmap, src, dst, mPaint);
   canvas.save();
   canvas.scale((float) dst.width() / (float) src.width(), (float) dst.height() / (float) src.height());
   canvas.translate(dst.left / scale, dst.top / scale);
   for (AFD_FSDKFace face : result) {
     mPaint.setColor(Color.RED);
     mPaint.setStrokeWidth(10.0f);
     mPaint.setStyle(Paint.Style.STROKE);
     canvas.drawRect(face.getRect(), mPaint);
   }
   canvas.restore();
   mSurfaceHolder.unlockCanvasAndPost(canvas);
   break;
  }
}
9.얼굴 을 얼굴 창고 에 등록
사람의 얼굴 이 감지 되면 우 리 는 해당 하 는 설명 정 보 를 입력 하여 사람의 얼굴 창고 에 가입 할 수 있다.
식별의 정확성 을 높이 기 위해 서 우 리 는 한 사람 에 게 얼굴 정 보 를 여러 번 등록 할 수 있다.

public void addFace(String name, AFR_FSDKFace face) {
  try {
   //check if already registered.
   boolean add = true;
   for (FaceRegist frface : mRegister) {
     if (frface.mName.equals(name)) {
      frface.mFaceList.add(face);
      add = false;
      break;
     }
   }
   if (add) { // not registered.
     FaceRegist frface = new FaceRegist(name);
     frface.mFaceList.add(face);
     mRegister.add(frface);
   }

   if (!new File(mDBPath + "/face.txt").exists()) {
     if (!saveInfo()) {
      Log.e(TAG, "save fail!");
     }
   }
   //save name
   FileOutputStream fs = new FileOutputStream(mDBPath + "/face.txt", true);
   ExtOutputStream bos = new ExtOutputStream(fs);
   bos.writeString(name);
   bos.close();
   fs.close();
   //save feature
   fs = new FileOutputStream(mDBPath + "/" + name + ".data", true);
   bos = new ExtOutputStream(fs);
   bos.writeBytes(face.getFeatureData());
   bos.close();
   fs.close();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
}
마지막 으로 얼굴 검사 엔진 을 없 애 는 것 을 잊 지 마 세 요.

err = engine.AFD_FSDK_UninitialFaceEngine(); 
Log.d("com.arcsoft", "AFD_FSDK_UninitialFaceEngine =" + err.getCode()); 
10.얼굴 인식 실현
위의 코드 가 준비 되면 우리 의 얼굴 인식 기능 을 시작 할 수 있다.저 희 는 제3자 확장 라 이브 러 리,ExtGLSurface View 의 확장 라 이브 러 리 CameraGLSurface View 를 사용 하여 검 측 된 사람의 얼굴 과 해당 하 는 설명 정 보 를 ImageView 와 TextView 로 표시 합 니 다.
우선 레이아웃 을 정의 합 니 다.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

  <com.guo.android_extend.widget.CameraSurfaceView
    android:id="@+id/surfaceView"
    android:layout_width="1dp"
    android:layout_height="1dp"/>

  <com.guo.android_extend.widget.CameraGLSurfaceView
    android:id="@+id/glsurfaceView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"/>

  <ImageView
    android:id="@+id/imageView"
    android:layout_width="120dp"
    android:layout_height="120dp"
    android:layout_marginLeft="10dp"
    android:layout_marginTop="10dp"/>

  <TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/imageView"
    android:layout_alignRight="@+id/imageView"
    android:layout_below="@+id/imageView"
    android:layout_marginTop="10dp"
    android:text="@string/app_name"
    android:textAlignment="center"/>

  <TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/imageView"
    android:layout_alignRight="@+id/imageView"
    android:layout_below="@+id/textView"
    android:layout_marginTop="10dp"
    android:text="@string/app_name"
    android:textAlignment="center"/>
</RelativeLayout>
엔진 에 필요 한 이미지 형식 은 NV 21 이기 때문에 카메라 의 이미지 형식 을 NV 21 로 미리 설정 해 야 합 니 다.

public Camera setupCamera() {
  // TODO Auto-generated method stub
  mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
  try {
   Camera.Parameters parameters = mCamera.getParameters();
   parameters.setPreviewSize(mWidth, mHeight);
   parameters.setPreviewFormat(ImageFormat.NV21);

   for( Camera.Size size : parameters.getSupportedPreviewSizes()) {
     Log.d(TAG, "SIZE:" + size.width + "x" + size.height);
   }
   for( Integer format : parameters.getSupportedPreviewFormats()) {
     Log.d(TAG, "FORMAT:" + format);
   }

   List<int[]> fps = parameters.getSupportedPreviewFpsRange();
   for(int[] count : fps) {
     Log.d(TAG, "T:");
     for (int data : count) {
      Log.d(TAG, "V=" + data);
     }
   }
   mCamera.setParameters(parameters);
  } catch (Exception e) {
   e.printStackTrace();
  }
  if (mCamera != null) {
   mWidth = mCamera.getParameters().getPreviewSize().width;
   mHeight = mCamera.getParameters().getPreviewSize().height;
  }
  return mCamera;
}
카메라 로 얼굴 을 인식 하려 면 FT 라 이브 러 리 를 사용 해 야 하 는데 FT 라 이브 러 리 는 얼굴 추적 알고리즘 에서 얼굴 검출 부분 을 최적화 해 영상 처 리 를 위해 최 적 화 된 라 이브 러 리 다.
11.얼굴 검사 엔진 초기 화(FT)
FD 와 마찬가지 로 얼굴 인식 FT 엔진 을 초기 화해 야 합 니 다.

Log.d(TAG, "AFT_FSDK_InitialFaceEngine =" + err.getCode());
err = engine.AFT_FSDK_GetVersion(version);
Log.d(TAG, "AFT_FSDK_GetVersion:" + version.toString() + "," + err.getCode());
카메라 의 미리 보기 이벤트 처리 함수 에서 FT 의 얼굴 인식 함수 함 수 를 먼저 호출 한 다음 에 FR 의 얼굴 정보 특징 추출 수 함 수 를 호출 합 니 다.

AFT_FSDKError err = engine.AFT_FSDK_FaceFeatureDetect(data, width, height, AFT_FSDKEngine.CP_PAF_NV21, result);

AFR_FSDKError error = engine.AFR_FSDK_ExtractFRFeature(mImageNV21, mWidth, mHeight, AFR_FSDKEngine.CP_PAF_NV21,mAFT_FSDKFace.getRect(), mAFT_FSDKFace.getDegree(), result);
이 안의 result 에는 얼굴 특징 정보 가 저장 되 어 있다.우 리 는 그것 을 저장 하거나 내 려 와 시스템 의 다른 정보 와 비교 할 수 있다.

AFR_FSDKMatching score = new AFR_FSDKMatching();
float max = 0.0f;
String name = null;
for (FaceDB.FaceRegist fr : mResgist) {
  for (AFR_FSDKFace face : fr.mFaceList) {
   error = engine.AFR_FSDK_FacePairMatching(result, face, score);
   Log.d(TAG, "Score:" + score.getScore() + ", AFR_FSDK_FacePairMatching=" + error.getCode());
   if (max < score.getScore()) {
     max = score.getScore();
     name = fr.mName;
   }
  }
}
score 의 특징 정보 가 0.6 보다 많 을 때 우 리 는 얼굴 에 맞 았 다 고 볼 수 있다.얼굴 일치 정 보 를 표시 합 니 다.
위의 순환 에서 볼 수 있 듯 이 실제 라 이브 러 리 를 옮 겨 다 니 며 찾 는 것 이다.우리 의 목적 은 실제 상황 에서 우 리 는 배합 치가 비교적 높 은 사람의 얼굴 을 찾 은 후에 순환 을 뛰 어 넘 을 수 있다 는 것 을 보 여 주 는 것 이다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기