mediapipe中的人臉檢測(java)代碼初探

1.android代碼,從創建activity說起.

facedetectioncpu(我們暫時講cpu版本) 下的MainActivity.java文件.

a. 毫無疑問,我們來看看.

protected void onCreate(Bundle savedInstanceState);

 

在創建activity的時候,做了些什麼工作呢?

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    previewDisplayView = new SurfaceView(this);
    setupPreviewDisplayView();

    // Initialize asset manager so that MediaPipe native libraries can access the app assets, e.g.,
    // binary graphs.
    AndroidAssetUtil.initializeNativeAssetManager(this);

    eglManager = new EglManager(null);
    processor =
        new FrameProcessor(
            this,
            eglManager.getNativeContext(),
            BINARY_GRAPH_NAME,
            INPUT_VIDEO_STREAM_NAME,
            OUTPUT_VIDEO_STREAM_NAME);
    processor.getVideoSurfaceOutput().setFlipY(FLIP_FRAMES_VERTICALLY);

以上是 部分代碼.

b.加載了 layout文件夾下的 activity_main.xml 文件.

c.創建了 SurfaceView ..

然後設置一下 預覽的視圖 參數. 下面是代碼:

    previewDisplayView.setVisibility(View.GONE);
    ViewGroup viewGroup = findViewById(R.id.preview_display_layout);
    viewGroup.addView(previewDisplayView);

只是 部分代碼.

只是剛開始,控件是不可見的,

然後去xml 文件 去找這個控件,添加之.

Surface的 三種狀態 回調代碼就 不貼出了,  A.創建,B. 改變 C. 銷燬 (這三個)

 

2.接着我們繼續看

AndroidAssetUtil.initializeNativeAssetManager(this);

從 字面本意上看,是初始化本地assert 文件管理.

跟蹤進去看,原來這個是靜態函數,實際上調用的是 native 寫的.

  public static boolean initializeNativeAssetManager(Context androidContext) {
    return nativeInitializeAssetManager(
        androidContext, androidContext.getCacheDir().getAbsolutePath());
  }

至於這個c/c++代碼,實現了啥,這裏暫時不跟下去.

 

3.接着我們繼續往下看.

    eglManager = new EglManager(null);

哦,這個原來是 OpenGL 的 初始化地方.

那它做了神嘛呢?

點進去看了下.

原來 EglManager(null),只是它其中的一個構造函數.調用了下面這個

  public EglManager(@Nullable Object parentContext, @Nullable int[] additionalConfigAttributes) {
    singleIntArray = new int[1];
    egl = (EGL10) EGLContext.getEGL();
    eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
    if (eglDisplay == EGL10.EGL_NO_DISPLAY) {
      throw new RuntimeException("eglGetDisplay failed");
    }
    int[] version = new int[2];
    if (!egl.eglInitialize(eglDisplay, version)) {
      throw new RuntimeException("eglInitialize failed");
    }
....
}

這裏,我們不過多介紹了,我們理解它 可以正確完成初始化就好.

 

4.繼續往下看...

    processor =
        new FrameProcessor(
            this,
            eglManager.getNativeContext(),
            BINARY_GRAPH_NAME,
            INPUT_VIDEO_STREAM_NAME,
            OUTPUT_VIDEO_STREAM_NAME);

其中的 BINRAY_GRAPH_NAME 變量是:     facedetectioncpu.binarypb

從代碼上看 是要加載這個文件.(估計這個是核心部分)

 

事實上,在我們創建app 時,bazel build的時候,做了一些預處理.

來看我麼的BUILD 文件.

genrule(
    name = "binary_graph",
    srcs = ["//mediapipe/graphs/face_detection:mobile_cpu_binary_graph"],
    outs = ["facedetectioncpu.binarypb"],
    cmd = "cp $< $@",
)
android_library(
    name = "mediapipe_lib",
    srcs = glob(["*.java"]),
    assets = [
        ":binary_graph",
        "//mediapipe/models:face_detection_front.tflite",
        "//mediapipe/models:face_detection_front_labelmap.txt",
    ],
...

)

 

在 graphs下的 face_detection下的BUILD 文件裏

mediapipe_binary_graph(
    name = "mobile_cpu_binary_graph",
    graph = "face_detection_mobile_cpu.pbtxt",
    output_name = "mobile_cpu.binarypb",
    deps = [":mobile_calculators"],
)

恩?

那麼face_detection_mobile_cpu.pbtxt 這個文件是幹嘛的呢?

難道就是上面 兩三段代碼,將定義的 xx.pbtxt 與 xx_front.tflite 和 xx_front_labelmap.txt  相關聯的?

 

5.進去看了看(face_detection_mobile_cpu.pbtxt)

定義了一些Node,還有算子,(包括配置算子參數等)

難道這裏面 就是真正實現了 檢測人臉算法的過程?(一系列,甚至包括,人臉檢測出來信息,框體位置轉化,甚至繪製在表面都在這裏完成? )

 

然後 就初始化了,跑起來了?

(是這樣的,看完代碼之後才知道,原來檢測速度流暢是有原因的)

後面沒什麼代碼了 (就是打開攝像頭.(如果權限有的話,就打開攝像頭...))

代碼是:

  @Override
  protected void onResume() {
    super.onResume();
    converter = new ExternalTextureConverter(eglManager.getContext());
    converter.setFlipY(FLIP_FRAMES_VERTICALLY);
    converter.setConsumer(processor);
    if (PermissionHelper.cameraPermissionsGranted(this)) {
      startCamera();
    }
  }

 

作者對加載過程還是不太明白,如有正在研究這框架的夥伴,歡迎 各位大佬 指點迷津:

留言即可.謝謝啦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章