mexopencv  3.4.1
MEX interface for OpenCV library
DetectionBasedTracker_.cpp
Go to the documentation of this file.
1 
8 #include "mexopencv.hpp"
9 #include "opencv2/objdetect.hpp"
10 using namespace std;
11 using namespace cv;
12 
13 //HACK: detection_based_tracker.cpp requires C++11 threads or Unix pthreads
14 // to compile. On Windows, it means we need >= VS2013 (VS2010 doesnt work).
15 //HACK: I'm excluding MinGW since not all builds have std::thread support,
16 // plus the detection code in opencv doesn't handle MinGW correctly.
17 #if defined(__linux__) || defined(__APPLE__) || \
18  (defined(CV_CXX11) && !defined(__MINGW32__))
19 
20 namespace {
21 // Persistent objects
23 int last_id = 0;
26 
28 const ConstMap<int,string> ObjectStatusInvMap = ConstMap<int,string>
29  (cv::DetectionBasedTracker::DETECTED_NOT_SHOWN_YET, "DetectedNotShownYet")
30  (cv::DetectionBasedTracker::DETECTED, "Detected")
31  (cv::DetectionBasedTracker::DETECTED_TEMPORARY_LOST, "DetectedTemporaryLost")
32  (cv::DetectionBasedTracker::WRONG_OBJECT, "WrongObject");
33 
39 DetectionBasedTracker::Parameters createParameters(
42 {
43  ptrdiff_t len = std::distance(first, last);
44  nargchk((len%2)==0);
45  DetectionBasedTracker::Parameters params;
46  for (; first != last; first += 2) {
47  string key(first->toString());
48  const MxArray& val = *(first + 1);
49  if (key == "MaxTrackLifetime")
50  params.maxTrackLifetime = val.toInt();
51  else if (key == "MinDetectionPeriod")
52  params.minDetectionPeriod = val.toInt();
53  else
54  mexErrMsgIdAndTxt("mexopencv:error",
55  "Unrecognized option %s", key.c_str());
56  }
57  return params;
58 }
59 
64 MxArray toStruct(const DetectionBasedTracker::Parameters &params)
65 {
66  const char *fields[] = {"maxTrackLifetime", "minDetectionPeriod"};
67  MxArray s = MxArray::Struct(fields, 2);
68  s.set("maxTrackLifetime", params.maxTrackLifetime);
69  s.set("minDetectionPeriod", params.minDetectionPeriod);
70  return s;
71 }
72 
78 {
79  const char *fields[] = {"id", "location", "status"};
80  MxArray s = MxArray::Struct(fields, 3, 1, objects.size());
81  for (mwIndex i = 0; i < objects.size(); ++i) {
82  s.set("id", objects[i].id, i);
83  s.set("location", objects[i].location, i);
84  s.set("status", ObjectStatusInvMap[objects[i].status], i);
85  }
86  return s;
87 }
88 
90 class CascadeDetectorAdapter : public DetectionBasedTracker::IDetector
91 {
92 public:
96  CascadeDetectorAdapter(Ptr<CascadeClassifier> p)
97  : IDetector(), detector(p)
98  {
99  CV_Assert(!p.empty());
100  }
101 
106  void detect(const Mat& image, vector<Rect>& objects)
107  {
108  detector->detectMultiScale(image, objects,
109  scaleFactor, minNeighbours, 0, minObjSize, maxObjSize);
110  }
111 
118  static Ptr<CascadeDetectorAdapter> create(string cascadeFile,
121  {
122  ptrdiff_t len = std::distance(first, last);
123  nargchk((len%2)==0);
124  Ptr<CascadeClassifier> detector = makePtr<CascadeClassifier>();
125  if (detector.empty() || !detector->load(cascadeFile))
126  mexErrMsgIdAndTxt("mexopencv:error",
127  "Failed to create CascadeClassifier");
128  Ptr<CascadeDetectorAdapter> p = makePtr<CascadeDetectorAdapter>(detector);
129  if (p.empty())
130  mexErrMsgIdAndTxt("mexopencv:error",
131  "Failed to create CascadeDetectorAdapter");
132  for (; first != last; first += 2) {
133  string key(first->toString());
134  const MxArray& val = *(first + 1);
135  if (key == "ScaleFactor")
136  p->setScaleFactor(val.toFloat());
137  else if (key == "MinNeighbors")
138  p->setMinNeighbours(val.toInt());
139  else if (key == "MinSize")
140  p->setMinObjectSize(val.toSize());
141  else if (key == "MaxSize")
142  p->setMaxObjectSize(val.toSize());
143  else
144  mexErrMsgIdAndTxt("mexopencv:error",
145  "Unrecognized option %s", key.c_str());
146  }
147  return p;
148  }
149 
150 private:
151  Ptr<CascadeClassifier> detector;
152 };
153 }
154 
162 void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
163 {
164  // Check the number of arguments
165  nargchk(nrhs>=2 && nlhs<=1);
166 
167  // Argument vector
168  vector<MxArray> rhs(prhs, prhs+nrhs);
169  int id = rhs[0].toInt();
170  string method(rhs[1].toString());
171 
172  // Constructor call
173  if (method == "new") {
174  nargchk(nrhs>=4 && (nrhs%2)==0 && nlhs<=1);
176  {
177  vector<MxArray> args(rhs[2].toVector<MxArray>());
178  nargchk(args.size() >= 1);
179  mainDetector = CascadeDetectorAdapter::create(
180  args[0].toString(), args.begin() + 1, args.end());
181  }
182  Ptr<DetectionBasedTracker::IDetector> trackingDetector;
183  {
184  vector<MxArray> args(rhs[3].toVector<MxArray>());
185  nargchk(args.size() >= 1);
186  trackingDetector = CascadeDetectorAdapter::create(
187  args[0].toString(), args.begin() + 1, args.end());
188  }
189  //TODO: mainDetector may be empty ?
190  if (mainDetector.empty() || trackingDetector.empty())
191  mexErrMsgIdAndTxt("mexopencv:error", "Failed to create IDetector");
192  DetectionBasedTracker::Parameters params = createParameters(
193  rhs.begin() + 4, rhs.end());
194  obj_[++last_id] = makePtr<DetectionBasedTracker>(
195  mainDetector, trackingDetector, params);
196  plhs[0] = MxArray(last_id);
197  mexLock();
198  return;
199  }
200 
201  // Big operation switch
203  if (obj.empty())
204  mexErrMsgIdAndTxt("mexopencv:error", "Object not found id=%d", id);
205  if (method == "delete") {
206  nargchk(nrhs==2 && nlhs==0);
207  obj_.erase(id);
208  mexUnlock();
209  }
210  else if (method == "run") {
211  nargchk(nrhs==2 && nlhs<=1);
212  bool success = obj->run();
213  plhs[0] = MxArray(success);
214  }
215  else if (method == "stop") {
216  nargchk(nrhs==2 && nlhs==0);
217  obj->stop();
218  }
219  else if (method == "resetTracking") {
220  nargchk(nrhs==2 && nlhs==0);
221  obj->resetTracking();
222  }
223  else if (method == "getParameters") {
224  nargchk(nrhs==2 && nlhs<=1);
225  plhs[0] = toStruct(obj->getParameters());
226  }
227  else if (method == "setParameters") {
228  nargchk(nrhs>=2 && nlhs<=1);
229  bool success = obj->setParameters(createParameters(
230  rhs.begin() + 2, rhs.end()));
231  plhs[0] = MxArray(success);
232  }
233  else if (method == "process") {
234  nargchk(nrhs==3 && nlhs==0);
235  Mat imageGray(rhs[2].toMat(CV_8U));
236  obj->process(imageGray);
237  }
238  else if (method == "getObjects") {
239  nargchk(nrhs==2 && nlhs<=2);
240  if (nlhs > 1) {
242  obj->getObjects(result); // rectangle + id
243  // separate std::pair<cv::Rect, int>
244  vector<Rect> locations;
245  vector<int> ids;
246  locations.reserve(result.size());
247  ids.reserve(result.size());
248  for (vector<DetectionBasedTracker::Object>::const_iterator it = result.begin(); it != result.end(); ++it) {
249  locations.push_back(it->first);
250  ids.push_back(it->second);
251  }
252  plhs[0] = MxArray(locations);
253  plhs[1] = MxArray(ids);
254  }
255  else {
256  vector<Rect> result;
257  obj->getObjects(result); // rectangle
258  plhs[0] = MxArray(result);
259  }
260  }
261  else if (method == "getObjectsExtended") {
262  nargchk(nrhs==2 && nlhs<=1);
264  obj->getObjects(result); // rectangle + id + status
265  plhs[0] = toStruct(result);
266  }
267  else if (method == "addObject") {
268  nargchk(nrhs==3 && nlhs<=1);
269  Rect location(rhs[2].toRect());
270  int id = obj->addObject(location);
271  plhs[0] = MxArray(id);
272  }
273  else
274  mexErrMsgIdAndTxt("mexopencv:error",
275  "Unrecognized method %s", method.c_str());
276 }
277 
278 #else
279 
280 void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
281 {
282  mexErrMsgIdAndTxt("mexopencv:error",
283  "DetectionBasedTracker is not supported");
284 }
285 
286 #endif
int toInt() const
Convert MxArray to int.
Definition: MxArray.cpp:489
#define CV_Assert(...)
T distance(T... args)
LIBMWMEX_API_EXTERN_C void mexLock(void)
Lock a MEX-function so that it cannot be cleared from memory.
STL namespace.
T end(T... args)
bool load(const String &filename)
struct mxArray_tag mxArray
Forward declaration for mxArray.
Definition: matrix.h:259
void set(mwIndex index, const T &value)
Template for numeric array element write accessor.
Definition: MxArray.hpp:1310
STL class.
MxArray toStruct(const std::vector< cv::ml::DTrees::Node > &nodes)
Convert tree nodes to struct array.
T push_back(T... args)
LIBMWMEX_API_EXTERN_C void mexErrMsgIdAndTxt(const char *identifier, const char *err_msg,...)
Issue formatted error message with corresponding error identifier and return to MATLAB prompt...
LIBMWMEX_API_EXTERN_C void mexUnlock(void)
Unlock a locked MEX-function so that it can be cleared from memory.
mxArray object wrapper for data conversion and manipulation.
Definition: MxArray.hpp:123
void nargchk(bool cond)
Alias for input/output arguments number check.
Definition: mexopencv.hpp:181
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexFunction is the user-defined C routine that is called upon invocation of a MEX-function.
static MxArray Struct(const char **fields=NULL, int nfields=0, mwSize m=1, mwSize n=1)
Create a new struct array.
Definition: MxArray.hpp:312
T size(T... args)
STL class.
bool empty() const
Global constant definitions.
T begin(T... args)
std::map wrapper with one-line initialization and lookup method.
Definition: MxArray.hpp:927
map< int, Ptr< AgastFeatureDetector > > obj_
Object container.
void create(int arows, int acols, int atype, Target target=ARRAY_BUFFER, bool autoRelease=false)
cv::Mat toMat() const
T reserve(T... args)