Fix nan issue in features
[trackerpp.git] / src / Engine.cpp
1 #include <mutex>
2 #include <thread>
3 #include <condition_variable>
4 #include "Engine.h"
5 #include "Logger.h"
6 #include "PredictorWrapper.h"
7
8 using namespace suanzi;
9 using namespace std;
10
11 static const std::string TAG = "Engine";
12 static std::mutex g_mutex;
13 static EngineWPtr g_instance;
14
15 typedef std::shared_ptr<std::vector<Person>> PersonsInfoPtr;
16
17 EnginePtr Engine::create()
18 {
19     LOG_DEBUG(TAG, "create");
20     std::lock_guard<std::mutex> lock(g_mutex);
21     if (g_instance.lock()){
22         LOG_ERROR(TAG, "already exists");
23         return EnginePtr();
24     }
25     EnginePtr instance (new Engine());
26     g_instance = instance;
27     return instance;
28 }
29
30 Engine::Engine()
31 {
32     detector = DetectorPtr(new Detector());
33 }
34
35 Engine::~Engine()
36 {    
37     destroy();
38 }
39
40 void Engine::destroy()
41 {
42     LOG_DEBUG(TAG, "destroy");
43     detector.reset();
44     multiTracker.reset();
45     reader.reset();
46     observer_list.clear();
47 }
48
49 void Engine::setVideoSrc(VideoSrcType type, const std::string& url)
50 {
51     reader = VideoReaderFactory::createVideoReader(type, url);
52 }
53
54 void Engine::run()
55 {
56     LOG_DEBUG(TAG, "run");
57     cv::Mat frame;
58     Detection detections[128];
59     while (reader->read(frame)){
60         LOG_DEBUG(TAG, "Size: " << frame.cols  <<  "x" << frame.rows);
61         int total = detector->detect(frame, detections);
62         multiTracker->update(total, detections, frame);
63     }
64 }
65
66 void Engine::start()
67 {
68     LOG_DEBUG(TAG, "start");
69     multiTracker = std::make_shared<MultiTracker>(g_instance);
70     if (!reader){
71         LOG_ERROR(TAG, "reader is null. exit");
72         return;
73     }
74     std::thread t(&Engine::run, this);
75     t.join();
76 }
77
78 void Engine::addObserver(EngineObserver *observer)
79 {
80     LOG_DEBUG(TAG, "addObserver");
81     observer_list.insert(observer);
82 }
83
84
85 // WorkItem class for event thread
86 class PersonInEventWorkItem : public WorkItem
87 {
88 public:
89     PersonInEventWorkItem(std::set<EngineObserver*> obs, PersonsInfoPtr info) : obs(obs), info(info){
90     }
91     ~PersonInEventWorkItem(){}
92     void run (){
93         for (auto o : obs){
94             o->onPersonsIn(*(info.get()));
95         }
96     }
97 private:
98     std::set<EngineObserver*> obs;
99     PersonsInfoPtr info;
100 };
101
102 class PersonOutEventWorkItem : public WorkItem
103 {
104 public:
105     PersonOutEventWorkItem(std::set<EngineObserver*> obs, PersonsInfoPtr info) : obs(obs), info(info){
106     }
107     ~PersonOutEventWorkItem(){}
108     void run (){
109         for (auto o : obs){
110             o->onPersonsIn(*(info.get()));
111         }
112     }
113 private:
114     std::set<EngineObserver*> obs;
115     PersonsInfoPtr info;
116 };
117
118 void Engine::onPersonsOut(const std::vector<Person>& p)
119 {
120     LOG_DEBUG(TAG, "onPersonOut");
121     PersonsInfoPtr pp = std::make_shared<std::vector<Person>>(p);
122     eventThread.enqueue(new PersonOutEventWorkItem(this->observer_list, pp));
123 }
124
125 void Engine::onPersonsIn(const std::vector<Person>& p)
126 {
127     LOG_DEBUG(TAG, "onPersonIn");
128     PersonsInfoPtr pp = std::make_shared<std::vector<Person>>(p);
129     eventThread.enqueue(new PersonInEventWorkItem(this->observer_list, pp));
130 }