System information
- OpenCV 4.3 / 3.4
- Linux Ubuntu 16.04
- Android Studio (Gradle / Ninja / CMake / clang++)
Detailed description
I'm trying to use OpenCV on Android's NDK.
I have two similar environments - one integrated with OpenCV 4.3 and the other with OpenCV 3.4.
I created an Android C++ app.
For the 4.3 integration I followed this tutorial.
For the 3.4 integration I followed this tutorial.
I have a very basic native-lib.cpp
file (see below), which is trying to use cv::imread
.
In my code I provide the last trial - which includes the OpenCVLoader.initAsync
instance, but I also tried the OpenCVLoader.initDebug
way and System.loadLibrary("opencv_java4")
, but the error remains.
I tried to build for my SDK version or against libc++, as described in the following:
- Android Studio with NDK : link error : undefined reference to 'stderr'
- Undefined References Error OpenCv Android with ndk 18 (c++_static)
- NDK - problems after GNUSTL has been removed from the NDK (revision r18)
and noticed some other issues, which do not use exactly the same setup (for example, using ndk-build instead of cmake):
but failed to solve the issue.
When trying to run the app I get the following errors:
undefined reference to `cv::imread'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
Isn't undefined reference a linker issue? Did I forget a compiler flag or something?
Steps to reproduce
Follow one of the tutorials (4.3 tutorial or 3.4 tutorial) to integrate OpenCV library into Android Studio.
Create the following simple native-lib.cpp:
#include <jni.h>
#include <string>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
extern "C" JNIEXPORT jstring JNICALL
Java_com_ocv_MainActivity_ocvLoadImage(
JNIEnv *env,
jobject thiz) {
using namespace cv;
using namespace std;
Mat image;
string imageName = "/Pictures/images/image-001.jpg";
image = imread(imageName, IMREAD_COLOR);
std::string returnString = "OpenCV load image: ";
if (! image.empty()){
returnString.append(imageName);
}
return env -> NewStringUTF(returnString.c_str());
}
and call it from this simple MainActivity.java:
package com.ocv;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.util.Log;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("native-lib");
System.loadLibrary("opencv_java4");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
if (status == LoaderCallbackInterface.SUCCESS) {
TextView textView = findViewById(R.id.sample_text);
String displayString =
textView.getText() +
"\n" + "OpenCV loaded successfully via initAsync" +
"\n" + ocvLoadImage();
textView.setText(displayString);
} else {
super.onManagerConnected(status);
}
}
};
@Override
public void onResume()
{
super.onResume();
OpenCVLoader.initAsync(
OpenCVLoader.OPENCV_VERSION_3_4_0,
this,
mLoaderCallback);
}
public native String ocvLoadImage(String imagePath);
}
NOTES:
- When calling
OpenCVLoader.initAsync
, both the 4.3 and the 3.4 version use theOPENCV_VERSION_3_4_0
flag, sinceOPENCV_VERSION
on 4.3 results in an error. I also tried theOpenCVLoader.initDebug
and it produces the same error. - When commenting out the
image = imread
line innative-lib.cpp
, the app runs OK, and returns the string (all cases).
the app's build.gradle:
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
abiFilters 'arm64-v8a'
arguments "-DOpenCV_DIR=" + opencvsdk + "/sdk/native/jni"
}
}
...
packagingOptions {
pickFirst 'lib/arm64-v8a/libopencv_java4.so'
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.4.1)
include_directories(${OpenCV_DIR}/jni/include)
find_package(OpenCV 4.3
REQUIRED
java)
add_library(
native-lib
SHARED
native-lib.cpp )
find_library(
log-lib
log )
target_link_libraries( # Specifies the target library.
native-lib
${OpenCV_LIBRARIES}
${log-lib} )
Error
ERROR:
undefined reference to "cv::imread"
BUILD:
Build command failed.
Error while executing process /path/to/Sdk/cmake/3.10.2.4988404/bin/ninja with arguments {-C /path/to/app/.cxx/cmake/debug/arm64-v8a native-lib}
ninja: Entering directory `/path/to/app/.cxx/cmake/debug/arm64-v8a'
[1/2] Building CXX object CMakeFiles/native-lib.dir/native-lib.cpp.o
[2/2] Linking CXX shared library /path/to/app/build/intermediates/cmake/debug/obj/arm64-v8a/libnative-lib.so
FAILED: /path/to/app/build/intermediates/cmake/debug/obj/arm64-v8a/libnative-lib.so
: && /path/to/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android29 --gcc-toolchain=/path/to/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/path/to/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -frtti -fexceptions -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libnative-lib.so -o /path/to/app/build/intermediates/cmake/debug/obj/arm64-v8a/libnative-lib.so CMakeFiles/native-lib.dir/native-lib.cpp.o /path/to/OpenCV-android-sdk/sdk/native/libs/arm64-v8a/libopencv_java4.so /path/to/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/29/liblog.so -ljnigraphics -llog -ldl -lz -latomic -lm && :
MORE
Tried How can I integrate OpenCV 4.0 into a pure C++ Android NDK project? :
CMakeLists.txt:
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_ANDROID_STL_TYPE c++_static)
set( OpenCV_DIR "/path/to/opencv-4.3.0-android-sdk/OpenCV-android-sdk/sdk/native/jni" )
find_package(OpenCV
REQUIRED
java)
add_library(native-lib
SHARED
native-lib.cpp )
get_target_property(__src opencv_java IMPORTED_LOCATION_RELEASE )
add_custom_command(TARGET native-lib POST_BUILD COMMAND
${CMAKE_COMMAND} -E copy ${__src} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
include_directories(${OpenCV_INCLUDE_DIRS})
find_library( log-lib
log )
target_link_libraries(
native-lib
opencv_java
${log-lib} )
but still get the same error.