playerproject / player

The Player cross-platform robot device interface & server
GNU General Public License v2.0
60 stars 32 forks source link

Fixing compatibility with OpenCV 4.9.0 and cvLoadImage not declared #28

Open ShadowOne333 opened 2 months ago

ShadowOne333 commented 2 months ago

I've been trying to compile the latest master branch for Player 3.1.1-dev, and I've been stumbling into a lot of issues regarding compatibility with some drivers and the current version of OpenCV. From what I could gather, the code for Player is currently using instances and functions from OpenCV 2, which has long been deprecated from what I know, and it currently sits at OpenCV 4.9 as the stable version.

However, OpenCV 4 does still offer the C API instructions and functions, so I managed to get the vast majority of the Player code to compile by changing some header names and directories to that of the current OpenCV 4 naming scheme as seen in this commit to my fork of Player: https://github.com/ShadowOne333/player/commit/6cc302ea21f18535331c7128d8e4ed6dd1d0b985

The majority of the drivers compile just fine now, with the exception of two specific cases: SimpleShape and ImageSeq.

These two rely on a very old OpenCV 2 cvLoadImage function, which apparently is not available/declared anymore in OpenCV 4, and the compilation for these two fail with the following error:

[ 40%] Building CXX object server/libplayerdrivers/CMakeFiles/playerdrivers.dir/__/drivers/blobfinder/simpleshape/simpleshape.o
player/server/drivers/blobfinder/simpleshape/simpleshape.cc: In member function ‘int SimpleShape::LoadModel()’:
player/server/drivers/blobfinder/simpleshape/simpleshape.cc:318:9: error: ‘cvLoadImage’ was not declared in this scope; did you mean ‘cvCloneImage’?
  318 |   img = cvLoadImage( this->modelFilename, 0);
      |         ^~~~~~~~~~~
      |         cvCloneImage
make[2]: *** [server/libplayerdrivers/CMakeFiles/playerdrivers.dir/build.make:216: server/libplayerdrivers/CMakeFiles/playerdrivers.dir/__/drivers/blobfinder/simpleshape/simpleshape.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:3802: server/libplayerdrivers/CMakeFiles/playerdrivers.dir/all] Error 2
make: *** [Makefile:156: all] Error 2

Here are the exact lines in which that function is called for both drivers:

I tried to fix it myself by declaring cvLoadImage manually inside those two .cc files as listed in the old OpenCV 2 documentation:

// Declare cvLoadImage
IplImage* cvLoadImage( const char* filename, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR));

But unfortunately, that breaks the compilation when trying to build the player executable:

[ 76%] Linking CXX executable player
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: libplayerdrivers/libplayerdrivers.so.3.1.1-dev: undefined reference to `cvLoadImage(char const*, int)'
collect2: error: ld returned 1 exit status

I only need to fix this undeclared/undefined instance of cvLoadImage in order to properly make Player as a whole compile with OpenCV 4. If I disable both ImageSeq and SimpleShape from CMake, then Player finished compilation without issues, so it's only that function left to properly update Player for OpenCV 4.

Anyone has any idea how to make this work?

As soon as a fix to that cvLoadImage function declaration is found, I will make the proper Pull Request of the changes so that Player can be used with Open CV 4.9.0, at least until OpenCV decides to remove the C API altogether, then the entire drivers relying on OpenCV would need to be updated to the current/new OpenCV 4 functions.

ShadowOne333 commented 2 months ago

I think I managed to fix the cvLoadImage calls by using a conversion to cvarrToMat from OpenCV's documentation.

Here's the modified lines for SimpleShape: https://github.com/ShadowOne333/player/blob/master/server/drivers/blobfinder/simpleshape/simpleshape.cc#L311-L326

And the modified lines for ImageSeq: https://github.com/ShadowOne333/player/blob/master/server/drivers/camera/imageseq/imageseq.cc#L206-L218

Taking ImageSeq changes as an example, I commented out the original lines, and added the cv::Mat with cvarrToMat conversion so that those cvLoadImage functions now user cv::imread instead:

  IplImage *image;
  cv::Mat image2 = cv::cvarrToMat(image);

  // Load image; currently forces the image to mono
  //image = cvLoadImage(filename, -1);
  image2 = cv::imread( filename, cv::IMREAD_UNCHANGED );

  //if(image == NULL)
  if( image2.empty() )
  {
        PLAYER_ERROR1("Could not load image file: %s", filename);
        return -1;
  }

It's nothing too complicated, and by doing this I managed to compile Player with the latest OpenCV4 successfully. So if anyone is willing to, I'll send a PR with these changes, so people more adept than me in these things can review it properly and let me know if something's missing or if I did something wrong.

Pull Request #29 should fix this issue.