将 Tesseract 和 Opencv 添加到 Android.mk (Android Studio)

Adding Tesseract and Opencv to Android.mk (Android Studio)

我按照 here 的说明成功添加了 OpenCV。但是几天来我也一直在尝试将 tesseract 添加到 Android.mk,但一直没能做到。

我有一个使用 tesseract 的 android.cpp 所以我必须在我的 Android.mk 中包含依赖项。我发现 this post that had almost the exact problem and he solved it importing libtess.so and liblept.so files into Android.mk, but didn't explain how to do that, so I looked and found this post 显示了如何 link 预构建库。所以基于此我尝试了这个 Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := liblept
LOCAL_SRC_FILES := ../libs/$(TARGET_ARCH_ABI)/liblept.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../../tess-two/jni
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libtess
LOCAL_SRC_FILES := ../libs/$(TARGET_ARCH_ABI)/libtess.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../../tess-two/jni
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
OPENCV_PACKAGE_DIR:= /Users/danielsierraf/Documents/OpenCV-2.4.10-android-sdk/sdk
OPENCV_CAMERA_MODULES := off
include $(OPENCV_PACKAGE_DIR)/native/jni/OpenCV.mk

LOCAL_MODULE    := run_detection
LOCAL_SHARED_LIBRARIES := libtess
LOCAL_SRC_FILES := text_detect.cpp android.cpp
LOCAL_LDLIBS    += -landroid -llog -ldl

include $(BUILD_SHARED_LIBRARY)

得到这个输出:

[armeabi-v7a] Prebuilt       : liblept.so <= src/main/jni/../libs/armeabi-v7a/
[armeabi-v7a] Install        : liblept.so => src/main/jniLibs/armeabi-v7a/liblept.so
[armeabi-v7a] Compile++ thumb: run_detection <= text_detect.cpp
In file included from src/main/jni/text_detect.h:4:0,
                 from src/main/jni/text_detect.cpp:10:
src/main/jni/../../../../tess-two/jni/com_googlecode_tesseract_android/src/api/baseapi.h:32:22: fatal error: platform.h: No such file or directory
 #include "platform.h"
                      ^
compilation terminated.

所以我猜 linking libtess 是不正确的,如果你仔细观察,它不会安装 libtess.so,它看起来像是安装了 liblept.so,然后跳转到text_detect.cpp,忽略这部分:

include $(CLEAR_VARS)
LOCAL_MODULE := libtess
LOCAL_SRC_FILES := ../libs/$(TARGET_ARCH_ABI)/libtess.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../../tess-two/jni
include $(PREBUILT_SHARED_LIBRARY)

所以我试图强制它安装 libleptlibtess,然后再将其放入不同的文件中。所以我把文件的最后一部分放在另一个文件夹的不同 Android.mk 中并尝试 include $(call all-subdir-makefiles),然后安装 libtessliblept 完全,但忽略 call all-subdir-makefiles

新的 jni 文件夹结构:

Android.mk
Application.mk
text_detect/
     Android.mk
     android.cpp
     text_detect.cpp
     text_detect.h

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := liblept
LOCAL_SRC_FILES := ../libs/$(TARGET_ARCH_ABI)/liblept.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../../tess-two/jni
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libtess
LOCAL_SRC_FILES := ../libs/$(TARGET_ARCH_ABI)/libtess.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../../../tess-two/jni
include $(PREBUILT_SHARED_LIBRARY)

include $(call all-subdir-makefiles)

textdetect/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

OPENCV_PACKAGE_DIR:= /Users/danielsierraf/Documents/OpenCV-2.4.10-android-sdk/sdk
OPENCV_CAMERA_MODULES := off
include $(OPENCV_PACKAGE_DIR)/native/jni/OpenCV.mk

LOCAL_MODULE    := run_detection
LOCAL_SHARED_LIBRARIES := libtess
LOCAL_SRC_FILES := text_detect.cpp android.cpp
LOCAL_LDLIBS    += -landroid -llog -ldl

include $(BUILD_SHARED_LIBRARY)

这是输出:

[armeabi-v7a] Prebuilt       : liblept.so <= src/main/jni/../libs/armeabi-v7a/
[armeabi-v7a] Install        : liblept.so => src/main/jniLibs/armeabi-v7a/liblept.so
[armeabi-v7a] Prebuilt       : libtess.so <= src/main/jni/../libs/armeabi-v7a/
[armeabi-v7a] Install        : libtess.so => src/main/jniLibs/armeabi-v7a/libtess.so
[armeabi] Prebuilt       : liblept.so <= src/main/jni/../libs/armeabi/
[armeabi] Install        : liblept.so => src/main/jniLibs/armeabi/liblept.so
[armeabi] Prebuilt       : libtess.so <= src/main/jni/../libs/armeabi/
[armeabi] Install        : libtess.so => src/main/jniLibs/armeabi/libtess.so
[mips] Prebuilt       : liblept.so <= src/main/jni/../libs/mips/
[mips] Install        : liblept.so => src/main/jniLibs/mips/liblept.so
[mips] Prebuilt       : libtess.so <= src/main/jni/../libs/mips/
[mips] Install        : libtess.so => src/main/jniLibs/mips/libtess.so
[x86] Prebuilt       : liblept.so <= src/main/jni/../libs/x86/
[x86] Install        : liblept.so => src/main/jniLibs/x86/liblept.so
[x86] Prebuilt       : libtess.so <= src/main/jni/../libs/x86/
[x86] Install        : libtess.so => src/main/jniLibs/x86/libtess.so

如您所见,它完美地安装了第一个 Android.mk 中的所有内容,但它从未运行 textdetect/Android.mk

所以,我做错了什么?我怎样才能完成这个看似简单的任务呢?有没有更简单的方法?

编辑:

@ph0b 回复后,我回到我的第一个设置并添加了与 original Makefiles 相同的 LOCAL_EXPORT_C_INCLUDES(有几个变体使其适应我的路径),然后解决了它。它找不到 platform.h,因为它不知道到哪里去找。

现在,在我进行此更改后,我遇到了一个不同的错误 No such file or directory #include "com_googlecode_tesseract_android/src/api/baseapi.h",我认为这是因为它没有在依赖于它的 run_detection 之前编译 tesseract。好吧,这不是问题,它仍然在 tesseract 之前编译 run_detection 但这不是问题,它简单得多,我觉得在这个错误上花了这么多时间很愚蠢。问题是它没有找到 com_googlecode_tesseract_android/src/api/baseapi.h 因为我也没有提供路径,所以我从 tess-two 复制了 com_googlecode_tesseract_androidcom_googlecode_leptonica_android 并添加了 $(LOCAL_PATH)LOCAL_EXPORT_C_INCLUDES。这是我的最终解决方案:

jni 文件夹结构:

Android.mk
Application.mk
text_detect.cpp
android.cpp
text_detect.h
com_googlecode_leptonica_android
com_googlecode_tesseract_android

Android.mk

LOCAL_PATH := $(call my-dir)

#leptonica
LEPTONICA_LOCAL := $(LOCAL_PATH)/com_googlecode_leptonica_android
LEPTONICA_PATH := $(LEPTONICA_LOCAL)/src

include $(CLEAR_VARS)

LOCAL_MODULE := liblept
LOCAL_SRC_FILES := ../libs/$(TARGET_ARCH_ABI)/liblept.so
LOCAL_EXPORT_C_INCLUDES := \
  $(LEPTONICA_LOCAL) \
  $(LEPTONICA_PATH)/src

include $(PREBUILT_SHARED_LIBRARY)

#tesseract
TESSERACT_LOCAL := $(LOCAL_PATH)/com_googlecode_tesseract_android
TESSERACT_PATH := $(TESSERACT_LOCAL)/src

include $(CLEAR_VARS)

LOCAL_MODULE := libtess
LOCAL_SRC_FILES := ../libs/$(TARGET_ARCH_ABI)/libtess.so
LOCAL_EXPORT_C_INCLUDES := \
  $(LOCAL_PATH) \
  $(TESSERACT_PATH)/api \
  $(TESSERACT_PATH)/ccmain \
  $(TESSERACT_PATH)/ccstruct \
  $(TESSERACT_PATH)/ccutil \
  $(TESSERACT_PATH)/classify \
  $(TESSERACT_PATH)/cube \
  $(TESSERACT_PATH)/cutil \
  $(TESSERACT_PATH)/dict \
  $(TESSERACT_PATH)/opencl \
  $(TESSERACT_PATH)/neural_networks/runtime \
  $(TESSERACT_PATH)/textord \
  $(TESSERACT_PATH)/viewer \
  $(TESSERACT_PATH)/wordrec \
  $(LEPTONICA_PATH)/src \
  $(TESSERACT_LOCAL)
LOCAL_SHARED_LIBRARIES := liblept

include $(PREBUILT_SHARED_LIBRARY)

#opencv
include $(CLEAR_VARS)
OPENCV_PACKAGE_DIR:= /Users/danielsierraf/Documents/OpenCV-2.4.10-android-sdk/sdk
OPENCV_CAMERA_MODULES := off
include $(OPENCV_PACKAGE_DIR)/native/jni/OpenCV.mk

LOCAL_MODULE    := run_detection
LOCAL_SRC_FILES := text_detect.cpp android.cpp
LOCAL_LDLIBS    += -landroid -llog -ldl
LOCAL_SHARED_LIBRARIES += libtess liblept

include $(BUILD_SHARED_LIBRARY)

您的最新设置以一种奇怪的方式失败了,ndk-build 至少应该尝试编译您的模块。也许在 all-subdir-makefiles 中有一个错误,当它前面定义了 ndk 模块时,它没有找到你模块的 Android.mk。您可以尝试在顶层 Android.mk.

中只包含 include $(call all-subdir-makefiles)

无论如何,我认为你应该回到你的第一个设置,将你的模块直接放在 jni 根文件夹中。然后,您的主要问题是包含路径的正确声明。 tess-two/jni 不包含任何 headers ?他们在 tess-two/jni/com_googlecode_*_android/src/*。这意味着你需要在你的模块声明中列出这些,通过给出 LOCAL_EXPORT_C_INCLUDES 变量的所有绝对路径(就像来自原始的 Makefiles:https://github.com/rmtheis/tess-two/blob/master/tess-two/jni/com_googlecode_tesseract_android/Android.mk#L33

您还需要为 libtess 添加对 liblept 的依赖:LOCAL_SHARED_LIBRARIES := liblept 在 libtess 库声明中。

如果还是失败,还有另一种可能:不使用生成的.so文件重新定义libtess和liblept模块,而是直接包含tess-two/jni/Android.mk,使用与Application.mk相同的tess-two(复制`tess-two/jni/Application.mk)。它已经正确定义了 libtess 和 liblept 模块。