@@ -145,6 +145,99 @@ static bool is_number(const std::string &s) {
145
145
return !s.empty () && std::all_of (s.begin (), s.end (), ::isdigit);
146
146
}
147
147
148
+ class CalcMask final {
149
+ protected:
150
+ enum class thread_state { INIT, RUNNING, DONE };
151
+ volatile thread_state state;
152
+ void *maskctx;
153
+ // buffers
154
+ cv::Mat mask1;
155
+ cv::Mat mask2;
156
+ cv::Mat *mask_current;
157
+ cv::Mat *mask_out;
158
+ cv::Mat frame1;
159
+ cv::Mat frame2;
160
+ cv::Mat *frame_current;
161
+ cv::Mat *frame_next;
162
+ // All mutexes need to come before the thread
163
+ std::mutex lock_frame;
164
+ std::mutex lock_mask;
165
+ std::condition_variable condition_new_frame;
166
+ bool new_frame;
167
+ bool new_mask;
168
+
169
+ std::thread thread; // Must be after state and all relevant mutexes, because of initialization order)
170
+
171
+ void run () {
172
+ cv::Mat *raw_tmp;
173
+
174
+ while (thread_state::INIT == this ->state )
175
+ usleep (1000 ); // Wait for constructor to complete initialization
176
+
177
+ while (thread_state::RUNNING == this ->state ) {
178
+ /* actual handling */
179
+ {
180
+ std::unique_lock<std::mutex> hold (lock_frame);
181
+ while (!new_frame) {
182
+ condition_new_frame.wait (hold);
183
+ }
184
+
185
+ // change frame buffer pointer
186
+ new_frame = false ;
187
+ raw_tmp = frame_next;
188
+ frame_next = frame_current;
189
+ frame_current = raw_tmp;
190
+ }
191
+ if (!bs_maskgen_process (maskctx, *frame_current, *mask_current)) {
192
+ fprintf (stderr, " failed to process video frame\n " );
193
+ exit (1 );
194
+ }
195
+ {
196
+ std::unique_lock<std::mutex> hold (lock_mask);
197
+ raw_tmp = mask_out;
198
+ mask_out = mask_current;
199
+ mask_current = raw_tmp;
200
+ new_mask = true ;
201
+ }
202
+ }
203
+ }
204
+
205
+ public:
206
+ CalcMask (void *maskctx) :
207
+ state{thread_state::INIT},
208
+ thread{&CalcMask::run, this } {
209
+ // Do all other initialization …
210
+ this ->maskctx = maskctx;
211
+ frame_next = &frame1;
212
+ frame_current = &frame2;
213
+ mask_current = &mask1;
214
+ mask_out = &mask2;
215
+ new_frame = false ;
216
+ new_mask = false ;
217
+ state = thread_state::RUNNING;
218
+ }
219
+
220
+ ~CalcMask () {
221
+ state = thread_state::DONE;
222
+ thread.join ();
223
+ }
224
+
225
+ void set_input_frame (cv::Mat &frame) {
226
+ std::lock_guard<std::mutex> hold (lock_frame);
227
+ *frame_next = frame.clone ();
228
+ new_frame = true ;
229
+ condition_new_frame.notify_all ();
230
+ }
231
+
232
+ void get_output_mask (cv::Mat &out) {
233
+ if (new_mask) {
234
+ std::lock_guard<std::mutex> hold (lock_mask);
235
+ out = mask_out->clone ();
236
+ new_mask = false ;
237
+ }
238
+ }
239
+ };
240
+
148
241
int main (int argc, char * argv[]) {
149
242
150
243
printf (" deepseg version %s\n " , _STR (DEEPSEG_VERSION));
@@ -334,8 +427,9 @@ int main(int argc, char* argv[]) {
334
427
if (!maskctx)
335
428
exit (1 );
336
429
337
- cv::Mat mask;
430
+ cv::Mat mask (height, width, CV_8U) ;
338
431
cv::Mat raw;
432
+ CalcMask ai (maskctx);
339
433
ti.lastns = timestamp ();
340
434
printf (" Startup: %ldns\n " , diffnanosecs (ti.lastns ,ti.bootns ));
341
435
@@ -349,6 +443,7 @@ int main(int argc, char* argv[]) {
349
443
cap.grab ();
350
444
// copy new frame to buffer
351
445
cap.retrieve (raw);
446
+ ai.set_input_frame (raw);
352
447
353
448
ti.copyns =timestamp ();
354
449
if (raw.rows == 0 || raw.cols == 0 ) continue ; // sanity check
@@ -360,11 +455,7 @@ int main(int argc, char* argv[]) {
360
455
361
456
if (filterActive) {
362
457
// do background detection magic
363
- cv::Mat mask;
364
- if (!bs_maskgen_process (maskctx, raw, mask)) {
365
- fprintf (stderr, " failed to process video frame\n " );
366
- exit (1 );
367
- }
458
+ ai.get_output_mask (mask);
368
459
369
460
// alpha blend background over foreground using mask
370
461
raw = alpha_blend (bg, raw, mask);
0 commit comments