opencv / opencv

Open Source Computer Vision Library
https://opencv.org
Apache License 2.0
75.95k stars 55.62k forks source link

Build failed with -DBUILD_EXAMPLES=ON #23329

Closed beew closed 1 year ago

beew commented 1 year ago

System Information

Opencv version 4.7.0-dev

OS Ubuntu 22.04

compiler gcc9.3.0

python 3.10.9

Detailed description

Building opencv failed if the flag -DBUILD_EXAMPLES is ON

it was successful if the flag is not set.

The error was

72%] Building CXX object modules/ovis/CMakeFiles/example_ovis_ovis_demo.dir/samples/ovis_demo.cpp.o
/home/bernard/opt/opencv/opencv_contrib/modules/ovis/samples/aruco_ar_demo.cpp:6:10: fatal error: opencv2/aruco_detector.hpp: No such file or directory
    6 | #include <opencv2/aruco_detector.hpp>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [modules/ovis/CMakeFiles/example_ovis_aruco_ar_demo.dir/build.make:76: modules/ovis/CMakeFiles/example_ovis_aruco_ar_demo.dir/samples/aruco_ar_demo.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:10655: modules/ovis/CMakeFiles/example_ovis_aruco_ar_demo.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....

Steps to reproduce

See above

Issue submission checklist

Kumataro commented 1 year ago

Hi, thank you for your report. It seems that not easy problem to complty fix. I think this issue requests some comments.

  1. This problem occurs in sample program in "ovis" module at opencv_contrib.
  2. aruco module is moved between opencv and opencv_contrib in OpenCV 4.7.0 URL. In this time, some functions had been deprecated,, and some functions lost backcompatibility.
  3. However ovis module is not adapted for this aruco changes. So some rewritting/fixing code is needed.

To suppress compile errors, we have some options.

  1. Disable ovis module. ( ‘BUILD_opencv_ovis = OFF` )
  2. Remove libogre-*-dev if it is not needed.
  3. Remove this sample program from ovis module.
  4. Fix this sample program to adapt changing new aruco module.

Following is considered only to suppress comple errors, it is not good fix.

And same problem occurs in sample program written by python.

$ git --no-pager diff
diff --git a/modules/ovis/CMakeLists.txt b/modules/ovis/CMakeLists.txt
index 912b86a5..92decf5d 100644
--- a/modules/ovis/CMakeLists.txt
+++ b/modules/ovis/CMakeLists.txt
@@ -24,7 +24,7 @@ ocv_glob_module_sources()
 ocv_module_include_directories()
 ocv_create_module()

-ocv_add_samples(opencv_aruco)
+ocv_add_samples(opencv_objdetect)

 ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-parameter)
 ocv_target_link_libraries(${the_module} ${OGRE_LIBRARIES})
diff --git a/modules/ovis/samples/aruco_ar_demo.cpp b/modules/ovis/samples/aruco_ar_demo.cpp
index 2398a718..87a04795 100644
--- a/modules/ovis/samples/aruco_ar_demo.cpp
+++ b/modules/ovis/samples/aruco_ar_demo.cpp
@@ -1,9 +1,9 @@
 #include <opencv2/highgui.hpp>
 #include <opencv2/calib3d.hpp>
 #include <opencv2/videoio.hpp>
+#include <opencv2/objdetect.hpp>

 #include <opencv2/ovis.hpp>
-#include <opencv2/aruco_detector.hpp>

 #include <iostream>

@@ -12,6 +12,79 @@

 using namespace cv;

+/**
+  backport from OpenCV 4.6.0
+  */
+
+enum PatternPos {
+    /** @brief The marker coordinate system is centered on the middle of the marker.
+        * The coordinates of the four corners (CCW order) of the marker in its own coordinate system are:
+        * (-markerLength/2, markerLength/2, 0), (markerLength/2, markerLength/2, 0),
+        * (markerLength/2, -markerLength/2, 0), (-markerLength/2, -markerLength/2, 0).
+        *
+        * These pattern points define this coordinate system:
+        * ![Image with axes drawn](images/singlemarkersaxes.jpg)
+        */
+    CCW_center,
+    /** @brief The marker coordinate system is centered on the top-left corner of the marker.
+        * The coordinates of the four corners (CW order) of the marker in its own coordinate system are:
+        * (0, 0, 0), (markerLength, 0, 0),
+        * (markerLength, markerLength, 0), (0, markerLength, 0).
+        *
+        * These pattern points define this coordinate system:
+        * ![Image with axes drawn](images/singlemarkersaxes2.jpg)
+        */
+    CW_top_left_corner
+};
+
+struct EstimateParameters {
+    CV_PROP_RW PatternPos pattern;
+    CV_PROP_RW bool useExtrinsicGuess;
+    CV_PROP_RW SolvePnPMethod solvePnPMethod;
+
+    EstimateParameters(): pattern(CCW_center), useExtrinsicGuess(false),
+                          solvePnPMethod(SOLVEPNP_ITERATIVE) {}
+
+    CV_WRAP static Ptr<EstimateParameters> create() {
+        return makePtr<EstimateParameters>();
+    }
+};
+
+/**
+  * @brief Return object points for the system centered in a middle (by default) or in a top left corner of single
+  * marker, given the marker length
+  */
+static void _getSingleMarkerObjectPoints(float markerLength, OutputArray _objPoints,
+                                         EstimateParameters estimateParameters) {
+
+    CV_Assert(markerLength > 0);
+
+    _objPoints.create(4, 1, CV_32FC3);
+    Mat objPoints = _objPoints.getMat();
+    // set coordinate system in the top-left corner of the marker, with Z pointing out
+    if (estimateParameters.pattern == CW_top_left_corner) {
+        objPoints.ptr<Vec3f>(0)[0] = Vec3f(0.f, 0.f, 0);
+        objPoints.ptr<Vec3f>(0)[1] = Vec3f(markerLength, 0.f, 0);
+        objPoints.ptr<Vec3f>(0)[2] = Vec3f(markerLength, markerLength, 0);
+        objPoints.ptr<Vec3f>(0)[3] = Vec3f(0.f, markerLength, 0);
+    }
+    else if (estimateParameters.pattern == CCW_center) {
+        objPoints.ptr<Vec3f>(0)[0] = Vec3f(-markerLength/2.f, markerLength/2.f, 0);
+        objPoints.ptr<Vec3f>(0)[1] = Vec3f(markerLength/2.f, markerLength/2.f, 0);
+        objPoints.ptr<Vec3f>(0)[2] = Vec3f(markerLength/2.f, -markerLength/2.f, 0);
+        objPoints.ptr<Vec3f>(0)[3] = Vec3f(-markerLength/2.f, -markerLength/2.f, 0);
+    }
+    else
+        CV_Error(Error::StsBadArg, "Unknown estimateParameters pattern");
+}
+
+
+static void estimatePoseSingleMarkers(InputArrayOfArrays corners, float markerLength,
+                                            InputArray cameraMatrix, InputArray distCoeffs,
+                                            OutputArray rvecs, OutputArray tvecs, OutputArray _objPoints = noArray(),
+                                            Ptr<EstimateParameters> estimateParameters = EstimateParameters::create());
+
+
 int main()
 {
   Mat img;
@@ -24,11 +97,13 @@ int main()
   const double focal_length = 800.0;

   // aruco
-  Ptr<aruco::Dictionary> adict = aruco::getPredefinedDictionary(aruco::DICT_4X4_50);
+  aruco::Dictionary adict = aruco::getPredefinedDictionary(aruco::DICT_4X4_50);
   //Mat out_img;
   //aruco::drawMarker(adict, 0, 400, out_img);
   //imshow("marker", out_img);

+  aruco::ArucoDetector detector(adict);
+
   // random calibration data, your mileage may vary
   Mat1d cm = Mat1d::zeros(3, 3); // init empty matrix
   cm.at<double>(0, 0) = focal_length; // f_x
@@ -53,16 +128,47 @@ int main()
   while (ovis::waitKey(1) != KEY_ESCAPE) {
     cap.read(img);
     win->setBackground(img);
-    aruco::detectMarkers(img, adict, corners, ids);
+    detector.detectMarkers(img, corners, ids);

     waitKey(1);

     if (ids.size() == 0)
       continue;

-    aruco::estimatePoseSingleMarkers(corners, 5, K, noArray(), rvecs, tvecs);
+    estimatePoseSingleMarkers(corners, 5, K, noArray(), rvecs, tvecs);
     win->setCameraPose(tvecs.at(0), rvecs.at(0), true);
   }

   return 0;
 }
+
+static void estimatePoseSingleMarkers(InputArrayOfArrays _corners, float markerLength,
+                               InputArray _cameraMatrix, InputArray _distCoeffs,
+                               OutputArray _rvecs, OutputArray _tvecs, OutputArray _objPoints,
+                               Ptr<EstimateParameters> estimateParameters) {
+
+    CV_Assert(markerLength > 0);
+
+    Mat markerObjPoints;
+    _getSingleMarkerObjectPoints(markerLength, markerObjPoints, *estimateParameters);
+    int nMarkers = (int)_corners.total();
+    _rvecs.create(nMarkers, 1, CV_64FC3);
+    _tvecs.create(nMarkers, 1, CV_64FC3);
+
+    Mat rvecs = _rvecs.getMat(), tvecs = _tvecs.getMat();
+
+    //// for each marker, calculate its pose
+    parallel_for_(Range(0, nMarkers), [&](const Range& range) {
+        const int begin = range.start;
+        const int end = range.end;
+
+        for (int i = begin; i < end; i++) {
+            solvePnP(markerObjPoints, _corners.getMat(i), _cameraMatrix, _distCoeffs, rvecs.at<Vec3d>(i),
+                     tvecs.at<Vec3d>(i), estimateParameters->solvePnPMethod);
+        }
+    });
+
+    if(_objPoints.needed()){
+        markerObjPoints.convertTo(_objPoints, -1);
+    }
+}
beew commented 1 year ago

Hi, it works now after removing libogre-xxx.dev.

Thanks.

hansonap commented 2 weeks ago

I ran into this same issue when trying to build from source, 4.8.1. Shouldn't the solution be to update these example programs? I see the issue has been closed but it doesn't reference a commit fix.

Kumataro commented 2 weeks ago

Hi, I said following. This workaround is not enough to merge into main trunk, I think.

Following is considered only to suppress comple errors, it is not good fix.

~Please could you create new pull request to fix it if you need ?~

I re-consider ant it is better to skip building this sample program.