4 * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "findobjwindow.h"
29 #include "overlayframe.h"
31 #include "pluginserver.h"
38 REGISTER_PLUGIN(FindObjMain)
40 FindObjConfig::FindObjConfig()
45 void FindObjConfig::reset()
47 algorithm = NO_ALGORITHM;
50 draw_scene_border = 0;
52 draw_object_border = 0;
53 draw_replace_border = 0;
54 object_x = 50; object_y = 50;
55 object_w = 100; object_h = 100;
57 scene_x = 50; scene_y = 50;
58 scene_w = 100; scene_h = 100;
60 replace_x = 50; replace_y = 50;
61 replace_w = 100; replace_h = 100;
62 replace_dx = 0; replace_dy = 0;
70 void FindObjConfig::boundaries()
72 bclamp(object_x, 0, 100); bclamp(object_y, 0, 100);
73 bclamp(object_w, 0, 100); bclamp(object_h, 0, 100);
74 bclamp(scene_x, 0, 100); bclamp(scene_y, 0, 100);
75 bclamp(scene_w, 0, 100); bclamp(scene_h, 0, 100);
76 bclamp(object_layer, MIN_LAYER, MAX_LAYER);
77 bclamp(replace_layer, MIN_LAYER, MAX_LAYER);
78 bclamp(scene_layer, MIN_LAYER, MAX_LAYER);
79 bclamp(blend, MIN_BLEND, MAX_BLEND);
82 int FindObjConfig::equivalent(FindObjConfig &that)
85 algorithm == that.algorithm &&
86 use_flann == that.use_flann &&
87 draw_keypoints == that.draw_keypoints &&
88 draw_scene_border == that.draw_scene_border &&
89 replace_object == that.replace_object &&
90 draw_object_border == that.draw_object_border &&
91 draw_replace_border == that.draw_replace_border &&
92 object_x == that.object_x && object_y == that.object_y &&
93 object_w == that.object_w && object_h == that.object_h &&
94 drag_object == that.drag_object &&
95 scene_x == that.scene_x && scene_y == that.scene_y &&
96 scene_w == that.scene_w && scene_h == that.scene_h &&
97 drag_scene == that.drag_scene &&
98 replace_x == that.replace_x && replace_y == that.replace_y &&
99 replace_w == that.replace_w && replace_h == that.replace_h &&
100 replace_dx == that.replace_dx && replace_dy == that.replace_dy &&
101 drag_replace == that.drag_replace &&
102 object_layer == that.object_layer &&
103 replace_layer == that.replace_layer &&
104 scene_layer == that.scene_layer &&
109 void FindObjConfig::copy_from(FindObjConfig &that)
111 algorithm = that.algorithm;
112 use_flann = that.use_flann;
113 draw_keypoints = that.draw_keypoints;
114 draw_scene_border = that.draw_scene_border;
115 replace_object = that.replace_object;
116 draw_object_border = that.draw_object_border;
117 draw_replace_border = that.draw_replace_border;
118 object_x = that.object_x; object_y = that.object_y;
119 object_w = that.object_w; object_h = that.object_h;
120 drag_object = that.drag_object;
121 scene_x = that.scene_x; scene_y = that.scene_y;
122 scene_w = that.scene_w; scene_h = that.scene_h;
123 drag_scene = that.drag_scene;
124 replace_x = that.replace_x; replace_y = that.replace_y;
125 replace_w = that.replace_w; replace_h = that.replace_h;
126 replace_dx = that.replace_dx; replace_dy = that.replace_dy;
127 drag_replace = that.drag_replace;
128 object_layer = that.object_layer;
129 replace_layer = that.replace_layer;
130 scene_layer = that.scene_layer;
134 void FindObjConfig::interpolate(FindObjConfig &prev, FindObjConfig &next,
135 int64_t prev_frame, int64_t next_frame, int64_t current_frame)
141 FindObjMain::FindObjMain(PluginServer *server)
142 : PluginVClient(server)
149 object = scene = replace = 0;
150 object_x = object_y = 0;
151 object_w = object_h = 0;
152 scene_x = scene_y = 0;
153 scene_w = scene_h = 0;
158 border_x1 = 0; border_y1 = 0;
159 border_x2 = 0; border_y2 = 0;
160 border_x3 = 0; border_y3 = 0;
161 border_x4 = 0; border_y4 = 0;
163 obj_x1 = 0; obj_y1 = 0;
164 obj_x2 = 0; obj_y2 = 0;
165 obj_x3 = 0; obj_y3 = 0;
166 obj_x4 = 0; obj_y4 = 0;
171 FindObjMain::~FindObjMain()
177 const char* FindObjMain::plugin_title() { return N_("FindObj"); }
178 int FindObjMain::is_realtime() { return 1; }
179 int FindObjMain::is_multichannel() { return 1; }
181 NEW_WINDOW_MACRO(FindObjMain, FindObjWindow)
182 LOAD_CONFIGURATION_MACRO(FindObjMain, FindObjConfig)
184 void FindObjMain::update_gui()
186 if( !thread ) return;
187 if( !load_configuration() ) return;
188 FindObjWindow *window = (FindObjWindow*)thread->window;
189 window->lock_window("FindObjMain::update_gui");
190 window->update_gui();
192 window->unlock_window();
195 void FindObjMain::save_data(KeyFrame *keyframe)
199 // cause data to be stored directly in text
200 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
201 output.tag.set_title("FINDOBJ");
202 output.tag.set_property("ALGORITHM", config.algorithm);
203 output.tag.set_property("USE_FLANN", config.use_flann);
204 output.tag.set_property("DRAG_OBJECT", config.drag_object);
205 output.tag.set_property("OBJECT_X", config.object_x);
206 output.tag.set_property("OBJECT_Y", config.object_y);
207 output.tag.set_property("OBJECT_W", config.object_w);
208 output.tag.set_property("OBJECT_H", config.object_h);
209 output.tag.set_property("DRAG_SCENE", config.drag_scene);
210 output.tag.set_property("SCENE_X", config.scene_x);
211 output.tag.set_property("SCENE_Y", config.scene_y);
212 output.tag.set_property("SCENE_W", config.scene_w);
213 output.tag.set_property("SCENE_H", config.scene_h);
214 output.tag.set_property("DRAG_REPLACE", config.drag_replace);
215 output.tag.set_property("REPLACE_X", config.replace_x);
216 output.tag.set_property("REPLACE_Y", config.replace_y);
217 output.tag.set_property("REPLACE_W", config.replace_w);
218 output.tag.set_property("REPLACE_H", config.replace_h);
219 output.tag.set_property("REPLACE_DX", config.replace_dx);
220 output.tag.set_property("REPLACE_DY", config.replace_dy);
221 output.tag.set_property("DRAW_KEYPOINTS", config.draw_keypoints);
222 output.tag.set_property("DRAW_SCENE_BORDER", config.draw_scene_border);
223 output.tag.set_property("REPLACE_OBJECT", config.replace_object);
224 output.tag.set_property("DRAW_OBJECT_BORDER", config.draw_object_border);
225 output.tag.set_property("DRAW_REPLACE_BORDER", config.draw_replace_border);
226 output.tag.set_property("OBJECT_LAYER", config.object_layer);
227 output.tag.set_property("REPLACE_LAYER", config.replace_layer);
228 output.tag.set_property("SCENE_LAYER", config.scene_layer);
229 output.tag.set_property("BLEND", config.blend);
231 output.tag.set_title("/FINDOBJ");
233 output.append_newline();
234 output.terminate_string();
237 void FindObjMain::read_data(KeyFrame *keyframe)
241 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
245 while( !(result = input.read_tag()) ) {
246 if( input.tag.title_is("FINDOBJ") ) {
247 config.algorithm = input.tag.get_property("ALGORITHM", config.algorithm);
248 config.use_flann = input.tag.get_property("USE_FLANN", config.use_flann);
249 config.object_x = input.tag.get_property("OBJECT_X", config.object_x);
250 config.object_y = input.tag.get_property("OBJECT_Y", config.object_y);
251 config.object_w = input.tag.get_property("OBJECT_W", config.object_w);
252 config.object_h = input.tag.get_property("OBJECT_H", config.object_h);
253 config.drag_object = input.tag.get_property("DRAG_OBJECT", config.drag_object);
254 config.scene_x = input.tag.get_property("SCENE_X", config.scene_x);
255 config.scene_y = input.tag.get_property("SCENE_Y", config.scene_y);
256 config.scene_w = input.tag.get_property("SCENE_W", config.scene_w);
257 config.scene_h = input.tag.get_property("SCENE_H", config.scene_h);
258 config.drag_scene = input.tag.get_property("DRAG_SCENE", config.drag_scene);
259 config.replace_x = input.tag.get_property("REPLACE_X", config.replace_x);
260 config.replace_y = input.tag.get_property("REPLACE_Y", config.replace_y);
261 config.replace_w = input.tag.get_property("REPLACE_W", config.replace_w);
262 config.replace_h = input.tag.get_property("REPLACE_H", config.replace_h);
263 config.replace_dx = input.tag.get_property("REPLACE_DX", config.replace_dx);
264 config.replace_dy = input.tag.get_property("REPLACE_DY", config.replace_dy);
265 config.drag_replace = input.tag.get_property("DRAG_REPLACE", config.drag_replace);
266 config.draw_keypoints = input.tag.get_property("DRAW_KEYPOINTS", config.draw_keypoints);
267 config.draw_scene_border = input.tag.get_property("DRAW_SCENE_BORDER", config.draw_scene_border);
268 config.replace_object = input.tag.get_property("REPLACE_OBJECT", config.replace_object);
269 config.draw_object_border = input.tag.get_property("DRAW_OBJECT_BORDER", config.draw_object_border);
270 config.draw_replace_border = input.tag.get_property("DRAW_REPLACE_BORDER", config.draw_replace_border);
271 config.object_layer = input.tag.get_property("OBJECT_LAYER", config.object_layer);
272 config.replace_layer = input.tag.get_property("REPLACE_LAYER", config.replace_layer);
273 config.scene_layer = input.tag.get_property("SCENE_LAYER", config.scene_layer);
274 config.blend = input.tag.get_property("BLEND", config.blend);
281 void FindObjMain::draw_line(VFrame *vframe, int x1, int y1, int x2, int y2)
283 vframe->draw_line(x1, y1, x2, y2);
286 void FindObjMain::draw_rect(VFrame *vframe, int x1, int y1, int x2, int y2)
289 draw_line(vframe, x1, y1, x2, y1);
290 draw_line(vframe, x2, y1, x2, y2);
291 draw_line(vframe, x2, y2, x1, y2);
292 draw_line(vframe, x1, y2, x1, y1);
295 void FindObjMain::draw_circle(VFrame *vframe, int x, int y, int r)
297 int x1 = x-r, x2 = x+r;
298 int y1 = y-r, y2 = y+r;
299 vframe->draw_smooth(x1,y, x1,y1, x,y1);
300 vframe->draw_smooth(x,y1, x2,y1, x2,y);
301 vframe->draw_smooth(x2,y, x2,y2, x,y2);
302 vframe->draw_smooth(x,y2, x1,y2, x1,y);
305 void FindObjMain::filter_matches(ptV &p1, ptV &p2, double ratio)
307 DMatches::iterator it;
308 for( it=pairs.begin(); it!=pairs.end(); ++it ) {
310 if( m.size() == 2 && m[0].distance < m[1].distance*ratio ) {
311 p1.push_back(obj_keypts[m[0].queryIdx].pt);
312 p2.push_back(scn_keypts[m[0].trainIdx].pt);
317 void FindObjMain::to_mat(Mat &mat, int mcols, int mrows,
318 VFrame *inp, int ix,int iy, BC_CModel mcolor_model)
320 int mcomp = BC_CModels::components(mcolor_model);
321 int mbpp = BC_CModels::calculate_pixelsize(mcolor_model);
322 int psz = mbpp / mcomp;
323 int mdepth = psz < 2 ? CV_8U : CV_16U;
324 if( mat.dims != 2 || mat.depth() != mdepth || mat.channels() != mcomp ||
325 mat.cols != mcols || mat.rows != mrows ) {
329 int type = CV_MAKETYPE(mdepth, mcomp);
330 mat.create(mrows, mcols, type);
332 uint8_t *mat_rows[mrows];
333 for( int y=0; y<mrows; ++y ) mat_rows[y] = mat.ptr(y);
334 uint8_t **inp_rows = inp->get_rows();
335 int ibpl = inp->get_bytes_per_line(), obpl = mcols * mbpp;
336 int icolor_model = inp->get_color_model();
337 BC_CModels::transfer(mat_rows, mcolor_model, 0,0, mcols,mrows, obpl,
338 inp_rows, icolor_model, ix,iy, mcols,mrows, ibpl, 0);
339 // VFrame vfrm(mat_rows[0], -1, mcols,mrows, mcolor_model, mat_rows[1]-mat_rows[0]);
340 // static int vfrm_no = 0; char vfn[64]; sprintf(vfn,"/tmp/dat/%06d.png", vfrm_no++);
341 // vfrm.write_png(vfn);
344 void FindObjMain::detect(Mat &mat, KeyPointV &keypts,Mat &descrs)
349 detector->detectAndCompute(mat, noArray(), keypts, descrs);
350 } catch(std::exception e) { printf(_("detector exception: %s\n"), e.what()); }
353 void FindObjMain::match()
357 matcher->knnMatch(obj_descrs, scn_descrs, pairs, 2);
358 } catch(std::exception e) { printf(_("match execption: %s\n"), e.what()); }
361 Ptr<DescriptorMatcher> FindObjMain::flann_kdtree_matcher()
363 const Ptr<flann::IndexParams>& indexParams =
364 makePtr<flann::KDTreeIndexParams>(5);
365 const Ptr<flann::SearchParams>& searchParams =
366 makePtr<flann::SearchParams>();
367 return makePtr<FlannBasedMatcher>(indexParams, searchParams);
369 Ptr<DescriptorMatcher> FindObjMain::flann_lshidx_matcher()
370 { // table_number = 6#12, key_size = 12#20, multi_probe_level = 1#2
371 const Ptr<flann::IndexParams>& indexParams =
372 makePtr<flann::LshIndexParams>(6, 12, 1);
373 const Ptr<flann::SearchParams>& searchParams =
374 makePtr<flann::SearchParams>();
375 return makePtr<FlannBasedMatcher>(indexParams, searchParams);
377 Ptr<DescriptorMatcher> FindObjMain::bf_matcher_norm_l2()
379 return BFMatcher::create(NORM_L2);
381 Ptr<DescriptorMatcher> FindObjMain::bf_matcher_norm_hamming()
383 return BFMatcher::create(NORM_HAMMING);
387 void FindObjMain::set_sift()
390 detector = SIFT::create();
391 matcher = config.use_flann ?
392 flann_kdtree_matcher() : bf_matcher_norm_l2();
396 void FindObjMain::set_surf()
399 detector = SURF::create(800);
400 matcher = config.use_flann ?
401 flann_kdtree_matcher() : bf_matcher_norm_l2();
405 void FindObjMain::set_orb()
408 detector = ORB::create();
409 matcher = config.use_flann ?
410 flann_lshidx_matcher() : bf_matcher_norm_hamming();
414 void FindObjMain::set_akaze()
417 detector = AKAZE::create();
418 matcher = config.use_flann ?
419 flann_lshidx_matcher() : bf_matcher_norm_hamming();
423 void FindObjMain::set_brisk()
426 detector = BRISK::create();
427 matcher = config.use_flann ?
428 flann_lshidx_matcher() : bf_matcher_norm_hamming();
432 void FindObjMain::process_match()
434 if( config.algorithm == NO_ALGORITHM ) return;
435 if( !config.replace_object &&
436 !config.draw_scene_border &&
437 !config.draw_keypoints ) return;
439 if( detector.empty() ) {
440 switch( config.algorithm ) {
442 case ALGORITHM_SIFT: set_sift(); break;
445 case ALGORITHM_SURF: set_surf(); break;
448 case ALGORITHM_ORB: set_orb(); break;
451 case ALGORITHM_AKAZE: set_akaze(); break;
454 case ALGORITHM_BRISK: set_brisk(); break;
457 obj_keypts.clear(); obj_descrs.release();
458 to_mat(object_mat, object_w,object_h, object, object_x,object_y, cvmodel);
459 detect(object_mat, obj_keypts, obj_descrs);
460 //printf("detect obj %d features\n", (int)obj_keypts.size());
463 to_mat(scene_mat, scene_w,scene_h, scene, scene_x,scene_y, cvmodel);
464 detect(scene_mat, scn_keypts, scn_descrs);
465 //printf("detect scn %d features\n", (int)scn_keypts.size());
468 filter_matches(p1, p2);
469 if( p1.size() < 4 ) return;
470 Mat H = findHomography(p1, p2, RANSAC, 5.0);
471 if( !H.dims || !H.rows || !H.cols ) {
472 //printf("fail, size p1=%d,p2=%d\n",(int)p1.size(),(int)p2.size());
477 float obj_x1 = 0, obj_x2 = object_w;
478 float obj_y1 = 0, obj_y2 = object_h;
479 src.push_back(Point2f(obj_x1,obj_y1));
480 src.push_back(Point2f(obj_x2,obj_y1));
481 src.push_back(Point2f(obj_x2,obj_y2));
482 src.push_back(Point2f(obj_x1,obj_y2));
483 perspectiveTransform(src, dst, H);
485 float dx = scene_x + replace_dx;
486 float dy = scene_y + replace_dy;
487 border_x1 = dst[0].x + dx; border_y1 = dst[0].y + dy;
488 border_x2 = dst[1].x + dx; border_y2 = dst[1].y + dy;
489 border_x3 = dst[2].x + dx; border_y3 = dst[2].y + dy;
490 border_x4 = dst[3].x + dx; border_y4 = dst[3].y + dy;
491 //printf("src %f,%f %f,%f %f,%f %f,%f\n",
492 // src[0].x,src[0].y, src[1].x,src[1].y, src[2].x,src[2].y, src[3].x,src[3].y);
493 //printf("dst %f,%f %f,%f %f,%f %f,%f\n",
494 // dst[0].x,dst[0].y, dst[1].x,dst[1].y, dst[2].x,dst[2].y, dst[3].x,dst[3].y);
497 int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double frame_rate)
499 int prev_algorithm = config.algorithm;
500 int prev_use_flann = config.use_flann;
502 if( load_configuration() )
505 if( prev_algorithm != config.algorithm ||
506 prev_use_flann != config.use_flann ) {
511 object_layer = config.object_layer;
512 scene_layer = config.scene_layer;
513 replace_layer = config.replace_layer;
514 Track *track = server->plugin->track;
518 int max_layer = PluginClient::get_total_buffers() - 1;
519 object_layer = bclip(config.object_layer, 0, max_layer);
520 scene_layer = bclip(config.scene_layer, 0, max_layer);
521 replace_layer = bclip(config.replace_layer, 0, max_layer);
523 int cfg_w = (int)(w * config.object_w / 100.);
524 int cfg_h = (int)(h * config.object_h / 100.);
525 int cfg_x1 = (int)(w * config.object_x / 100. - cfg_w / 2);
526 int cfg_y1 = (int)(h * config.object_y / 100. - cfg_h / 2);
527 int cfg_x2 = cfg_x1 + cfg_w;
528 int cfg_y2 = cfg_y1 + cfg_h;
529 bclamp(cfg_x1, 0, w); object_x = cfg_x1;
530 bclamp(cfg_y1, 0, h); object_y = cfg_y1;
531 bclamp(cfg_x2, 0, w); object_w = cfg_x2 - cfg_x1;
532 bclamp(cfg_y2, 0, h); object_h = cfg_y2 - cfg_y1;
534 cfg_w = (int)(w * config.scene_w / 100.);
535 cfg_h = (int)(h * config.scene_h / 100.);
536 cfg_x1 = (int)(w * config.scene_x / 100. - cfg_w / 2);
537 cfg_y1 = (int)(h * config.scene_y / 100. - cfg_h / 2);
538 cfg_x2 = cfg_x1 + cfg_w;
539 cfg_y2 = cfg_y1 + cfg_h;
540 bclamp(cfg_x1, 0, w); scene_x = cfg_x1;
541 bclamp(cfg_y1, 0, h); scene_y = cfg_y1;
542 bclamp(cfg_x2, 0, w); scene_w = cfg_x2 - cfg_x1;
543 bclamp(cfg_y2, 0, h); scene_h = cfg_y2 - cfg_y1;
545 cfg_w = (int)(w * config.replace_w / 100.);
546 cfg_h = (int)(h * config.replace_h / 100.);
547 cfg_x1 = (int)(w * config.replace_x / 100. - cfg_w / 2);
548 cfg_y1 = (int)(h * config.replace_y / 100. - cfg_h / 2);
549 cfg_x2 = cfg_x1 + cfg_w;
550 cfg_y2 = cfg_y1 + cfg_h;
551 bclamp(cfg_x1, 0, w); replace_x = cfg_x1;
552 bclamp(cfg_y1, 0, h); replace_y = cfg_y1;
553 bclamp(cfg_x2, 0, w); replace_w = cfg_x2 - cfg_x1;
554 bclamp(cfg_y2, 0, h); replace_h = cfg_y2 - cfg_y1;
556 int cfg_dx = (int)(w * config.replace_dx / 100.);
557 int cfg_dy = (int)(h * config.replace_dy / 100.);
558 bclamp(cfg_dx, -h, h); replace_dx = cfg_dx;
559 bclamp(cfg_dy, -w, w); replace_dy = cfg_dy;
561 // Read in the input frames
562 for( int i = 0; i < PluginClient::get_total_buffers(); i++ ) {
563 read_frame(frame[i], i, start_position, frame_rate, 0);
566 object = frame[object_layer];
567 scene = frame[scene_layer];
568 replace = frame[replace_layer];
570 border_x1 = obj_x1; border_y1 = obj_y1;
571 border_x2 = obj_x2; border_y2 = obj_y2;
572 border_x3 = obj_x3; border_y3 = obj_y3;
573 border_x4 = obj_x4; border_y4 = obj_y4;
575 if( scene_w > 0 && scene_h > 0 && object_w > 0 && object_h > 0 ) {
579 double w0 = init_border ? (init_border=0, 1.) : config.blend/100., w1 = 1. - w0;
580 obj_x1 = border_x1*w0 + obj_x1*w1; obj_y1 = border_y1*w0 + obj_y1*w1;
581 obj_x2 = border_x2*w0 + obj_x2*w1; obj_y2 = border_y2*w0 + obj_y2*w1;
582 obj_x3 = border_x3*w0 + obj_x3*w1; obj_y3 = border_y3*w0 + obj_y3*w1;
583 obj_x4 = border_x4*w0 + obj_x4*w1; obj_y4 = border_y4*w0 + obj_y4*w1;
585 // Replace object in the scene layer
586 if( config.replace_object ) {
587 int cpus1 = get_project_smp() + 1;
589 affine = new AffineEngine(cpus1, cpus1);
591 overlayer = new OverlayFrame(cpus1);
592 VFrame *temp = new_temp(w, h, scene->get_color_model());
594 affine->set_in_viewport(replace_x, replace_y, replace_w, replace_h);
595 int x1 = obj_x1, x2 = obj_x2, x3 = obj_x3, x4 = obj_x4;
596 int y1 = obj_y1, y2 = obj_y2, y3 = obj_y3, y4 = obj_y4;
597 bclamp(x1, 0, w); bclamp(x2, 0, w); bclamp(x3, 0, w); bclamp(x4, 0, w);
598 bclamp(y1, 0, h); bclamp(y2, 0, h); bclamp(y3, 0, h); bclamp(y4, 0, h);
600 replace_x, replace_y, replace_x+replace_w, replace_y+replace_h,
601 x1,y1, x2,y2, x3,y3, x4,y4);
602 affine->process(temp, replace, 0,
603 AffineEngine::TRANSFORM, 0,0, 100,0, 100,100, 0,100, 1);
604 overlayer->overlay(scene, temp, 0,0, w,h, 0,0, w,h,
605 1, TRANSFER_NORMAL, NEAREST_NEIGHBOR);
609 if( config.draw_scene_border ) {
610 int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1;
611 scene->set_pixel_color(WHITE); scene->set_stiple(ss*2);
612 draw_rect(scene, scene_x, scene_y, scene_x+scene_w, scene_y+scene_h);
614 if( config.draw_object_border ) {
615 int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1;
616 scene->set_pixel_color(YELLOW); scene->set_stiple(ss*3);
617 draw_rect(scene, object_x, object_y, object_x+object_w, object_y+object_h);
619 if( config.draw_replace_border ) {
620 int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1;
621 scene->set_pixel_color(GREEN); scene->set_stiple(ss*3);
622 draw_rect(scene, replace_x, replace_y, replace_x+replace_w, replace_y+replace_h);
624 if( config.draw_keypoints ) {
625 scene->set_pixel_color(RED); scene->set_stiple(0);
626 for( int i=0,n=scn_keypts.size(); i<n; ++i ) {
627 Point2f &pt = scn_keypts[i].pt;
628 int r = scn_keypts[i].size * 1.2/9 * 2;
629 int x = pt.x + scene_x, y = pt.y + scene_y;
630 draw_circle(scene, x, y, r);
635 if( config.drag_scene ) {
636 scene->set_pixel_color(WHITE);
637 DragCheckBox::draw_boundary(scene, scene_x, scene_y, scene_w, scene_h);
639 if( config.drag_object ) {
640 scene->set_pixel_color(YELLOW);
641 DragCheckBox::draw_boundary(scene, object_x, object_y, object_w, object_h);
643 if( config.drag_replace ) {
644 scene->set_pixel_color(GREEN);
645 DragCheckBox::draw_boundary(scene, replace_x, replace_y, replace_w, replace_h);
649 scene->set_pixel_color(BLACK);
650 scene->set_stiple(0);