如何使 OpenCV 跟踪 classes 从基数 class 派生?
How to make OpenCV tracking classes derive from a base class?
OpenCV 跟踪 API 在 3 个不同的地方有实现。
video/tracking.hpp
tracking.hpp
tracking/tracking_legacy.hpp
我希望能够通过提供算法名称作为输入来使用任何实现。
cv::Ptr<cv::Tracker> get_tracker(std::string trackerType);
似乎有效。
if tracker_type == 'CSRT':
tracker = cv2.TrackerCSRT_create()
elif tracker_type == 'MOSSE':
tracker = cv.legacy.TrackerMOSSE_create()
...
ok = tracker.init(frame, bbox)
ok, bbox = tracker.update(frame)
C++ 的问题是 tracker
的类型应该在编译时知道。
有different implementations using templates是函数的解决方案,但是我们返回的是一个对象,所以这个不适用。
正确的解决方案是使用继承从具有纯虚函数 init
和 update
的基 class 派生 cv::Tracker
and cv::legacy::Tracker
。两个 classes 都有这些方法,但它们分别派生自 cv::Algorithm
,cv::Algorithm
没有任何这些功能。
到目前为止,我创建了单独的函数来获取跟踪器对象。
#include <opencv2/tracking.hpp>
#include <opencv2/tracking/tracking_legacy.hpp>
#include <string>
#include <stdexcept>
// https://docs.opencv.org/4.5.2/d0/d0a/classcv_1_1Tracker.html
cv::Ptr<cv::Tracker> get_tracker(std::string trackerType)
{
if (trackerType == "MIL")
return cv::TrackerMIL::create();
if (trackerType == "GOTURN")
return cv::TrackerGOTURN::create();
if (trackerType == "CSRT")
return cv::TrackerCSRT::create();
if (trackerType == "KCF")
return cv::TrackerKCF::create();
throw std::runtime_error("Unknown tracker type.");
}
// https://docs.opencv.org/4.5.2/db/dfe/classcv_1_1legacy_1_1Tracker.html
cv::Ptr<cv::legacy::Tracker> get_legacy_tracker(std::string legacyTrackerType)
{
if (legacyTrackerType == "MIL")
return cv::legacy::TrackerMIL::create();
if (legacyTrackerType == "BOOSTING")
return cv::legacy::TrackerBoosting::create();
if (legacyTrackerType == "MEDIANFLOW")
return cv::legacy::TrackerMedianFlow::create();
if (legacyTrackerType == "TLD")
return cv::legacy::TrackerTLD::create();
if (legacyTrackerType == "KCF")
return cv::legacy::TrackerKCF::create();
if (legacyTrackerType == "MOSSE")
return cv::legacy::TrackerMOSSE::create();
if (legacyTrackerType == "CSRT")
return cv::legacy::TrackerCSRT::create();
throw std::runtime_error("Unknown legacy tracker type.");
}
我将跟踪器类型作为命令行输入。使以下代码适用于所有跟踪器类型的任何解决方案都值得赞赏。 Tracker
在可用时优于 legacy
。
tracker->init(frame, bbox);
bool ok = tracker->update(frame, bbox);
注意:我使用的是 OpenCV 4.5.2。 legacy
模块创建于 this commit。
另一个注意事项: 目前,opencv-python==4.5.2
的 pip 包不可用。提供的Python代码未经测试,是根据文档编写的。
解决办法就在OpenCV的示例脚本中。 (tracking/samples/samples_utility.hpp)
我们需要将 cv::legacy::Tracker
转换为首选类型 cv::Tracker
。就像一个函数的不同输入问题一样,我们需要分别实现这些成员函数。
class LegacyTrackerWrapper : public cv::Tracker
{
const cv::Ptr<cv::legacy::Tracker> legacy_tracker_;
public:
LegacyTrackerWrapper(const cv::Ptr<legacy::Tracker>& legacy_tracker)
: legacy_tracker_(legacy_tracker) {}
~LegacyTrackerWrapper() override {}
void init(cv::InputArray image, const cv::Rect& boundingBox) override
{
legacy_tracker_->init(image, static_cast<cv::Rect2d>(boundingBox));
}
bool update(cv::InputArray image, cv::Rect& boundingBox) override
{
cv::Rect2d boundingBox2d;
bool res = legacy_tracker_->update(image, boundingBox2d);
boundingBox = static_cast<cv::Rect>(boundingBox2d); // the cast is not defined by default
return res;
}
};
我们可以使用包装器 class 来获得所需的行为。
cv::Ptr<cv::Tracker> upgradeTrackingAPI(const cv::Ptr<legacy::Tracker>& legacy_tracker)
{
return cv::makePtr<LegacyTrackerWrapper>(legacy_tracker);
}
cv::Ptr<cv::Tracker> get_tracker(std::string trackerType)
{
if (trackerType == "CSRT")
return cv::TrackerCSRT::create();
if (trackerType == "MOSSE")
return upgradeTrackingAPI(cv::legacy::TrackerMOSSE::create());
}
OpenCV 跟踪 API 在 3 个不同的地方有实现。
video/tracking.hpp
tracking.hpp
tracking/tracking_legacy.hpp
我希望能够通过提供算法名称作为输入来使用任何实现。
cv::Ptr<cv::Tracker> get_tracker(std::string trackerType);
if tracker_type == 'CSRT':
tracker = cv2.TrackerCSRT_create()
elif tracker_type == 'MOSSE':
tracker = cv.legacy.TrackerMOSSE_create()
...
ok = tracker.init(frame, bbox)
ok, bbox = tracker.update(frame)
C++ 的问题是 tracker
的类型应该在编译时知道。
有different implementations using templates是函数的解决方案,但是我们返回的是一个对象,所以这个不适用。
正确的解决方案是使用继承从具有纯虚函数 init
和 update
的基 class 派生 cv::Tracker
and cv::legacy::Tracker
。两个 classes 都有这些方法,但它们分别派生自 cv::Algorithm
,cv::Algorithm
没有任何这些功能。
到目前为止,我创建了单独的函数来获取跟踪器对象。
#include <opencv2/tracking.hpp>
#include <opencv2/tracking/tracking_legacy.hpp>
#include <string>
#include <stdexcept>
// https://docs.opencv.org/4.5.2/d0/d0a/classcv_1_1Tracker.html
cv::Ptr<cv::Tracker> get_tracker(std::string trackerType)
{
if (trackerType == "MIL")
return cv::TrackerMIL::create();
if (trackerType == "GOTURN")
return cv::TrackerGOTURN::create();
if (trackerType == "CSRT")
return cv::TrackerCSRT::create();
if (trackerType == "KCF")
return cv::TrackerKCF::create();
throw std::runtime_error("Unknown tracker type.");
}
// https://docs.opencv.org/4.5.2/db/dfe/classcv_1_1legacy_1_1Tracker.html
cv::Ptr<cv::legacy::Tracker> get_legacy_tracker(std::string legacyTrackerType)
{
if (legacyTrackerType == "MIL")
return cv::legacy::TrackerMIL::create();
if (legacyTrackerType == "BOOSTING")
return cv::legacy::TrackerBoosting::create();
if (legacyTrackerType == "MEDIANFLOW")
return cv::legacy::TrackerMedianFlow::create();
if (legacyTrackerType == "TLD")
return cv::legacy::TrackerTLD::create();
if (legacyTrackerType == "KCF")
return cv::legacy::TrackerKCF::create();
if (legacyTrackerType == "MOSSE")
return cv::legacy::TrackerMOSSE::create();
if (legacyTrackerType == "CSRT")
return cv::legacy::TrackerCSRT::create();
throw std::runtime_error("Unknown legacy tracker type.");
}
我将跟踪器类型作为命令行输入。使以下代码适用于所有跟踪器类型的任何解决方案都值得赞赏。 Tracker
在可用时优于 legacy
。
tracker->init(frame, bbox);
bool ok = tracker->update(frame, bbox);
注意:我使用的是 OpenCV 4.5.2。 legacy
模块创建于 this commit。
另一个注意事项: 目前,opencv-python==4.5.2
的 pip 包不可用。提供的Python代码未经测试,是根据文档编写的。
解决办法就在OpenCV的示例脚本中。 (tracking/samples/samples_utility.hpp)
我们需要将 cv::legacy::Tracker
转换为首选类型 cv::Tracker
。就像一个函数的不同输入问题一样,我们需要分别实现这些成员函数。
class LegacyTrackerWrapper : public cv::Tracker
{
const cv::Ptr<cv::legacy::Tracker> legacy_tracker_;
public:
LegacyTrackerWrapper(const cv::Ptr<legacy::Tracker>& legacy_tracker)
: legacy_tracker_(legacy_tracker) {}
~LegacyTrackerWrapper() override {}
void init(cv::InputArray image, const cv::Rect& boundingBox) override
{
legacy_tracker_->init(image, static_cast<cv::Rect2d>(boundingBox));
}
bool update(cv::InputArray image, cv::Rect& boundingBox) override
{
cv::Rect2d boundingBox2d;
bool res = legacy_tracker_->update(image, boundingBox2d);
boundingBox = static_cast<cv::Rect>(boundingBox2d); // the cast is not defined by default
return res;
}
};
我们可以使用包装器 class 来获得所需的行为。
cv::Ptr<cv::Tracker> upgradeTrackingAPI(const cv::Ptr<legacy::Tracker>& legacy_tracker)
{
return cv::makePtr<LegacyTrackerWrapper>(legacy_tracker);
}
cv::Ptr<cv::Tracker> get_tracker(std::string trackerType)
{
if (trackerType == "CSRT")
return cv::TrackerCSRT::create();
if (trackerType == "MOSSE")
return upgradeTrackingAPI(cv::legacy::TrackerMOSSE::create());
}