1. 程式人生 > >Android studio 2.3.3+Dlib

Android studio 2.3.3+Dlib

最近因為需要,嘗試著將Dlib移植到android上。android小白一枚,做之前沒接觸過android,所以就用了別人說比較好的android studio 最新穩定版(windows下)。在android studio2.3.3版本中使用cmake+clang來編譯C/C++。我直接將之前在Ubuntu17.04的跑通了的程式碼拿過來,之前用的cmake+gcc,所以CMakeList.txt也是直接複製過來稍加修改。因為用dlib一般少不了要用opencv的庫,網上很多教程,我配置的時候一些問題基本都能從網上找到解決辦法,就不在這裡多說了。

其實弄好opencv之後,再把這個庫加到專案裡基本就沒啥問題了,修改CmakeList.txt如下(這裡是最基本的樣子):

set(pathToProject D:/AndroidStudioProjects/MyProject)
set(pathToOpenCv D:/AndroidStudioProjects/OpenCV-android-sdk)
set(pathToDlib D:/AndroidStudioProjects/MyProject/app/src/main/dlib)
cmake_minimum_required(VERSION 3.4.1)
include(${pathToDlib}/dlib/cmake)
add_library( lib_opencv SHARED IMPORTED )


include_directories(lib_opencv ${pathToOpenCv}/sdk/native/jni/include )
set_target_properties( lib_opencv PROPERTIES IMPORTED_LOCATION ${pathToProject}/app/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)
add_library( native-lib SHARED src/main/cpp/native-lib.cpp )
find_library( log-lib log )
target_link_libraries( native-lib ${log-lib} lib_opencv dlib::dlib )

內容和dlib給的examples沒啥太大差別。android studio 會自動把dlib加進專案中,然後編譯就行啦。

問題及解決:

(1)

error :no member named ‘round’ in namespace ‘std’; did you mean simply ‘round’?

一開始看到這個報錯在網上翻了好多帖子,都沒找到解決辦法,無奈只能自己從標頭檔案開始找起。把clang報錯的內容拿出來看了,標頭檔案包含路徑沒有問題,編譯的引數沒有問題(這個函式是從c++11之後才有的,所以有人會說在build.gradle裡的cppFlags加上“-std=c++11”,這個在建專案的時候選C++11就已經加進去了啊,沒啥用啊),最後就去看標頭檔案cmath,在cmath中找到了這個函式的宣告:

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  // types
  using ::double_t;
  using ::float_t;

  // functions
  ……
  using ::round;
  ……

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

咋一看也沒問題啊,可是上面這一段是包含在下面這兩句裡面的,-std=c++11已經加了,所以就是那個巨集的問題了。然後就去找,在別的標頭檔案中確實有這個巨集定義,但是那個標頭檔案的引用順序應該在cmath之後,所以才會出這個問題。

#if __cplusplus >= 201103L
#ifdef _GLIBCXX_USE_C99_MATH_TR1

知道問題之後解決起來就是各種辦法了,一開始我直接在cmath中加了一句

#define _GLIBCXX_USE_C99_MATH_TR1 1

編譯,沒錯。不過後來用這個關鍵詞去檢索,查到了stackoverflow上的一個類似的問題,按照裡面的方法改了一下,也沒問題。不過,

$ndk\sources\cxx-stl\gnu-libstdc++\libs\armeabi\include\bits\c++config.h

這個路徑再自己看一下,好多個c++config.h,應該改哪個就根據實際來咯。
(2)

error: no type named ‘exception_ptr’ in namespace ‘std’; did you mean ‘exception’?

這個問題和上面的如出一轍,先去找對應的標頭檔案<exception>,在該檔案的最後

#if (__cplusplus >= 201103L) && (ATOMIC_INT_LOCK_FREE > 1)
#include <bits/exception_ptr.h>
#include <bits/nested_exception.h>
#endif

std::exception_ptr就是在<bits/exception_ptr.h>裡面定義的,那就往回找ATOMIC_INT_LOCK_FREE 這個巨集,在atomic_lockfree_defines.h裡面有如下巨集定義:

#if __cplusplus >= 201103L
……
#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
……
#endif

參考預定義巨集,用clang++.exe -E -dM - < nul可以看到這個巨集在clang裡也是有的並且值為2(那為啥還會報錯???黑人問號臉.jpg)。這裡暫時先不管了,我直接把#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE改成了#define ATOMIC_INT_LOCK_FREE 2 ,編譯妥妥的,至於這兩個巨集,自己去查資料吧……

(3)

error: “DLIB_NO_GUI_SUPPORT is defined so you can’t use the GUI code. Turn DLIB_NO_GUI_SUPPORT off if you want to use it.”

這是移植過來又一個問題,因為之前在Ubuntu下面已經捯飭過dlib,所以大概知道問題出現在dlib的cmake檔案中,DLIB_NO_GUI_SUPPORT這個巨集相關的在dlib/dlib/CMakeLists.txt裡面,可以自己看一下,下圖是問題所在CMakeLists.txt
在windows下面編譯我怎麼去給你弄這些包啊?那乾脆註釋掉好了。

(8月3日修改)在寫程式測試的時候也遇到過一些問題,參考了github上的這個,Java的bitmap轉換成mat,還有如何在Java裡使用C++類等。
打算把dlib的人臉特徵點提取使用在android程式上,但是dlib和opencv庫的儲存開銷對一個小程式來說就有點大,如果大家有啥減少儲存開銷的好辦法請留言我。