1

I'm using OpenCV 3.4.5 with native library and I used CMake (CMakeLists.txt) for this.

Before this project I tried very simple code with same way (that was converting realtime RGB camera video to gray video) and it was working successfully.

Now I'm trying to make a realtime face detection (not recognization) project with the same way.

Here's my native-lib.cpp file in project.

#include "opencv2/core.hpp"
#include <jni.h>
#include <opencv2/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <string>

using namespace cv;


using namespace std;
void detect (Mat& frame);
extern "C"
JNIEXPORT void JNICALL Java_com_example_alas02_NativeClass_testFunction(JNIEnv *env, jclass type,jlong addrRgba){
    Mat &frame = *(Mat *) addrRgba;
    detect(frame);
}
void detect (Mat& frame){
    String face_cascade_name = "/storage/emulated/0/ony.xml";
    String eyes_cascade_name = "/storage/emulated/0/moe.xml";
    CascadeClassifier face_cascade;
    CascadeClassifier eyes_cascade;


    if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading\n"); return; };
    if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading\n"); return; };


    std::vector<Rect> faces;
    Mat frame_gray;

    cvtColor( frame, frame_gray, CV_BGR2GRAY );
    equalizeHist( frame_gray, frame_gray );

    //-- Detect faces
    face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );

    for( size_t i = 0; i < faces.size(); i++ )
    {
        Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
        ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );

        Mat faceROI = frame_gray( faces[i] );
        std::vector<Rect> eyes;

        //-- In each face, detect eyes
        eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );

        for( size_t j = 0; j < eyes.size(); j++ )
        {
            Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 );
            int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
            circle( frame, center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 );
        }
    }
}

Note: there's any sync error but when I'm trying to build it it gives me errors like;

Build command failed.
Error while executing process C:\Users\k22\AppData\Local\Android\Sdk\cmake\3.6.4111459\bin\cmake.exe with arguments {--build C:\Users\k22\AndroidStudioProjects\alas02\app\.externalNativeBuild\cmake\debug\x86_64 --target native-lib}
[1/2] Building CXX object CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
[2/2] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\debug\obj\x86_64\libnative-lib.so
FAILED: cmd.exe /C "cd . && C:\Users\k22\AppData\Local\Android\Sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe  --target=x86_64-none-linux-android21 --gcc-toolchain=C:/Users/k22/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/k22/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security   -std=gnu++11 -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -shared -Wl,-soname,libnative-lib.so -o ..\..\..\..\build\intermediates\cmake\debug\obj\x86_64\libnative-lib.so CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o  -llog ../../../../src/main/jniLibs/x86_64/libopencv_java3.so -latomic -lm && cd ."
C:\Users\k22\AndroidStudioProjects\alas02\app\src\main\cpp/native-lib.cpp:35: error: undefined reference to 'cv::CascadeClassifier::detectMultiScale(cv::_InputArray const&, std::__ndk1::vector<cv::Rect_<int>, std::__ndk1::allocator<cv::Rect_<int> > >&, double, int, int, cv::Size_<int>, cv::Size_<int>)'

C:\Users\k22\AndroidStudioProjects\alas02\app\src\main\cpp/native-lib.cpp:46: error: undefined reference to 'cv::CascadeClassifier::detectMultiScale(cv::_InputArray const&, std::__ndk1::vector<cv::Rect_<int>, std::__ndk1::allocator<cv::Rect_<int> > >&, double, int, int, cv::Size_<int>, cv::Size_<int>)'

clang++: error: linker command failed with exit code 1 (use -v to see invocation)

ninja: build stopped: subcommand failed.

K22
  • 23
  • 6

1 Answers1

2

You are using libopencv_java3.so. It is not compatible with recent releases of NDK. See https://stackoverflow.com/a/50686467/192373.

The win-win solution is to switch to OpenCV 4. This may require some minor changes in your code.

To stay with OpenCV 3.4.5, you can step back to older NDK release (not recommended), or rebuild libopencv_java3.so with the latest NDK (adventurous).

Dan Albert
  • 10,079
  • 2
  • 36
  • 79
Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • I tried same codes with minor changes with OpenCV 4.1.1 and 4.1.0 but now I'm giving "OpenCV not loaded" message from my devices, one of them is API 17 other one is API 28. Please write me about which codes or files I have to share with you. – K22 Aug 31 '19 at 05:15
  • How do you load OpenCV? Do you pack libopencv_java4.so into the APK? – Alex Cohn Aug 31 '19 at 11:21
  • Actually yes i wrote this in the CMakeLists.txt's associated line. – K22 Aug 31 '19 at 15:15
  • It's not enough to reference `libopencv_java4.so` in **CMakeLists.txt** file; you should also put it in one of **JniLibs.src** directories. – Alex Cohn Sep 01 '19 at 06:59
  • I'm already have jniLibs and jniIncludes directories in app/src/main wich have folders and files that copied from OpenCV's own downloaded file. Aren't they enough to importing OpenCV? If it is false can you write what i have to do detailed? By the way thanks for your answers. – K22 Sep 01 '19 at 18:02