Ask Your Question
0

How to create map with pointer to function to cv tracking ?

asked 2020-02-05 05:06:30 -0600

Bensuperpc gravatar image

updated 2020-02-05 08:55:27 -0600

Good morning, I would like to create map with pointer function with tracking functions, i tried many solution but aren't working :/

I would like to avoid many if like :

cv::Ptr<cv::Tracker>
TestTrackingVideo::createTrackerByName(std::string &trackerType) {
  cv::Ptr<cv::Tracker> tracker;
  if (trackerType == trackerTypes[0])
    tracker = cv::TrackerBoosting::create();
  else if (trackerType == trackerTypes[1])
    tracker = cv::TrackerMIL::create();
  else if (trackerType == trackerTypes[2])
    tracker = cv::TrackerKCF::create();
  else if (trackerType == trackerTypes[3])
    tracker = cv::TrackerTLD::create();
  else if (trackerType == trackerTypes[4])
    tracker = cv::TrackerMedianFlow::create();
  else if (trackerType == trackerTypes[5])
    tracker = cv::TrackerGOTURN::create();
  else if (trackerType == trackerTypes[6])
    tracker = cv::TrackerMOSSE::create();
  else if (trackerType == trackerTypes[7])
    tracker = cv::TrackerCSRT::create();
  else {
    std::cout << "Incorrect tracker name" << std::endl;
    std::cout << "Available trackers are: " << std::endl;
    for (std::vector<std::string>::iterator it = trackerTypes.begin();
         it != trackerTypes.end(); ++it)
      std::cout << " " << *it << std::endl;
  }
  return tracker;
}

I would like to create map with pointer to function like :

  std::map<std::string, cv::Ptr<cv::Tracker> (*)()> trackerTypes_map =
      {{"BOOSTINGS", &cv::TrackerBoosting::create},
       {"MIL", &cv::TrackerMIL::create}};

And call it :

cv::Ptr<cv::Tracker>
createTrackerByName(std::string &trackerType) {
   auto &iter = this->trackerTypes_map.find(trackerType);
   if (iter == this->trackerTypes_map.end()) {
      throw "tracker type not found !";
   }
   return (this->trackerTypes_map.second)();
}

When i tried to compile, i have this error :

error : could not convert '{{"BOOSTINGS", (& cv::TrackerBoosting::create)}, {"BOOSTING", (& cv::TrackerBoosting::create)}}' from '<brace-enclosed initializer list>' to 'std::map<std::__cxx11::basic_string<char>, cv::Ptr<cv::TrackerBoosting> (*)()>'
                           {"BOOSTING", &cv::TrackerBoosting::create}};
                                                                 ^

I don't know why isn't working, is something missing ? Wrong type ?

edit retag flag offensive close merge delete

Comments

if i may ask - what is the actual use-case of this ? (looks like over-engineering)

and why double Ptr here: cv::Ptr<cv::Ptr<cv::TrackerBoosting> > (*)() ?

&cv::TrackerMOSSE::create is a different type than &cv::TrackerKCF::create, but your map needs a consistent type for second

it won't ever work, i guess ;( xD

berak gravatar imageberak ( 2020-02-05 07:28:14 -0600 )edit
1

My computer school, do not like that we do several if, It is an error when looking for a solution,

I use the "cv::Tracker" template in mat, the other heirs, this one ? it worked with the mother class in template during lessons, I can't understand, maybe we need a special syntax with cv::Ptr?

I changed the original post a bit, when we call the pointer to function.

Bensuperpc gravatar imageBensuperpc ( 2020-02-05 07:51:28 -0600 )edit
1

"My computer school," -- hehe, ok ;)

there are 3 problems:

  • your trackertypes map contains factories/create functions, to create an instance you would need to call it
  • all function pointers in your map need to have the same type / signature
  • there is no cast from a function returning Ptr<cv::TrackerBoosting> to another returning a type like Ptr<cv::Tracker>
berak gravatar imageberak ( 2020-02-05 09:17:33 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
2

answered 2020-02-05 09:07:34 -0600

berak gravatar image

if you can live with the generic cv::Tracker interface for the trackers created, you could generate a factory (wrapper) function, so you can store unique function pointers (of the same signature) in your map later:

// map value type
typedef cv::Ptr<cv::Tracker> (*TrackerFactory)();

// generated function sig
template<class T>
cv::Ptr<cv::Tracker> _wrap(){ return T::create(); }

int main()
{
    std::map<std::string, TrackerFactory> trackerTypes_map;
    trackerTypes_map["BOOSTING"] = _wrap<cv::TrackerBoosting>;
    trackerTypes_map["MIL"]      = _wrap<cv::TrackerMIL>;
    trackerTypes_map["MOSSE"]    = _wrap<cv::TrackerMOSSE>;

    auto test = [&](string s){
        cout << s << "\t\t";
        TrackerFactory factory = trackerTypes_map[s]; // returns nullptr for unknown keys
        cout << factory;
        if (factory) { // mandatory check !
            Ptr<Tracker> p1 = factory();
            cout << " " << (!p1.empty());
        }
        cout << endl;
    };
    test("MOSSE");
    test("MIL");
    test("Boostings");
    test("BOOSTING");
}
edit flag offensive delete link more

Comments

Thank you very much, it works :)

Bensuperpc gravatar imageBensuperpc ( 2020-02-05 09:30:13 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2020-02-05 05:06:30 -0600

Seen: 514 times

Last updated: Feb 05 '20