0

I am implementing Text detection on image using EAST Text Detection in C++. I am developing an android app which will detect text from image using EAST text detection in c++. But in the process of developing this app . i am getting an error mentioned below.

Build command failed.
Error while executing process /home/karshsoni/Android/Sdk/cmake/3.6.4111459/bin/cmake with arguments {--build /home/karshsoni/Documents/CVTextDetection/app/.externalNativeBuild/cmake/debug/arm64-v8a --target native-lib}
[1/2] Building CXX object CMakeFiles/native-lib.dir/native-lib.cpp.o
[2/2] Linking CXX shared library /home/karshsoni/Documents/CVTextDetection/app/build/intermediates/cmake/debug/obj/arm64-v8a/libnative-lib.so
FAILED: : && /home/karshsoni/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --gcc-toolchain=/home/karshsoni/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/karshsoni/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-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 -stdlib=libc++ -std=gnu++11 -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libnative-lib.so -o /home/karshsoni/Documents/CVTextDetection/app/build/intermediates/cmake/debug/obj/arm64-v8a/libnative-lib.so CMakeFiles/native-lib.dir/native-lib.cpp.o /home/karshsoni/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/21/liblog.so /home/karshsoni/Documents/CVTextDetection/app/src/main/jniLibs/arm64-v8a/libopencv_java3.so -latomic -lm && :
CMakeFiles/native-lib.dir/native-lib.cpp.o: In function `Java_com_example_cvtextdetection_MainActivity_getMat':
/home/karshsoni/Documents/CVTextDetection/app/src/main/cpp/native-lib.cpp:89: undefined reference to `cv::dnn::experimental_dnn_34_v10::Net::forward(cv::_OutputArray const&, std::__ndk1::vector<cv::String, std::__ndk1::allocator<cv::String> > const&)'
/home/karshsoni/Documents/CVTextDetection/app/src/main/cpp/native-lib.cpp:101: undefined reference to `cv::dnn::experimental_dnn_34_v10::NMSBoxes(std::__ndk1::vector<cv::RotatedRect, std::__ndk1::allocator<cv::RotatedRect> > const&, std::__ndk1::vector<float, std::__ndk1::allocator<float> > const&, float, float, std::__ndk1::vector<int, std::__ndk1::allocator<int> >&, float, int)'
/home/karshsoni/Documents/CVTextDetection/app/src/main/cpp/native-lib.cpp:123: undefined reference to `cv::dnn::experimental_dnn_34_v10::Net::getPerfProfile(std::__ndk1::vector<double, std::__ndk1::allocator<double> >&)'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

As i am developing an android app i am communicating with cpp code from java via JNI.

#include <jni.h>
#include <string>

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/dnn.hpp>

using namespace cv;
using namespace cv::dnn;

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_cvtextdetection_MainActivity_stringFromJNI(
JNIEnv *env,
jobject / this /) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}

std::string jstring2string(JNIEnv *env, jstring jStr);

void decode(const Mat& scores, const Mat& geometry, float scoreThresh,
std::vector<RotatedRect>& detections, std::vector<float>& confidences)
{
detections.clear();
CV_Assert(scores.dims == 4); CV_Assert(geometry.dims == 4); CV_Assert(scores.size[0] == 1);
CV_Assert(geometry.size[0] == 1); CV_Assert(scores.size[1] == 1); CV_Assert(geometry.size[1] == 5);
CV_Assert(scores.size[2] == geometry.size[2]); CV_Assert(scores.size[3] == geometry.size[3]);

const int height = scores.size[2];
const int width = scores.size[3];
for (int y = 0; y < height; ++y)
{
const float* scoresData = scores.ptr<float>(0, 0, y);
const float* x0_data = geometry.ptr<float>(0, 0, y);
const float* x1_data = geometry.ptr<float>(0, 1, y);
const float* x2_data = geometry.ptr<float>(0, 2, y);
const float* x3_data = geometry.ptr<float>(0, 3, y);
const float* anglesData = geometry.ptr<float>(0, 4, y);
for (int x = 0; x < width; ++x)
{
float score = scoresData[x];
if (score < scoreThresh)
continue;

// Decode a prediction.
// Multiple by 4 because feature maps are 4 time less than input image.
float offsetX = x 4.0f, offsetY = y 4.0f;
float angle = anglesData[x];
float cosA = std::cos(angle);
float sinA = std::sin(angle);
float h = x0_data[x] + x2_data[x];
float w = x1_data[x] + x3_data[x];

Point2f offset(offsetX + cosA x1_data[x] + sinA x2_data[x],
offsetY - sinA x1_data[x] + cosA x2_data[x]);
Point2f p1 = Point2f(-sinA h, -cosA h) + offset;
Point2f p3 = Point2f(-cosA w, sinA w) + offset;
RotatedRect r(0.5f (p1 + p3), Size2f(w, h), -angle 180.0f / (float)CV_PI);
detections.push_back(r);
confidences.push_back(score);
}
}
}

extern "C"
JNIEXPORT void JNICALL
Java_com_example_cvtextdetection_MainActivity_getMat(JNIEnv *env, jobject instance, jlong mat,
jstring modelPath_) {
const char *modelPath = env->GetStringUTFChars(modelPath_, 0);

int inpWidth = 320;
int inpHeight = 320;
float confThreshold = 0.5;
float nmsThreshold = 0.5;

Mat* frame = (Mat*)mat;
String path = jstring2string(env, modelPath_);
Net net = readNet(path);

std::vector<Mat> output;
std::vector<String> outputLayers(2);
outputLayers[0] = "feature_fusion/Conv_7/Sigmoid";
outputLayers[1] = "feature_fusion/concat_3";

Mat blob;

blobFromImage(*frame, blob, 1.0, Size(inpWidth, inpHeight), Scalar(123.68, 116.78, 103.94), true, false);
net.setInput(blob);
net.forward(output, outputLayers);

Mat scores = output[0];
Mat geometry = output[1];

// Decode predicted bounding boxes.
std::vector<RotatedRect> boxes;
std::vector<float> confidences;
decode(scores, geometry, confThreshold, boxes, confidences);

// Apply non-maximum suppression procedure.
std::vector<int> indices;
NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);

// Render detections.
Point2f ratio((float)(frame->cols)/ inpWidth, (float)frame->rows / inpHeight);
for (size_t i = 0; i < indices.size(); ++i)
{
RotatedRect& box = boxes[indices[i]];

Point2f vertices[4];
box.points(vertices);
for (int j = 0; j < 4; ++j)
{
vertices[j].x *= ratio.x;
vertices[j].y *= ratio.y;
}
for (int j = 0; j < 4; ++j)
line(*frame, vertices[j], vertices[(j + 1) % 4], Scalar(0, 255, 0), 2, LINE_AA);
}


}

std::string jstring2string(JNIEnv *env, jstring jStr) {
if (!jStr)
return "";

const jclass stringClass = env->GetObjectClass(jStr);
const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
const jbyteArray stringJbytes = (jbyteArray) env->CallObjectMethod(jStr, getBytes, env->NewStringUTF("UTF-8"));

size_t length = (size_t) env->GetArrayLength(stringJbytes);
jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);

std::string ret = std::string((char *)pBytes, length);
env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);

env->DeleteLocalRef(stringJbytes);
env->DeleteLocalRef(stringClass);
return ret;
}

I have referred this code from Learnopencv github of which i'll put a link down here.

https://github.com/spmallick/learnopencv/blob/master/TextDetectionEAST/textDetection.cpp

Please let me know if you have any idea about this problem. Thanks.

Solution Soni
  • 183
  • 2
  • 2
  • 11
  • 2
    These are linker errors, which means the compiler saw their prototypes and output code to call them, but when it came time to connect the call site to the actual function, it couldn't find the functions amongst the libraries and object files you gave it to link together. So you need to make sure you are linking to all the right libraries AND that they are listed in the right order (sometimes order matters on Linux). Figure out which library the missing functions are in (`nm` is your friend if you don't know which), and make sure it's in the list in the right place. You can repeat a lib also. – metal Feb 28 '19 at 12:43
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Matthieu Brucher Feb 28 '19 at 12:45

1 Answers1

0

Its seems like your CMakeLists.txt not linking OpenCV library.

target_link_libraries( # Specifies the target library.
        native-lib
        -ljnigraphics

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

Also check for the required libopencv_java3.so file is exists at your target processor's jniLibs path which is "arm64-v8a" here.

/home/karshsoni/Documents/CVTextDetection/app/src/main/jniLibs/arm64-v8a/libopencv_java3.so

Mayur Kanojiya
  • 158
  • 1
  • 8