[OpenCV.js] Build tracking module in opencv_contrib but encounter generate error

Hi I tried to build tracking module in opencv.js but failed
I got error :

make -f 3rdparty/protobuf/CMakeFiles/libprotobuf.dir/build.make 3rdparty/protobuf/CMakeFiles/libprotobuf.dir/build
Generator warning: enum cv.detail.CvFeatureParams.FeatureType (cname=cv::detail::CvFeatureParams::FeatureType) already exists
Generator error: constant CvFeatureParams_HAAR (cname=cv::detail::CvFeatureParams::HAAR) already exists
make[3]: *** [modules/js_bindings_generator/CMakeFiles/gen_opencv_js_source.dir/build.make:145: modules/js_bindings_generator/gen/bindings.cpp] Error 255
make[3]: Leaving directory ‘/src/build_js’
make[2]: *** [CMakeFiles/Makefile2:3268: modules/js_bindings_generator/CMakeFiles/gen_opencv_js_source.dir/all] Error 2
make[2]: *** Waiting for unfinished jobs…
make[3]: Entering directory ‘/src/build_js’
make[3]: Nothing to be done for ‘3rdparty/protobuf/CMakeFiles/libprotobuf.dir/build’.
make[3]: Leaving directory ‘/src/build_js’
[ 18%] Built target libprotobuf
make[2]: Leaving directory ‘/src/build_js’
make[1]: *** [CMakeFiles/Makefile2:3455: modules/js/CMakeFiles/opencv.js.dir/rule] Error 2
make[1]: Leaving directory ‘/src/build_js’
make: *** [Makefile:548: opencv.js] Error 2
Traceback (most recent call last):
File “./platforms/js/build_js.py”, line 321, in
builder.build_opencvjs()
File “./platforms/js/build_js.py”, line 229, in build_opencvjs
execute([“make”, “-j”, str(multiprocessing.cpu_count()), “opencv.js”])
File “./platforms/js/build_js.py”, line 23, in execute
raise Fail(“Child returned: %s” % retcode)
main.Fail: Child returned: 2

[Environment Information]
OS: Windows10
openCV: 4.5.1
openCV_contrb : 4.5.1

[Modification]

  1. opencv/modules/js/generator/embindgen.py

    tracking = {“Tracker”: [“init”, “update”], “TrackerKCF”: [“create”], “TrackerBoosting”: [“create”], “TrackerMIL”: [“create”], “TrackerTLD”: [“create”], “TrackerMedianFlow”: [“create”], “TrackerMOSSE”: [“create”], “TrackerCSRT”: [“create”]}

  2. opencv/modules/js/generator/embindgen.py

    white_list = makeWhiteList([tracking])

  3. opencv/platforms/js/build_js.py

    cmd = [“cmake”,
    “-DOPENCV_EXTRA_MODULES_PATH=/opencv_contrib/modules”,

  4. opencv/modules/js/src/core_bindings.cpp

    using namespace tracking;

  5. opencv_contrib/modules/tracking/CMakeLists - Append “js” in ocv_define_module

    ocv_define_module(tracking opencv_imgproc opencv_core opencv_video opencv_plot${debug_modules} OPTIONAL opencv_dnn opencv_datasets opencv_highgui WRAP java python objc js)

[Command]

cd opencv docker run --rm --workdir /src -v “$(get-location):/src” -v “my/peth/to/opencv_contrib:/contrib” “emscripten/emsdk:2.0.10” emcmake python3 ./platforms/js/build_js.py build_js

Hi,

I also ran into this issue. My guess is that both modules/video and contrib/modules/tracking have CvFeatureParams class. But I don’t know how to fix it such that one of them re-uses the other.

Any thoughts?

I managed to overcome this issue with a temporary workaround.

The main issue was because the binding generator tries to load constants and enums from all the modules and CvFeatureParams, CvFeatureEvaluator etc are few of the modules present in both video and tracking modules, causing conflicts.

So, I did the following:

In OpenCV main repo, I edited embindgen.py in modules/js/generator (opencv repo) to make sure that I ignore the error when trying to add a constant that already exists and explicitly namespace the references to the repeated modules.

My diff:

diff --git a/modules/js/generator/embindgen.py b/modules/js/generator/embindgen.py
index a11309a551..0f2d645285 100644
--- a/modules/js/generator/embindgen.py
+++ b/modules/js/generator/embindgen.py
@@ -367,6 +367,13 @@ class JSWrapperGenerator(object):
 
     def add_const(self, name, decl):
         cname = name.replace('.','::')
+
+        # FIXME: Hack to ignore the ambiguous cv::detail::CvFeatureParams
+        # as it appears in both video and contrib/tracking modules.
+        # Since we are not using it, forcing it one of the classes.
+        if cname.startswith('cv::detail::CvFeatureParams'):
+            cname = cname.replace('detail::', 'detail::feature::')
+
         namespace, classes, name = self.split_decl_name(name)
         namespace = '.'.join(namespace)
         name = '_'.join(classes+[name])
@@ -374,8 +381,12 @@ class JSWrapperGenerator(object):
         if name in ns.consts:
             print("Generator error: constant %s (cname=%s) already exists" \
                 % (name, cname))
-            sys.exit(-1)
-        ns.consts[name] = cname
+
+            # FIXME: Hack to know where conflicts occur and prevent crashing of script
+            print(name, cname, classes, namespace, ns.consts)
+            #sys.exit(-1)
+        else:
+            ns.consts[name] = cname
 
     def add_func(self, decl):
         namespace, classes, barename = self.split_decl_name(decl[0])

In OpenCV contrib repo, I added js to WRAP in CMakeLists.txt and explicitly called the respective CvFeatureEvaluator of the contrib_feature namespace

--- a/modules/tracking/CMakeLists.txt
+++ b/modules/tracking/CMakeLists.txt
@@ -19,6 +19,7 @@ ocv_define_module(tracking
       java
       python
       objc
+      js
 )
 
 ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-shadow /wd4458)
diff --git a/modules/tracking/include/opencv2/tracking/tracking_internals.hpp b/modules/tracking/include/opencv2/tracking/tracking_internals.hpp
index 92ca54a9..ab5fd804 100644
--- a/modules/tracking/include/opencv2/tracking/tracking_internals.hpp
+++ b/modules/tracking/include/opencv2/tracking/tracking_internals.hpp
@@ -890,12 +890,12 @@ class CV_EXPORTS TrackerContribFeatureHAAR : public TrackerContribFeature
   @param id The position
   @param feature The feature
  */
-  bool swapFeature( int id, CvHaarEvaluator::FeatureHaar& feature );
+  bool swapFeature( int id, cv::detail::contrib_feature::CvHaarEvaluator::FeatureHaar& feature );
 
   /** @brief Get the feature in position id
     @param id The position
      */
-  CvHaarEvaluator::FeatureHaar& getFeatureAt( int id );
+  cv::detail::contrib_feature::CvHaarEvaluator::FeatureHaar& getFeatureAt( int id );
 
  protected:
   bool computeImpl( const std::vector<Mat>& images, Mat& response ) CV_OVERRIDE;
@@ -903,7 +903,7 @@ class CV_EXPORTS TrackerContribFeatureHAAR : public TrackerContribFeature
  private:
 
   Params params;
-  Ptr<CvHaarEvaluator> featureEvaluator;
+  Ptr<cv::detail::contrib_feature::CvHaarEvaluator> featureEvaluator;
 };
 
 /**

And I compiled the opencv.js with the following command:

# Following instructions from https://docs.opencv.org/3.4/d4/da1/tutorial_js_setup.html

emcmake python3 ./platforms/js/build_js.py build_wasm \
    --build_wasm \
    --cmake_option="-DOPENCV_EXTRA_MODULES_PATH=/code/opencv/contrib/modules" \
    --cmake_option="-DBUILD_LIST=core,imgproc,video,tracking,js"

The next step would be to add the bindings for the init, update, create methods for Tracker, TrackerKCF etc.

Hi so i want to include UnscentedKalmanFilter also in the build. I have no idea how to proceed can you make some suggestions please.

Hello! As I understand, some of the trackers were moved to “legacy”. I am not familiar with OpenCV.js that much, but I think that can be an issue for building from source.
You can track changes in tracking API and discussions about the tracking module here: OE-21 Tracking API · Issue #18481 · opencv/opencv · GitHub.

Thanks for the reply ieliz. I am not sure but there is no mention of Unscented kalman filter anywhere in the link you provided. All i want is to be able to include https://docs.opencv.org/4.5.1/d7/dd9/classcv_1_1detail_1_1tracking_1_1kalman__filters_1_1UnscentedKalmanFilter.html in my opencv js build. If anyone can help me with the classes and corresponding methods to be whitelisted in the opencv_js.config.py file and any other necessary changes that would be great.
Thanks

My answer is related to the original question of this post about building tracking module, sorry for the misunderstanding :slight_smile:

I didn’t go all the way to enable all tracking modules by modifying opencv_js_config.py.

But instead, I wrote a c++ program to expose the same interface required for a tracking module - Accept a typedarray from js, convert it to Mat, process it, and send back cv::Rect back to js. I achieved this using embind.

I followed the following tutorials for embind

  1. From MDN - Compiling an Existing C Module to WebAssembly
  2. Blog by Sean Voisen - section Getting tricky with embind - Rendering images with Emscripten, WASM and OpenGL

Hope this helps.

So, will the correct solution be to port the required functionality back into video module under the new API?

As I said previously, I am not good with OpenCV.js :frowning:
But I know for sure, that some trackers are not moved to “video” because of their low competitiveness in comparison with new trackers.
The best option, in my opinion, is to create an issue on OpenCV GitHub and ask about it, because the rework of the module still in progress.
Also, you can use the previous version of OpenCV - before tracking API rework (kinda workaround :man_shrugging: ).

1 Like