Why am I getting undefined reference to cv::imwrite?

asked 2018-07-18 11:37:30 -0600

accdev gravatar image

updated 2018-07-26 10:44:25 -0600

I'm developing an app for android with react-native that uses opencv and the imread and imwrite functions. They are in the same header file(using opencv version 3.4.1), but I get an undefined reference when trying to use imwrite, NOT imread. Imread reads the image perfectly and I am able to do my image analysis, but can't save the post-processed image as I get this error. Any thoughts?

Here is the c++ code:

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
extern "C"
void JNICALL Java_com_app_ImageConvert_OpencvNativeClass_invertImage(JNIEnv *env, jobject instance,
                                                                         jstring filePath, jstring invertedFilePath) {
    // get file paths
    const char *filePathStr = env->GetStringUTFChars(filePath, 0);
    const char *invertedFilePathStr = env->GetStringUTFChars(invertedFilePath, 0);
    // read photo with path
    Mat image = imread( filePathStr , IMREAD_COLOR);
    // image analysis code here
    // save image

Java Code to get file paths:

        File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);    
        //make path of photo with gallery path
        String imageName;
        int index = imagePath.lastIndexOf("/");
        imageName = imagePath.substring(index+1, imagePath.length()-4);
        String filePath = dir.getAbsolutePath() + "/" + imageName + ".jpg";
        //make path of inverted photo
        String invertedFilePath = dir.getAbsolutePath() + "/" + imageName + "_inverted.jpg";

Here is CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)
add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)
add_library( # Sets the name of the library.

             # Sets the library as a shared library.

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # file are automatically included.
             src/main/cpp/native-lib.cpp )
find_library( # Sets the name of the path variable.

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )
target_link_libraries( # Specifies the target library.

                       # OpenCV lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

Here is the Error Message:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:externalNativeBuildDebug'.
> Build command failed.
  Error while executing process C:\Users\USER\AppData\Local\Android\Sdk\cmake\3.6.4111459\bin\cmake.exe with arguments {--build C:\Users\USER\Desktop\App\android\app\.externalNativeBuild\cmake\debug\armeabi-v7a --target native-lib}
  [1/1] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\debug\obj\armeabi-v7a\libnative-lib.so
  FAILED: cmd.exe /C "cd . && C:\Users\USER\AppData\Local\Android\Sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe  --target=armv7-none-linux-androideabi --gcc-toolchain=C:/Users/USER/AppData/Local/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64 --sysroot=C:/Users/USER/AppData/Local/Android/Sdk/ndk-bundle/sysroot -fPIC -isystem C:/Users/USER/AppData/Local/Android/Sdk/ndk-bundle/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=16 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -frtti -fexceptions -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -nostdlib++ --sysroot C:/Users/USER/AppData/Local/Android/Sdk/ndk-bundle/platforms/android-16/arch-arm -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--fix-cortex-a8 -Wl,--exclude-libs,libunwind ...
edit retag flag offensive close merge delete


show code, please. mk files, anything you deem useful.

berak gravatar imageberak ( 2018-07-18 11:55:13 -0600 )edit

Actually in your C++ code, you never really check if the imread actually succeeded in filling the Mat element (and thus read a valid image, before writing). Can you add a if(image.empty()){ cerr << "Go bezerk >_<!"; return -1; } right after the imread? If that fails, it means your string for reading the image is wrong.

StevenPuttemans gravatar imageStevenPuttemans ( 2018-07-24 04:42:01 -0600 )edit

So part of the image analysis is a circle detection, and I have this in my image analysis: if (circles.size() == 1){usleep(5000000); And if I take of picture with a circle I get this 5 second pause.

accdev gravatar imageaccdev ( 2018-07-26 10:13:52 -0600 )edit

^^ that is entirely unrelated and irrelevant.

with react-native

yea, good luck there, you're way off the trodden path.

can you add the exact error msg to your question, please ?

(imwrite() has an additional params arg, with a std::vector. your android c++ libs might have somethong slightly different here)

berak gravatar imageberak ( 2018-07-26 10:22:33 -0600 )edit

Your saying the fact that this is in react-native is irrelevant? Or is it the bit of code I've added? And I edited the question to include the exact error message.

accdev gravatar imageaccdev ( 2018-07-26 10:46:40 -0600 )edit

no, the timeout code is irrelevant.

berak gravatar imageberak ( 2018-07-26 10:56:04 -0600 )edit

'cv::imwrite(cv::String const&, cv::_InputArray const&, std::__ndk1::vector<int, std::__ndk1::allocator<int> > const&) look at the last arg.

i can only guess, but it looks like your android libs were compiled against a different c++ std implementation as the react native code youre trying to compile now.

berak gravatar imageberak ( 2018-07-26 11:00:18 -0600 )edit

Hmm, I'm not certain how I would check/fix it if this is the issue. Also, the point of the timeout code was to answer @StevenPuttemans question that imread is indeed reading an image that isn't empty.

accdev gravatar imageaccdev ( 2018-07-26 13:01:20 -0600 )edit

You may try to use an older version of NDK, e.g., 16b.

SunnyYo gravatar imageSunnyYo ( 2019-03-18 05:30:43 -0600 )edit