2

I am trying to get a C++ program for capturing images using a Basler camera to work. I got the code from the manufacturer and it was supposed to be "very easy to use", however, linking it has become a nightmare. My C++ times are in the past (only using Matlab lately), so I might be making some stupid mistake, but please enlighten me:

The code looks like this:

// Include files to use the PYLON API.
#include <pylon/PylonIncludes.h>
#ifdef PYLON_WIN_BUILD
#    include <pylon/PylonGUI.h>
#endif

// Namespace for using pylon objects.
using namespace Pylon;
using namespace GenApi;


#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/video/video.hpp>
//#include <opencv2/videoio.hpp>

using namespace cv;




// Namespace for using cout.
using namespace std;

#include <stdio.h>
#include "kbhit.h"

#include <sys/stat.h>  // for checking the file size
#include <sstream>

// Number of images to be grabbed.
//static const uint32_t c_countOfImagesToGrab = 100;




int main(int argc, char* argv[])
{
    // The exit code of the sample application.
    int exitCode = 0;

    // Automagically call PylonInitialize and PylonTerminate to ensure the pylon runtime system
    // is initialized during the lifetime of this object.
    Pylon::PylonAutoInitTerm autoInitTerm;
    VideoWriter cvVideoCreator;
    struct stat statbuf;
    string filenameBase = "/opt/PylonTestAVI";
    uint filecounter = 1;
    string filename = "";

    ... (and so on)

I am trying to compile it using the following:

g++ GrabV3.cpp -I/opt/pylon5 -I/opt/pylon5/include -I/usr/local/include -I/usr/include/ -L/opt/pylon5/lib64 

Here /opt/pylon5 is Basler's own library and /usr/local/include links to the opencv4 folder.

I get a page-long error message list - the start looks like this GrabV3.cpp:(.text+0x2a5): undefined reference to cv::VideoWriter::VideoWriter()' GrabV3.cpp:(.text+0x32a): undefined reference toPylon::CTlFactory::GetInstance()' GrabV3.cpp:(.text+0x346): undefined reference to Pylon::CDeviceInfo::CDeviceInfo()' GrabV3.cpp:(.text+0x370): undefined reference toPylon::CInstantCamera::CInstantCamera(Pylon::IPylonDevice, Pylon::ECleanup)' GrabV3.cpp:(.text+0x38e): undefined reference to Pylon::CInstantCamera::Open()' GrabV3.cpp:(.text+0x39d): undefined reference toPylon::CInstantCamera::GetNodeMap()' GrabV3.cpp:(.text+0x3cb): undefined reference to GenICam_3_1_Basler_pylon::gcstring::gcstring(char const*)' GrabV3.cpp:(.text+0x41b): undefined reference toGenICam_3_1_Basler_pylon::gcstring::~gcstring()' GrabV3.cpp:(.text+0x465): undefined reference to GenICam_3_1_Basler_pylon::gcstring::gcstring(char const*)' GrabV3.cpp:(.text+0x488): undefined reference toGenICam_3_1_Basler_pylon::gcstring::~gcstring()' GrabV3.cpp:(.text+0x4af): undefined reference to GenICam_3_1_Basler_pylon::gcstring::gcstring(char const*)' GrabV3.cpp:(.text+0x4ff): undefined reference toGenICam_3_1_Basler_pylon::gcstring::~gcstring()' GrabV3.cpp:(.text+0x526): undefined reference to GenICam_3_1_Basler_pylon::gcstring::gcstring(char const*)' GrabV3.cpp:(.text+0x576): undefined reference toGenICam_3_1_Basler_pylon::gcstring::~gcstring()' GrabV3.cpp:(.text+0x745): undefined reference to `cv::VideoWriter::open(cv::String const&, int, double, cv::Size_, bool)'*

so apparently nothing works, starting with the cv:VideoWriter() function which is a part of standard OpenCV (which I installed using this tutorial: https://cv-tricks.com/installation/opencv-4-1-ubuntu18-04/).

So I am lost here - already spent about a day trying to make it work. Can somebody help?

mikael
  • 49
  • 6
  • Please, try `g++` instead of `gcc`. (Missing reference to `std::basic_string` let me think that std c++ lib. isn't linked. `g++` should do this by default.) – Scheff's Cat Oct 03 '19 at 10:08
  • Possible duplicate of [What is the difference between g++ and gcc?](https://stackoverflow.com/questions/172587/what-is-the-difference-between-g-and-gcc) – Scheff's Cat Oct 03 '19 at 10:12
  • Using g++ helps slightly, as the Missing reference errors disappear. However, I am still getting the Undefined reference from classes I believe I have linked. – mikael Oct 03 '19 at 10:25
  • Can you [edit] and update your question with the error messages got for `g++`? – Scheff's Cat Oct 03 '19 at 10:26
  • 1
    Looking again at your command, I strongly believe there is/are missing lib. which causes the left Undefined Reference errors (link errors). To elaborate cmd. args.: `-I` (capital i) is for include paths (for compiler). `-L` is for library paths (for linker). `-l` (small ell) is for libraries. I don't see any `-l` argument in your compile command. I believe this is what you are missing. – Scheff's Cat Oct 03 '19 at 10:32
  • 1
    As @Scheff mentions you need to link with the proper libraries. As I can see you only link with this pylon library but you also use opencv and you get also an undefined reference for this (I believe installing alone is not enough for the linker to find the right library). – Philipp Oct 03 '19 at 11:13
  • Yes, I thought so, but I cannot get it done properly. As cv::VideoWriter() is a function of OpenCV, I thought linking -L/usr/local/include/opencv4/opencv2 or even simpler -L/usr/local/include should suffice, but I'm getting the same errors no matter what I link. – mikael Oct 03 '19 at 11:18
  • I think a library shouldn't not reside in `/usr/local/include`. Only header files should be there (but I work mostly on Windows). There should be a folder containing the static librarie(s) of opencv which you can then link. Also see here https://stackoverflow.com/questions/47410667/link-to-external-library-with-g for more information how to link. – Philipp Oct 03 '19 at 11:26
  • You might wanna have a look in `/usr/local/lib` I believe that's one of the locations libraries get installed to. If it's in one of the default locations all you need to to is to add `-Llibraryname` (`-Lopencv`) to your compile command – Philipp Oct 03 '19 at 11:28
  • g++ GrabV3.cpp -I/opt/pylon5/include -I/opt/pylon5/include/pylon -L/usr/local/lib -Lopencv brings about the same error litany. My /usr/local/lib does include many "libopencv*.so" named files, but shouldn't -L/usr/local/lib link to these? – mikael Oct 03 '19 at 12:11
  • Normally, packages such as OpenCV include a file in them called `xxx.pc` These are `pkg-config` files, and there is a utility called `pkg-config` that can read them and tell you the correct include paths (`-I` uppercase letter `i`) for headers, the correct library paths (`-L`) and the correct libraries (`-l` lowercase letter `L`). So your compilation command becomes `g++ $(pkg-config --cflags --libs opencv) main.cpp -o main` or similar and it pulls in all the correct switches. – Mark Setchell Oct 03 '19 at 12:36
  • 1
    So, this command will tell you all the packages that `pkg-config` knows about `pkg-config --list-all` and you should be able to find **OpenCV** and **Pylon** in there, say as **opencv4**. Then you can get the libraries for that with `pkg-config --libs --cflags opencv4` and put that in your compilation command inside `$(...)`. Likewise for Pylon. – Mark Setchell Oct 03 '19 at 13:10
  • @Mark Indeed, in /usr/local/lib/pkgconfig there is a "opencv4.pc" -file. Using your syntax, my linking command became: _g++ $(pkg-config --cflags --libs opencv4) GrabV3.cpp -I/opt/pylon5/include -I/opt/pylon5/include/pylon -L/opt/pylon5/lib64_ and the error messages became quite different, _GrabV3.cpp:83:32: error: ‘CV_FOURCC’ was not declared in this scope cvVideoCreator.open(filename,CV_FOURCC('D','I','V','X'),20,FrameSize,true);_ So now the opencv4 libraries appear to have been successfully linked and the problem seems easier to handle. I will keep trying. – mikael Oct 03 '19 at 13:12
  • 1
    Ok, looking at your code in more detail... the include files inside your code itself are wrong for OpenCV4. They all changed and there is now just ONE include file for the whole of OpenCV, not `core.hpp`, `highgui.hpp` and `video.hpp` I think it is `#include ` – Mark Setchell Oct 03 '19 at 14:39
  • Sorry for a very late answer, I thought the discussion had died out. Thanks for the suggestion, but changing the 3 includes to _#include _ results in the same, the compiler fails to see the macro, although it is clearly linked as _videoih.h_ is behind _/usr/include/opencv2/videoio/videoio.h_ . This function is actually a very simple macro; I also tried writing it out in the variable, but this somehow also completely screws up the linking. – mikael Oct 14 '19 at 10:56

1 Answers1

0

Okay, so Mark's suggestion solved the linking problem. However, as the software still isn't compiled, and we're still inside the "Compiling a program for using a Basler Camera" theme, I will continue with a scope problem:

g++ $(pkg-config --cflags --libs opencv4) GrabV3.cpp -I/opt/pylon5/include -I/opt/pylon5/include/pylon -L/opt/pylon5/lib64 -L/opt/pylon5/include/pylon

now gives the following error:

 GrabV3.cpp: In function ‘int main(int, char**)’:
  GrabV3.cpp:84:32: error: ‘CV_FOURCC’ was not declared in this scope
  cvVideoCreator.open(filename,CV_FOURCC('D','I','V','X'),20,FrameSize,true);

After the "and so on" (see my first post) the code continues as follows:

 try
{
    // Create an instant camera object with the camera device found first.
    CInstantCamera camera( CTlFactory::GetInstance().CreateFirstDevice());

    camera.Open();

    INodeMap& nodeMap = camera.GetNodeMap();
    CEnumerationPtr TestImageSelector = nodeMap.GetNode("TestImageSelector");
    TestImageSelector->FromString("Testimage4");

    CIntegerPtr Width = nodeMap.GetNode("Width");
    CIntegerPtr Height = nodeMap.GetNode("Height");
    Size FrameSize = Size(Width->GetValue(),Height->GetValue());
    stringstream s ;
    s<<"_" ;
    s<< filecounter;
    filename = filenameBase;
    filename += s.str() + ".avi";

    //cvVideoCreator.open("``/opt/PylonTest_DIVX.avi",CV_FOURCC('M','P','4','2'),20,FrameSize,true);
    cvVideoCreator.open(filename,CV_FOURCC('D','I','V','X'),20,FrameSize,true);
    //cvVideoCreator.open("/opt/PylonTest.avi",CV_FOURCC('M','J','P','G'),20,FrameSize,true);


    // Print the model name of the camera.
    cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl;

    // The parameter MaxNumBuffer can be used to control the count of buffers
    // allocated for grabbing. The default value of this parameter is 10.
    camera.MaxNumBuffer = 5;
    CImageFormatConverter fc;
    fc.OutputPixelFormat = PixelType_BGR8packed;
    CPylonImage image;

    // Start the grabbing of c_countOfImagesToGrab images.
    // The camera device is parameterized with a default configuration which
    // sets up free-running continuous acquisition.
    camera.StartGrabbing();

    // This smart pointer will receive the grab result data.
    CGrabResultPtr ptrGrabResult;

CV_FOURCC('D','I','V','X') is a INLINE function defined in /usr/include/opencv2/videoio/videoio_c.h, which is now out of scope for some reason.

I tried to bruteforce-link it by including

#include "/usr/include/opencv2/videoio/videoio_c.h"

but this resulted in completely screwing up the linking. Thanks for @Mark for getting me this far; how to get on from here?

mikael
  • 49
  • 6