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

时间:2020-12-10 08:54:42

I followed the instructions from here and added OpenCV successfully. But I've been trying to add tesseract to the Android.mk as well, for a few days now, and haven't been able to do it.

我按照这里的说明成功添加了OpenCV。但是我已经尝试将tesseract添加到Android.mk中,现在已经有几天了,而且还无法做到。

I have an android.cpp that uses tesseract so I have to include the dependency in my Android.mk . I found 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 that shows how to link prebuilt libraries. So based on that I tried this Android.mk:

我有一个使用tesseract的android.cpp所以我必须在我的Android.mk中包含依赖项。我发现这个帖子几乎确实存在问题,他解决了将libtess.so和liblept.so文件导入Android.mk,但没有解释如何做到这一点,所以我看了一下,发现这篇帖子显示了如何链接预建库。基于此我尝试了这个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)

And got this output:

得到了这个输出:

[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.

So I guess is not linking libtess correctly, and if you look closely, it doesn't ever install libtess.so, it looks like it installs liblept.so, and then jumps to text_detect.cpp, ignoring this part:

所以我想不是正确链接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)

So I tried to force it to install liblept and libtess completely before proceeding by putting it in different files. So I put the last part of the file in a different Android.mk in another folder and tried include $(call all-subdir-makefiles), and then it installs libtess and liblept completely, but ignores the call all-subdir-makefiles.

因此我尝试强制它完全安装liblept和libtess,然后将其放入不同的文件中。所以我将文件的最后一部分放在另一个文件夹中的另一个Android.mk中并尝试包含$(调用all-subdir-makefiles),然后完全安装libtess和liblept,但忽略调用all-subdir-makefiles。

new jni folder structure:

新的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)

And this is the output:

这是输出:

[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

As you see it installs everything from the first Android.mk perfectly, but it never runs textdetect/Android.mk

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

So, what I'm I doing wrong? How can I achieve this task that seems so simple? Is there an easier way?

那么,我做错了什么?我怎样才能实现这么简单的任务呢?有没有更简单的方法?

EDIT:

After @ph0b response I went back to my first setup and added the same LOCAL_EXPORT_C_INCLUDES as the original Makefiles (with a couple of variations adapting it to my paths), and that solved it. It couldn't find platform.h because it didn't know where to look for it.

在@ ph0b响应之后,我回到了我的第一个设置并添加了与原始Makefile相同的LOCAL_EXPORT_C_INCLUDES(有几个变体使其适应我的路径),这解决了它。它找不到platform.h,因为它不知道在哪里寻找它。

Now, after I did this change I had a different error No such file or directory #include "com_googlecode_tesseract_android/src/api/baseapi.h" and I thought this was because it didn't compile tesseract before run_detection that depends on it. Well that wasn't the problem, it still compiles run_detection before tesseract but that wasn't the issue, it was so much simpler and I feel so stupid for having spent so much time on this error. The problem was it didn't find com_googlecode_tesseract_android/src/api/baseapi.h because I didn't provide the path for that either, so I copied com_googlecode_tesseract_android and com_googlecode_leptonica_android from tess-two and added $(LOCAL_PATH) to LOCAL_EXPORT_C_INCLUDES. This is my final solution:

现在,在我做了这个更改之后我遇到了一个不同的错误没有这样的文件或目录#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_android和com_googlecode_leptonica_android,并将$(LOCAL_PATH)添加到LOCAL_EXPORT_C_INCLUDES。这是我的最终解决方案:

jni folder structure:

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)

1 个解决方案

#1


Your latest setup is failing in a weird way, ndk-build should at least try to compile your module. Maybe there is a bug in all-subdir-makefiles when there are ndk modules defined before it, and it doesn't find your module's Android.mk. You can try having only include $(call all-subdir-makefiles) inside your top level Android.mk.

你的最新设置是以一种奇怪的方式失败,ndk-build至少应该尝试编译你的模块。当在它之前定义了ndk模块时,all-subdir-makefiles中可能存在一个错误,并且它找不到你的模块的Android.mk。您可以尝试在*Android.mk中包含$(call all-subdir-makefiles)。

Anyway, I think you should go back to your first setup, with your module directly in the jni root folder. Then, your main issue is the proper declaration of includes paths. tess-two/jni doesn't contain any headers ? They're in tess-two/jni/com_googlecode_*_android/src/*. That means you need to list these in your module declarations, by giving all the absolute paths to LOCAL_EXPORT_C_INCLUDES variables (like from the original Makefiles: https://github.com/rmtheis/tess-two/blob/master/tess-two/jni/com_googlecode_tesseract_android/Android.mk#L33)

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

You also need to add the dependency on liblept for libtess: LOCAL_SHARED_LIBRARIES := liblept inside libtess library declaration.

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

If it still fails, there is also another possibility: instead of redefining libtess and liblept modules using the generated .so files, you can directly include tess-two/jni/Android.mk and use the same Application.mk than tess-two (copy `tess-two/jni/Application.mk). It will already properly define libtess and liblept modules.

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

#1


Your latest setup is failing in a weird way, ndk-build should at least try to compile your module. Maybe there is a bug in all-subdir-makefiles when there are ndk modules defined before it, and it doesn't find your module's Android.mk. You can try having only include $(call all-subdir-makefiles) inside your top level Android.mk.

你的最新设置是以一种奇怪的方式失败,ndk-build至少应该尝试编译你的模块。当在它之前定义了ndk模块时,all-subdir-makefiles中可能存在一个错误,并且它找不到你的模块的Android.mk。您可以尝试在*Android.mk中包含$(call all-subdir-makefiles)。

Anyway, I think you should go back to your first setup, with your module directly in the jni root folder. Then, your main issue is the proper declaration of includes paths. tess-two/jni doesn't contain any headers ? They're in tess-two/jni/com_googlecode_*_android/src/*. That means you need to list these in your module declarations, by giving all the absolute paths to LOCAL_EXPORT_C_INCLUDES variables (like from the original Makefiles: https://github.com/rmtheis/tess-two/blob/master/tess-two/jni/com_googlecode_tesseract_android/Android.mk#L33)

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

You also need to add the dependency on liblept for libtess: LOCAL_SHARED_LIBRARIES := liblept inside libtess library declaration.

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

If it still fails, there is also another possibility: instead of redefining libtess and liblept modules using the generated .so files, you can directly include tess-two/jni/Android.mk and use the same Application.mk than tess-two (copy `tess-two/jni/Application.mk). It will already properly define libtess and liblept modules.

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