1+ /*
2+ * FasterRCNN_SE.h
3+ * FasterRCNN_SpringEdition
4+ *
5+ * Created by kimbom on 2017. 10. 2...
6+ * Copyright 2017 Sogang Univ. All rights reserved.
7+ *
8+ */
9+ #if !defined(FASTERRCNN_SE_7E1_A_2_FASTERRCNN_SE_HPP_INCLUDED)
10+ #define FASTERRCNN_SE_7E1_A_2_FASTERRCNN_SE_HPP_INCLUDED
11+ #include < iostream>
12+ #include < vector>
13+ #include < string>
14+ #include < sstream>
15+ #include < Windows.h>
16+ #include < opencv2/opencv.hpp>
17+ #ifndef SPRING_EDITION_BOX
18+ #define SPRING_EDITION_BOX
19+ /* *
20+ * @brief 이 클래스는 cv::Rect를 확장한 것으로 클래스값과 스코어값이 추가되었습니다.
21+ * @author kimbomm
22+ * @date 2017-10-05
23+ *
24+ * @see https://github.com/springkim/FasterRCNN_SpringEdition
25+ * @see https://github.com/springkim/YOLOv2_SpringEdition
26+ */
27+ class BoxSE : public cv ::Rect {
28+ public:
29+ int m_class = -1 ;
30+ float m_score = 0 .0F ;
31+ std::string m_class_name;
32+ BoxSE () {
33+ m_class_name = " Unknown" ;
34+ }
35+ BoxSE (int c, float s, int _x, int _y, int _w, int _h, std::string name = " " )
36+ :m_class(c), m_score(s) {
37+ this ->x = _x;
38+ this ->y = _y;
39+ this ->width = _w;
40+ this ->height = _h;
41+ char * lb[5 ] = { " th" ," st" ," nd" ," rd" ," th" };
42+ if (name.length () == 0 ) {
43+ m_class_name = std::to_string (m_class) + lb[m_class < 4 ? m_class : 4 ] + " class" ;
44+ }
45+ }
46+ };
47+ #endif
48+ class FasterRCNN {
49+ public:
50+ static const int AlexNet = 0 ;
51+ static const int VGG16 = 1 ;
52+ static const int VGG19 = 2 ;
53+ private:
54+ int m_base_model;
55+ std::string m_key_mutex = " " ;
56+ HANDLE m_mutex = INVALID_HANDLE_VALUE;
57+ std::string m_key_shmem = " " ;
58+ HANDLE m_shmem = INVALID_HANDLE_VALUE;
59+ DWORD m_size = 0 ;
60+ char * m_buffer = nullptr ;
61+ // 0(48) = load model
62+ // 1(49) = send image path
63+ // 2(50) = detect
64+ // 3(51) = receive
65+ // 9(57) = terminate signal
66+ std::vector<std::string> m_class_map;
67+ public:
68+ void Create (int base_model, std::string model_path,std::string classfile,DWORD size=10000 ,float filter_threshold=0 .4F ) {
69+ m_base_model = base_model;
70+ m_key_shmem = this ->GetKey () + " _shmem" ;
71+ m_key_mutex = this ->GetKey () + " _mutex" ;
72+ m_size = size;
73+
74+ m_mutex = ::CreateMutexA (nullptr , FALSE , m_key_mutex.c_str ());
75+ m_shmem = ::CreateFileMappingA (INVALID_HANDLE_VALUE, nullptr ,PAGE_READWRITE, 0 , m_size, m_key_shmem.c_str ());
76+ m_buffer = (char *)::MapViewOfFile (m_shmem, FILE_MAP_ALL_ACCESS, 0 , 0 , m_size);
77+ m_buffer[0 ] = 0 ;
78+ // std::string exec = "python35 \"C:/Users/sprin/Downloads/FasterRCNN_SpringEdition_final/FasterRCNN_SE_Train/src/FasterRCNN_Detect_SE.py\"";
79+ std::string exec = " FasterRCNN_Detect_SE.exe" ;
80+ HWND hwnd = GetForegroundWindow ();
81+ std::vector<std::string> models = { " AlexNet" ," VGG16" ," VGG19" };
82+ std::ostringstream oss;
83+ // oss << exec << " " << m_key_shmem << " " << m_key_mutex << " " << m_size << " " << "\"" << model_path << "\"" << "\t" << filter_threshold << " " << hwnd << " " << models[m_base_model];
84+ // UINT ret=WinExec(oss.str().c_str(), SW_HIDE);
85+ oss << m_key_shmem << " " << m_key_mutex << " " << m_size << " " << " \" " << model_path << " \" " << " \t " << filter_threshold << " " << hwnd << " " << models[m_base_model];
86+ HINSTANCE ret=ShellExecuteA (NULL , " open" , exec.c_str (), oss.str ().c_str (), NULL , SW_HIDE);
87+ if ((size_t )ret < 31 ) {
88+ ::MessageBoxA (nullptr , " FasterRCNN Detector execute failed\n It needs \" FasterRCNN_Detect_SE.exe\" ." , " Error" , MB_OK);
89+ exit (1 );
90+ }
91+ bool load = false ;
92+ while (load==false ) {
93+ WaitForSingleObject (m_mutex, INFINITE);
94+ if (m_buffer[0 ] == ' 1' ) {
95+ load = true ;
96+ }
97+ ::ReleaseMutex (m_mutex);
98+ }
99+ std::fstream fin;
100+ fin.open (classfile, std::ios::in);
101+ if (fin.is_open () == false ) {
102+ ::MessageBoxA (nullptr , " Can't read class map file" , " Error" , MB_OK);
103+ exit (1 );
104+ }
105+ std::string line;
106+ while (!fin.eof ()) {
107+ std::getline (fin, line);
108+ if (line.length () == 0 ) {
109+ break ;
110+ }
111+ std::istringstream iss (line);
112+ std::string _class;
113+ iss >> _class;
114+ m_class_map.push_back (_class);
115+ }
116+ fin.close ();
117+ }
118+ void Release () {
119+ bool pass = false ;
120+ while (pass == false ) {
121+ WaitForSingleObject (m_mutex, INFINITE);
122+ if (m_buffer[0 ] == ' 1' ) {
123+ m_buffer[0 ] = ' 9' ;
124+ pass = true ;
125+ }
126+ ::ReleaseMutex (m_mutex);
127+ }
128+ ::UnmapViewOfFile (m_buffer);
129+ ::CloseHandle (m_shmem);
130+ ::ReleaseMutex (m_mutex);
131+ m_shmem = INVALID_HANDLE_VALUE;
132+ m_mutex = INVALID_HANDLE_VALUE;
133+ }
134+ ~FasterRCNN () {
135+ if (m_shmem != INVALID_HANDLE_VALUE) {
136+ this ->Release ();
137+ }
138+ }
139+ std::vector<BoxSE> Detect (std::string img_path, float threshold) {
140+ ::ReleaseMutex (m_mutex);
141+ bool pass = false ;
142+ while (pass == false ) {
143+ WaitForSingleObject (m_mutex, INFINITE);
144+ if (m_buffer[0 ] == ' 1' ) {
145+ memset (m_buffer + 1 , 0 ,m_size - 1 );
146+ char * p = m_buffer + 1 ;
147+ const char * q = img_path.data ();
148+ while (*q != ' \0 ' ) {
149+ *p++ = *q++;
150+ }
151+ *p = ' \0 ' ;
152+ // strcpy(m_buffer + 1, img_path.c_str()); //strcpy is not working on SDL.
153+ // strcpy_s(m_buffer + 1, m_size-1,img_path.c_str()); //strcpy_s is not working on debug mode.
154+ m_buffer[0 ] = ' 2' ; // running
155+ pass = true ;
156+ }
157+ ::ReleaseMutex (m_mutex);
158+ }
159+ std::string receive;
160+ bool finish = false ;
161+ while (finish == false ) {
162+ WaitForSingleObject (m_mutex, INFINITE);
163+ if (m_buffer[0 ] == ' 3' ) {
164+ receive = m_buffer + 1 ;
165+ m_buffer[0 ] = ' 1' ; // restore
166+ finish = true ;
167+ }
168+ ::ReleaseMutex (m_mutex);
169+ }
170+ std::string token = " ;" ;
171+ std::string::size_type offset = 0 ;
172+ std::vector<int > result;
173+ while (offset<receive.length ()) {
174+ std::string str = receive.substr (offset, receive.find (token, offset) - offset);
175+ result.push_back (atoi (str.c_str ()));
176+ offset += str.length () + 1 ;
177+ }
178+ std::vector<BoxSE> boxes;
179+ for (int i = 0 ; i < result[0 ]; i++) {
180+ BoxSE box;
181+ box.m_class = result[i * 6 + 1 ];
182+ box.m_class_name = m_class_map[box.m_class ];
183+ box.m_score = result[i * 6 + 2 ] / 10000 .0F ;
184+ box.x = result[i * 6 + 3 ];
185+ box.y = result[i * 6 + 4 ];
186+ box.width = result[i * 6 + 5 ] - box.x ;
187+ box.height = result[i * 6 + 6 ] - box.y ;
188+ if (box.m_score >= threshold) {
189+ boxes.push_back (box);
190+ }
191+ }
192+ auto IOU = [](BoxSE& a, BoxSE& b)->float {
193+ float i = static_cast <float >((a & b).area ());
194+ float u = a.area () + b.area () - i;
195+ return i / u;
196+ };
197+ // Sort by Greater
198+ std::sort (boxes.begin (), boxes.end (), [](BoxSE& a, BoxSE& b)->bool {return a.m_score > b.m_score ; });
199+ std::vector<bool > select (boxes.size (), true );
200+ std::vector<BoxSE> boxes2;
201+ for (int i = 0 ; i < boxes.size (); i++) {
202+ if (select[i] == true ) {
203+ for (int j = i + 1 ; j < boxes.size (); j++) {
204+ if (select[j] == true ) {
205+ if (IOU (boxes[i], boxes[j]) > 0.4 ) {
206+ select[j] = false ;
207+ }
208+ }
209+ }
210+ boxes2.push_back (boxes[i]);
211+ }
212+ }
213+ WaitForSingleObject (m_mutex, INFINITE);
214+ return boxes2;
215+ }
216+ std::string GetObjectName (int idx) {
217+ return m_class_map[idx];
218+ }
219+ private:
220+ std::string GetKey () {
221+ // https://stackoverflow.com/questions/10654258/get-millisecond-part-of-time
222+ SYSTEMTIME stime;
223+ FILETIME ftime;
224+ FILETIME ftime_stamp;
225+ GetSystemTimeAsFileTime (&ftime_stamp);
226+ FileTimeToLocalFileTime (&ftime_stamp, &ftime);
227+ FileTimeToSystemTime (&ftime, &stime);
228+ char buf[256 ];
229+ sprintf_s (buf, " %d%d%d%d%d%d%d" , stime.wYear , stime.wMonth , stime.wDay , stime.wHour , stime.wMinute , stime.wSecond , stime.wMilliseconds );
230+ return buf;
231+ }
232+ };
233+ #endif // FASTERRCNN_SE_7E1_A_2_FASTERRCNN_SE_HPP_INCLUDED
0 commit comments