1

I'm trying to compile a simple program using OpenCV 4.6.0 in C++ (I'm on Ubuntu 20.04 and that's the default installation) that reads an image, runs a BRISK feature detection, and displays the keypoints' locations on the image using imshow. I can do proprocessing, compilation, and assembly into a .o file no problem, but g++ has so far flatly refused to do the linking step.

I was originally getting an undefined reference error for every OpenCV function call, but after much pain and trial-and-error, including uninstalling and reinstalling OpenCV multiple times (following the instructions at https://docs.opencv.org/4.x/d7/d9f/tutorial_linux_install.html#tutorial_linux_install_detailed_basic_verify), I realized that for some reason, g++ will only link to OpenCV libraries when explicitly told to do so with -l. I have now written a bash script to manually link every single OpenCV library I can find in /usr/local/lib. The script is called opencv_linker, and it contains the following:

#!/bin/bash
g++ $@ -lopencv_core -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lopencv_calib3d -lopencv_dnn -lopencv_features2d -lopencv_flann -lopencv_gapi -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_videoio -lopencv_video

I run it from the command line as

./opencv_linker brisk_test.cpp -I/usr/local/include/opencv4

(I will turn this into a makefile eventually, but for now I'm just trying to get OpenCV to work at all. Also, I'm sure I don't strictly need all of these libraries for what I'm doing, but I don't have a good reference for which libraries include which functions, so I'm taking the brute force route.)

Running the above in the command line gives the following error:

usr/bin/ld: /tmp/ccdVMcvM.o: in function `main':
<path_to_directory>/brisk_test.cpp:19: undefined reference to `cv::Mat::Mat()'
collect2: error: ld returned 1 exit status

I have also tried running g++ brisk_test.cpp -I/usr/local/include/opencv4 `pkg-config --libs opencv4`, which I think is equivalent. Same result. Swapping the order of the -I argument and the pkg-config argument didn't change anything.

I've run out of ideas as to what to do to eliminate this last undefined reference. I don't understand why g++ would be unable to find cv::Mat::Mat() in any of the OpenCV libraries (unless there's another library somewhere that I just don't know about). I've searched for answers online, and nothing I've found has addressed the problem -- the answers to this post and this post didn't solve the problem, and this post doesn't have an answer. If anyone has any ideas as to what might be going on, I will be eternally grateful.

EDIT: I don't think the order in which I'm linking the libraries is an issue (but I could be wrong). Everything online about the order in which to link the libraries just says to use `pkg-config --cflags --libs opencv4` (sometimes without --cflags), and apparently that should take care of the ordering? I've tried the following six commands:

g++ -g brisk_test.cpp -I/usr/local/include/opencv4 `pkg-config --libs opencv4`
g++ -g brisk_test.cpp `pkg-config --libs opencv4` -I/usr/local/include/opencv4
g++ -g brisk_test.cpp -I/usr/local/include/opencv4 `pkg-config --cflags --libs opencv4`
g++ -g brisk_test.cpp `pkg-config --cflags --libs opencv4` -I/usr/local/include/opencv4
g++ -g `pkg-config --cflags opencv4` brisk_test.cpp `pkg-config --libs opencv4` -I/usr/local/include/opencv4
g++ -g `pkg-config --cflags opencv4` brisk_test.cpp -I/usr/local/include/opencv4 `pkg-config --libs opencv4`

All of them gave me the same error message as above.

EDIT 2: Here's the output of nm -CD /usr/local/lib/libopencv_core.so | grep Mat::Mat:

$ nm -CD /usr/local/lib/libopencv_core.so | grep Mat::Mat
00000000001c2580 T cv::Mat::Mat(int, int, int)
00000000001c12e0 T cv::Mat::Mat(int, int, int, void*, unsigned long)
00000000001c25d0 T cv::Mat::Mat(int, int, int, cv::Scalar_<double> const&)
00000000001c2440 T cv::Mat::Mat(int, int const*, int)
00000000001c2ab0 T cv::Mat::Mat(int, int const*, int, void*, unsigned long const*)
00000000001c2490 T cv::Mat::Mat(int, int const*, int, cv::Scalar_<double> const&)
00000000001c2640 T cv::Mat::Mat(cv::Size_<int>, int)
00000000001c14e0 T cv::Mat::Mat(cv::Size_<int>, int, void*, unsigned long)
00000000001c2690 T cv::Mat::Mat(cv::Size_<int>, int, cv::Scalar_<double> const&)
00000000001c1790 T cv::Mat::Mat(cv::Mat&&)
00000000001c19e0 T cv::Mat::Mat(cv::Mat const&)
00000000001c3630 T cv::Mat::Mat(cv::Mat const&, cv::Range const*)
00000000001c38a0 T cv::Mat::Mat(cv::Mat const&, cv::Range const&, cv::Range const&)
00000000001c2800 T cv::Mat::Mat(cv::Mat const&, cv::Rect_<int> const&)
00000000001c3cb0 T cv::Mat::Mat(cv::Mat const&, std::vector<cv::Range, std::allocator<cv::Range> > const&)
00000000001c2740 T cv::Mat::Mat(std::vector<int, std::allocator<int> > const&, int)
00000000001c34e0 T cv::Mat::Mat(std::vector<int, std::allocator<int> > const&, int, void*, unsigned long const*)
00000000001c2790 T cv::Mat::Mat(std::vector<int, std::allocator<int> > const&, int, cv::Scalar_<double> const&)
00000000001c11c0 T cv::Mat::Mat()
00000000001c2580 T cv::Mat::Mat(int, int, int)
00000000001c12e0 T cv::Mat::Mat(int, int, int, void*, unsigned long)
00000000001c25d0 T cv::Mat::Mat(int, int, int, cv::Scalar_<double> const&)
00000000001c2440 T cv::Mat::Mat(int, int const*, int)
00000000001c2ab0 T cv::Mat::Mat(int, int const*, int, void*, unsigned long const*)
00000000001c2490 T cv::Mat::Mat(int, int const*, int, cv::Scalar_<double> const&)
00000000001c2640 T cv::Mat::Mat(cv::Size_<int>, int)
00000000001c14e0 T cv::Mat::Mat(cv::Size_<int>, int, void*, unsigned long)
00000000001c2690 T cv::Mat::Mat(cv::Size_<int>, int, cv::Scalar_<double> const&)
00000000001c1790 T cv::Mat::Mat(cv::Mat&&)
00000000001c19e0 T cv::Mat::Mat(cv::Mat const&)
00000000001c3630 T cv::Mat::Mat(cv::Mat const&, cv::Range const*)
00000000001c38a0 T cv::Mat::Mat(cv::Mat const&, cv::Range const&, cv::Range const&)
00000000001c2800 T cv::Mat::Mat(cv::Mat const&, cv::Rect_<int> const&)
00000000001c3cb0 T cv::Mat::Mat(cv::Mat const&, std::vector<cv::Range, std::allocator<cv::Range> > const&)
00000000001c2740 T cv::Mat::Mat(std::vector<int, std::allocator<int> > const&, int)
00000000001c34e0 T cv::Mat::Mat(std::vector<int, std::allocator<int> > const&, int, void*, unsigned long const*)
00000000001c2790 T cv::Mat::Mat(std::vector<int, std::allocator<int> > const&, int, cv::Scalar_<double> const&)
00000000001c11c0 T cv::Mat::Mat()

EDIT 3: I know which line of code is causing a problem, thanks to me having the bright idea of trying something which I really should have tried already (my bad, sorry -- I'm really not an expert at this): namely, commenting out lines of code until the program successfully compiles and links. When I reduce my program to just the following lines of code, it compiles and links successfully to produce an executable:

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/features2d.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc, char* argv[])
{
  Mat img = imread("test_image.jpg", IMREAD_GRAYSCALE);
  
  Ptr<BRISK> detector = BRISK::create();
  std::vector<KeyPoint> keypoints;
  detector->detect(img, keypoints);
  
  return EXIT_SUCCESS;
}

What breaks the code is the addition of the next line necessary to draw keypoints: namely, g++ is unable to do the linking when I add the line Mat img_keypoints; before the return. I don't understand why that line would cause an issue, particularly since I am apparently able to create a Mat object in the first line. I do know that the error occurs in the linking step, though, as I am able to compile and assemble my program into a .o file, even with the problematic line of code included.

EDIT 4: Changing the code above (which works) to split the first line into two also breaks things: namely,

int main(int argc, char* argv[])
{
  Mat img;
  img = imread("test_image.jpg", IMREAD_GRAYSCALE);
  
  Ptr<BRISK> detector = BRISK::create();
  std::vector<KeyPoint> keypoints;
  detector->detect(img, keypoints);
  
  return EXIT_SUCCESS;
}

also gives me the same linker error.

Iascaire
  • 11
  • 4
  • 1
    Strange, it should be in opencv_core. Do you have libopencv_core.so in /usr/local/lib? Can you do `nm -CD /usr/local/lib/libopencv_code.so | grep Mat::Mat`? – n. m. could be an AI Jun 30 '22 at 15:19
  • Sorry for the belated reply. The output is too long for a comment, so I'll edit my question above. It does look like it should be there, which is interesting. – Iascaire Jul 01 '22 at 13:27
  • So it is there. You may somehow got yourself a set of 32 bit libraries. What does `file /usr/local/lib/libopencv_core.so` say? – n. m. could be an AI Jul 01 '22 at 16:33
  • libopencv_core.so is a symbolic link to libopencv_core.so.406, which is in turn a link to libopencv_core.so.4.6.0. ```file /usr/local/lib/libopencv_core.so.4.6.0``` gives the following output: ```/usr/local/lib/libopencv_core.so.4.6.0: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=093c7b7f36398ea824fe64041efd0c836d9df2c7, not stripped``` – Iascaire Jul 01 '22 at 17:19
  • No idea. Try `g++ -v brisk_test.cpp -I/usr/local/include/opencv4 -lopencv_core` (only). Look at the verbose output. – n. m. could be an AI Jul 01 '22 at 17:24
  • You can also try `-Wl,--verbose`. – n. m. could be an AI Jul 01 '22 at 18:01
  • 1
    The verbose output does include the line ```attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libopencv_core.so succeeded```. I also have determined which line of code in my program is causing the problem, and I'll update my question momentarily with info on that. I don't know why it's causing a problem, but hopefully this helps. Thank you so, so much for your help, by the way. – Iascaire Jul 01 '22 at 19:36
  • It seems you have opencv installed in more than one place, and you are linking with your system-installed opencv, which may be of a different version. Try uninstalling it and/or add `-L /usr/locval/lib` to your link flags. – n. m. could be an AI Jul 02 '22 at 09:50
  • You may be right -- I thought I had deleted everything opencv-related from my system prior to reinstalling, but when I added ```-L/usr/local/lib```, I got the following message: ```/usr/bin/ld: warning: libopencv_core.so.4.2, needed by /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libopencv_aruco.so, may conflict with libopencv_core.so.406``` as well as a couple similar messages about other libraries. Can I go in and manually delete the conflicting libraries? I'm a Linux novice and I don't want to break my computer... – Iascaire Jul 05 '22 at 13:19
  • No, use a package manager to (possibly repair and then) uninstall the package cleanly. You don't have to do it right now, try to add `-Wl,-rpath=/usr/local/lib` linker option and see if the warning goes away. But in the long run it is better not to have any conflicts. – n. m. could be an AI Jul 05 '22 at 13:34
  • Apologies for my belated response. Unfortunately, the linker option you suggested didn't work. I do think I have a better grasp of what my problem is, though. I installed OpenCV from source, not using a package manager like apt, and perhaps that was a mistake. Apparently I do have a previous version of OpenCV installed, but I don't know who installed it or how it was installed, so I don't know how to remove it. I could play around with apt to try to figure it out, but I'm having misc. issues with apt that are outside the scope of this question. In any case, thank you so much for all your help! – Iascaire Jul 08 '22 at 14:45

0 Answers0