Undefined symbol: cv::imwrite when linking with Qt Creator

Hello,

I am trying to built a mobile app using CMake with Qt and OpenCV, but I get an error when running make.

Those are my files

CMakeLists.txt file

cmake_minimum_required(VERSION 3.16)
project(androidnotifier LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

find_package(Qt6 COMPONENTS Multimedia Widgets Core REQUIRED)

set(OpenCV_DIR "/home/ivelin/opencv/platforms/linux/build_hardfp")

set(PROJECT_SOURCES
        main.cpp
)

if(ANDROID)
    set(ANDROID_TARGET_SDK_VERSION 30)
    qt_add_executable(androidnotifier
        MANUAL_FINALIZATION
        ${PROJECT_SOURCES}
        )
            find_package(OpenCV)
        message("message: ${OpenCV_PATH}")


        include_directories( ${OpenCV_PATH} )

        target_link_libraries(androidnotifier PRIVATE Qt6::Multimedia Qt6::Widgets Qt6::Core Qt6::CorePrivate ${OpenCV_LIBS})


    set_property(TARGET androidnotifier APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
                 ${CMAKE_CURRENT_SOURCE_DIR}/android)

    qt_finalize_executable(androidnotifier)

    qt6_add_resources(androidnotifier "main"
        PREFIX
            "/"
    )
endif()

main.cpp

#include <opencv2/opencv.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;

int main()
{
    // Create a VideoCapture object to capture from the camera
    VideoCapture cap(0);

    // Check if the camera is opened successfully
    if (!cap.isOpened())
    {
        std::cout << "Error opening video capture" << std::endl;
        return -1;
    }

    // Set the desired frame width and height
    cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480);

    // Capture a frame
    Mat frame;
    cap.read(frame);

    // Save the frame to disk
    std::string filename = "captured_image.jpg";
    cv::imwrite(filename, frame);

    // Release the VideoCapture object
    cap.release();

    return 0;
}

I type those commands to start building it:

cmake -DCMAKE_TOOLCHAIN_FILE=/home/ivelin/Qt/6.2.4/android_arm64_v8a/lib/cmake/Qt6/qt.toolchain.cmake .
make 

adb install -r android-build/androidnotifier.apk

But I get

-- Build files have been written to: /home/ivelin/Qt/Examples/Qt-6.2.4/corelib/platform/androidnotifier
[ 16%] Automatic MOC and UIC for target androidnotifier
[ 16%] Built target androidnotifier_autogen
[ 33%] Building CXX object CMakeFiles/androidnotifier.dir/androidnotifier_autogen/mocs_compilation.cpp.o
[ 50%] Building CXX object CMakeFiles/androidnotifier.dir/main.cpp.o
[ 66%] Linking CXX shared module libandroidnotifier_arm64-v8a.so
ld: error: undefined symbol: cv::imwrite(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, cv::_InputArray const&, std::__ndk1::vector<int, std::__ndk1::allocator<int> > const&)
>>> referenced by main.cpp:29
>>>               CMakeFiles/androidnotifier.dir/main.cpp.o:(main)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [CMakeFiles/androidnotifier.dir/build.make:135: libandroidnotifier_arm64-v8a.so] Error 1
make[1]: *** [CMakeFiles/Makefile2:225: CMakeFiles/androidnotifier.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

However, when I remove this line from the main.cpp

    cv::imwrite(filename, frame);

It works fine.

Why is that ? Could someone please try to help me out here?

so your issue isn’t with Qt, it’s with not linking the imgcodecs module, which does contain imwrite()

Thank you for you answer.

I can’t see why that is.

I have added the OpenCV_LIBS variable to target_link_libraries. I have printed it out it is

opencv_calib3d;opencv_core;opencv_dnn;opencv_features2d;opencv_flann;opencv_gapi;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_stitching;opencv_video;opencv_videoio

Why is it not linking it correctly?

The problem is not in linking, but missing #include <imgcodecs.hpp> that tells the compiler the detailed definition of the function.

Hello,

I have tried that too. This is my current code:

#include <opencv2/opencv.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;

int main()
{
    // Create a VideoCapture object to capture from the camera
    VideoCapture cap(0);

    // Check if the camera is opened successfully
    if (!cap.isOpened())
    {
        std::cout << "Error opening video capture" << std::endl;
        return -1;
    }

    // Set the desired frame width and height
    cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480);

    // Capture a frame
    Mat frame;
    cap.read(frame);

    // Save the frame to disk
    std::string filename = "captured_image.jpg";
    cv::imwrite(filename, frame);

    // Release the VideoCapture object
    cap.release();

    return 0;
}

However, I get the same error:

ld: error: undefined symbol: cv::imwrite(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, cv::_InputArray const&, std::__ndk1::vector<int, std::__ndk1::allocator<int> > const&)
>>> referenced by main.cpp:29
>>>               CMakeFiles/androidnotifier.dir/main.cpp.o:(main)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [CMakeFiles/androidnotifier.dir/build.make:135: libandroidnotifier_arm64-v8a.so] Error 1
make[1]: *** [CMakeFiles/Makefile2:225: CMakeFiles/androidnotifier.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

looks like you’re linking against a different c++ std , than the opencv libs were built with (for sure NOT __ndk1)

Could you please explain me how to link it to the correct one ? I am unaware how exactly that works and I have found nothing for the past couple of days. I suppose I have to configure those things in the CMake file?

Sorry for the bother again, but after some research I still do not understand.

Do I have to switch from CMake to Android.mk ?

no, (if i’m right at all), you must check, which c++ std lib was used, when building your opencv libs, and use the same for your program

and sorry to say so, your project is way off the trodden path, can’t help much further ;(