X-Git-Url: https://git.cinelerra-gg.org/git/?a=blobdiff_plain;ds=sidebyside;f=cinelerra-5.1%2Fplugins%2Ffindobj%2Ffindobj.C;h=6815fd1aaf233e77b939a65bafb0d98ff6de8eb3;hb=c0fe374d9f9ab1653e9cc2edb41afb076eeae69f;hp=70fc9b3f260ded07d8789f78ec22eb7ccb66a506;hpb=9f682a609a1817808682efa68cb96a296815bf80;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/plugins/findobj/findobj.C b/cinelerra-5.1/plugins/findobj/findobj.C index 70fc9b3f..6815fd1a 100644 --- a/cinelerra-5.1/plugins/findobj/findobj.C +++ b/cinelerra-5.1/plugins/findobj/findobj.C @@ -19,7 +19,7 @@ */ #include "affine.h" -#include "cicolors.h" +#include "bccolors.h" #include "clip.h" #include "filexml.h" #include "language.h" @@ -27,6 +27,9 @@ #include "findobjwindow.h" #include "mutex.h" #include "overlayframe.h" +#include "plugin.h" +#include "pluginserver.h" +#include "track.h" #include #include @@ -35,17 +38,35 @@ REGISTER_PLUGIN(FindObjMain) FindObjConfig::FindObjConfig() +{ + reset(); +} + +void FindObjConfig::reset() { algorithm = NO_ALGORITHM; use_flann = 1; + mode = MODE_QUADRILATERAL; + draw_match = 0; + aspect = 1; + scale = 1; + translate = 1; + rotate = 1; draw_keypoints = 0; - draw_border = 0; + draw_scene_border = 0; replace_object = 0; draw_object_border = 0; + draw_replace_border = 0; object_x = 50; object_y = 50; object_w = 100; object_h = 100; + drag_object = 0; scene_x = 50; scene_y = 50; scene_w = 100; scene_h = 100; + drag_replace = 0; + replace_x = 50; replace_y = 50; + replace_w = 100; replace_h = 100; + replace_dx = 0; replace_dy = 0; + drag_scene = 0; scene_layer = 0; object_layer = 1; replace_layer = 2; @@ -69,14 +90,27 @@ int FindObjConfig::equivalent(FindObjConfig &that) int result = algorithm == that.algorithm && use_flann == that.use_flann && + mode == that.mode && + aspect == that.aspect && + scale == that.scale && + translate == that.translate && + rotate == that.rotate && draw_keypoints == that.draw_keypoints && - draw_border == that.draw_border && + draw_match == that.draw_match && + draw_scene_border == that.draw_scene_border && replace_object == that.replace_object && draw_object_border == that.draw_object_border && + draw_replace_border == that.draw_replace_border && object_x == that.object_x && object_y == that.object_y && object_w == that.object_w && object_h == that.object_h && + drag_object == that.drag_object && scene_x == that.scene_x && scene_y == that.scene_y && scene_w == that.scene_w && scene_h == that.scene_h && + drag_scene == that.drag_scene && + replace_x == that.replace_x && replace_y == that.replace_y && + replace_w == that.replace_w && replace_h == that.replace_h && + replace_dx == that.replace_dx && replace_dy == that.replace_dy && + drag_replace == that.drag_replace && object_layer == that.object_layer && replace_layer == that.replace_layer && scene_layer == that.scene_layer && @@ -88,14 +122,27 @@ void FindObjConfig::copy_from(FindObjConfig &that) { algorithm = that.algorithm; use_flann = that.use_flann; + mode = that.mode; + aspect = that.aspect; + scale = that.scale; + translate = that.translate; + rotate = that.rotate; draw_keypoints = that.draw_keypoints; - draw_border = that.draw_border; + draw_match = that.draw_match; + draw_scene_border = that.draw_scene_border; replace_object = that.replace_object; draw_object_border = that.draw_object_border; + draw_replace_border = that.draw_replace_border; object_x = that.object_x; object_y = that.object_y; object_w = that.object_w; object_h = that.object_h; + drag_object = that.drag_object; scene_x = that.scene_x; scene_y = that.scene_y; scene_w = that.scene_w; scene_h = that.scene_h; + drag_scene = that.drag_scene; + replace_x = that.replace_x; replace_y = that.replace_y; + replace_w = that.replace_w; replace_h = that.replace_h; + replace_dx = that.replace_dx; replace_dy = that.replace_dy; + drag_replace = that.drag_replace; object_layer = that.object_layer; replace_layer = that.replace_layer; scene_layer = that.scene_layer; @@ -126,15 +173,18 @@ FindObjMain::FindObjMain(PluginServer *server) scene_layer = 1; replace_layer = 2; - border_x1 = 0; border_y1 = 0; - border_x2 = 0; border_y2 = 0; - border_x3 = 0; border_y3 = 0; - border_x4 = 0; border_y4 = 0; - - obj_x1 = 0; obj_y1 = 0; - obj_x2 = 0; obj_y2 = 0; - obj_x3 = 0; obj_y3 = 0; - obj_x4 = 0; obj_y4 = 0; + match_x1 = 0; match_y1 = 0; + match_x2 = 0; match_y2 = 0; + match_x3 = 0; match_y3 = 0; + match_x4 = 0; match_y4 = 0; + shape_x1 = 0; shape_y1 = 0; + shape_x2 = 0; shape_y2 = 0; + shape_x3 = 0; shape_y3 = 0; + shape_x4 = 0; shape_y4 = 0; + out_x1 = 0; out_y1 = 0; + out_x2 = 0; out_y2 = 0; + out_x3 = 0; out_y3 = 0; + out_x4 = 0; out_y4 = 0; init_border = 1; } @@ -145,7 +195,7 @@ FindObjMain::~FindObjMain() delete overlayer; } -const char* FindObjMain::plugin_title() { return _("Find Object"); } +const char* FindObjMain::plugin_title() { return N_("FindObj"); } int FindObjMain::is_realtime() { return 1; } int FindObjMain::is_multichannel() { return 1; } @@ -158,32 +208,7 @@ void FindObjMain::update_gui() if( !load_configuration() ) return; FindObjWindow *window = (FindObjWindow*)thread->window; window->lock_window("FindObjMain::update_gui"); - window->algorithm->set_text(FindObjAlgorithm::to_text(config.algorithm)); - window->use_flann->update(config.use_flann); - window->object_x->update(config.object_x); - window->object_x_text->update((float)config.object_x); - window->object_y->update(config.object_y); - window->object_y_text->update((float)config.object_y); - window->object_w->update(config.object_w); - window->object_w_text->update((float)config.object_w); - window->object_h->update(config.object_h); - window->object_h_text->update((float)config.object_h); - window->scene_x->update(config.scene_x); - window->scene_x_text->update((float)config.scene_x); - window->scene_y->update(config.scene_y); - window->scene_y_text->update((float)config.scene_y); - window->scene_w->update(config.scene_w); - window->scene_w_text->update((float)config.scene_w); - window->scene_h->update(config.scene_h); - window->scene_h_text->update((float)config.scene_h); - window->draw_keypoints->update(config.draw_keypoints); - window->draw_border->update(config.draw_border); - window->replace_object->update(config.replace_object); - window->draw_object_border->update(config.draw_object_border); - window->object_layer->update( (int64_t)config.object_layer); - window->replace_layer->update( (int64_t)config.replace_layer); - window->scene_layer->update( (int64_t)config.scene_layer); - window->blend->update( (int64_t)config.blend); + window->update_gui(); window->flush(); window->unlock_window(); } @@ -197,18 +222,34 @@ void FindObjMain::save_data(KeyFrame *keyframe) output.tag.set_title("FINDOBJ"); output.tag.set_property("ALGORITHM", config.algorithm); output.tag.set_property("USE_FLANN", config.use_flann); + output.tag.set_property("MODE", config.mode); + output.tag.set_property("ASPECT", config.aspect); + output.tag.set_property("SCALE", config.scale); + output.tag.set_property("TRANSLATE", config.translate); + output.tag.set_property("ROTATE", config.rotate); + output.tag.set_property("DRAG_OBJECT", config.drag_object); output.tag.set_property("OBJECT_X", config.object_x); output.tag.set_property("OBJECT_Y", config.object_y); output.tag.set_property("OBJECT_W", config.object_w); output.tag.set_property("OBJECT_H", config.object_h); + output.tag.set_property("DRAG_SCENE", config.drag_scene); output.tag.set_property("SCENE_X", config.scene_x); output.tag.set_property("SCENE_Y", config.scene_y); output.tag.set_property("SCENE_W", config.scene_w); output.tag.set_property("SCENE_H", config.scene_h); + output.tag.set_property("DRAG_REPLACE", config.drag_replace); + output.tag.set_property("REPLACE_X", config.replace_x); + output.tag.set_property("REPLACE_Y", config.replace_y); + output.tag.set_property("REPLACE_W", config.replace_w); + output.tag.set_property("REPLACE_H", config.replace_h); + output.tag.set_property("REPLACE_DX", config.replace_dx); + output.tag.set_property("REPLACE_DY", config.replace_dy); output.tag.set_property("DRAW_KEYPOINTS", config.draw_keypoints); - output.tag.set_property("DRAW_BORDER", config.draw_border); + output.tag.set_property("DRAW_MATCH", config.draw_match); + output.tag.set_property("DRAW_SCENE_BORDER", config.draw_scene_border); output.tag.set_property("REPLACE_OBJECT", config.replace_object); output.tag.set_property("DRAW_OBJECT_BORDER", config.draw_object_border); + output.tag.set_property("DRAW_REPLACE_BORDER", config.draw_replace_border); output.tag.set_property("OBJECT_LAYER", config.object_layer); output.tag.set_property("REPLACE_LAYER", config.replace_layer); output.tag.set_property("SCENE_LAYER", config.scene_layer); @@ -232,18 +273,34 @@ void FindObjMain::read_data(KeyFrame *keyframe) if( input.tag.title_is("FINDOBJ") ) { config.algorithm = input.tag.get_property("ALGORITHM", config.algorithm); config.use_flann = input.tag.get_property("USE_FLANN", config.use_flann); + config.mode = input.tag.get_property("MODE", config.mode); + config.aspect = input.tag.get_property("ASPECT", config.aspect); + config.scale = input.tag.get_property("SCALE", config.scale); + config.translate = input.tag.get_property("TRANSLATE", config.translate); + config.rotate = input.tag.get_property("ROTATE", config.rotate); config.object_x = input.tag.get_property("OBJECT_X", config.object_x); config.object_y = input.tag.get_property("OBJECT_Y", config.object_y); config.object_w = input.tag.get_property("OBJECT_W", config.object_w); config.object_h = input.tag.get_property("OBJECT_H", config.object_h); + config.drag_object = input.tag.get_property("DRAG_OBJECT", config.drag_object); config.scene_x = input.tag.get_property("SCENE_X", config.scene_x); config.scene_y = input.tag.get_property("SCENE_Y", config.scene_y); config.scene_w = input.tag.get_property("SCENE_W", config.scene_w); config.scene_h = input.tag.get_property("SCENE_H", config.scene_h); + config.drag_scene = input.tag.get_property("DRAG_SCENE", config.drag_scene); + config.replace_x = input.tag.get_property("REPLACE_X", config.replace_x); + config.replace_y = input.tag.get_property("REPLACE_Y", config.replace_y); + config.replace_w = input.tag.get_property("REPLACE_W", config.replace_w); + config.replace_h = input.tag.get_property("REPLACE_H", config.replace_h); + config.replace_dx = input.tag.get_property("REPLACE_DX", config.replace_dx); + config.replace_dy = input.tag.get_property("REPLACE_DY", config.replace_dy); + config.drag_replace = input.tag.get_property("DRAG_REPLACE", config.drag_replace); config.draw_keypoints = input.tag.get_property("DRAW_KEYPOINTS", config.draw_keypoints); - config.draw_border = input.tag.get_property("DRAW_BORDER", config.draw_border); + config.draw_match = input.tag.get_property("DRAW_MATCH", config.draw_match); + config.draw_scene_border = input.tag.get_property("DRAW_SCENE_BORDER", config.draw_scene_border); config.replace_object = input.tag.get_property("REPLACE_OBJECT", config.replace_object); config.draw_object_border = input.tag.get_property("DRAW_OBJECT_BORDER", config.draw_object_border); + config.draw_replace_border = input.tag.get_property("DRAW_REPLACE_BORDER", config.draw_replace_border); config.object_layer = input.tag.get_property("OBJECT_LAYER", config.object_layer); config.replace_layer = input.tag.get_property("REPLACE_LAYER", config.replace_layer); config.scene_layer = input.tag.get_property("SCENE_LAYER", config.scene_layer); @@ -259,12 +316,45 @@ void FindObjMain::draw_line(VFrame *vframe, int x1, int y1, int x2, int y2) vframe->draw_line(x1, y1, x2, y2); } +void FindObjMain::draw_quad(VFrame *vframe, + int x1, int y1, int x2, int y2, + int x3, int y3, int x4, int y4) +{ + int r = bmin(vframe->get_w(), vframe->get_h()) / 200 + 1; + for( int i=r; --i>0; ) { + draw_line(vframe, x1+i, y1+i, x2, y2); + draw_line(vframe, x1-i, y1-i, x2, y2); + draw_line(vframe, x2+i, y2+i, x3, y3); + draw_line(vframe, x2-i, y2-i, x3, y3); + draw_line(vframe, x3+i, y3+i, x4, y4); + draw_line(vframe, x3-i, y3-i, x4, y4); + draw_line(vframe, x4+i, y4+i, x1, y1); + draw_line(vframe, x4-i, y4-i, x1, y1); + } + draw_line(vframe, x1, y1, x2, y2); + draw_line(vframe, x2, y2, x3, y3); + draw_line(vframe, x3, y3, x4, y4); + draw_line(vframe, x4, y4, x1, y1); +} + +void FindObjMain::draw_point(VFrame *vframe, int x1, int y1) +{ + int r = bmin(vframe->get_w(), vframe->get_h()) / 200 + 1; + for( int i=r; --i>0; ) + draw_circle(vframe, x1, y1, i); +} + void FindObjMain::draw_rect(VFrame *vframe, int x1, int y1, int x2, int y2) { - draw_line(vframe, x1, y1, x2, y1); - draw_line(vframe, x2, y1 + 1, x2, y2); - draw_line(vframe, x2 - 1, y2, x1, y2); - draw_line(vframe, x1, y2 - 1, x1, y1 + 1); + int r = bmin(vframe->get_w(), vframe->get_h()) / 200 + 1; + for( int i=r; --i>0; ) { + --x2; --y2; + draw_line(vframe, x1, y1, x2, y1); + draw_line(vframe, x2, y1, x2, y2); + draw_line(vframe, x2, y2, x1, y2); + draw_line(vframe, x1, y2, x1, y1); + ++x1; ++y1; + } } void FindObjMain::draw_circle(VFrame *vframe, int x, int y, int r) @@ -404,12 +494,10 @@ void FindObjMain::set_brisk() } #endif + void FindObjMain::process_match() { if( config.algorithm == NO_ALGORITHM ) return; - if( !config.replace_object && - !config.draw_border && - !config.draw_keypoints ) return; if( detector.empty() ) { switch( config.algorithm ) { @@ -449,22 +537,167 @@ void FindObjMain::process_match() } ptV src, dst; - float obj_x1 = 0, obj_x2 = object_w; - float obj_y1 = 0, obj_y2 = object_h; - src.push_back(Point2f(obj_x1,obj_y1)); - src.push_back(Point2f(obj_x2,obj_y1)); - src.push_back(Point2f(obj_x2,obj_y2)); - src.push_back(Point2f(obj_x1,obj_y2)); + float out_x1 = 0, out_x2 = object_w; + float out_y1 = 0, out_y2 = object_h; + src.push_back(Point2f(out_x1,out_y1)); + src.push_back(Point2f(out_x2,out_y1)); + src.push_back(Point2f(out_x2,out_y2)); + src.push_back(Point2f(out_x1,out_y2)); perspectiveTransform(src, dst, H); - border_x1 = dst[0].x + scene_x; border_y1 = dst[0].y + scene_y; - border_x2 = dst[1].x + scene_x; border_y2 = dst[1].y + scene_y; - border_x3 = dst[2].x + scene_x; border_y3 = dst[2].y + scene_y; - border_x4 = dst[3].x + scene_x; border_y4 = dst[3].y + scene_y; -//printf("src %f,%f %f,%f %f,%f %f,%f\n", -// src[0].x,src[0].y, src[1].x,src[1].y, src[2].x,src[2].y, src[3].x,src[3].y); -//printf("dst %f,%f %f,%f %f,%f %f,%f\n", -// dst[0].x,dst[0].y, dst[1].x,dst[1].y, dst[2].x,dst[2].y, dst[3].x,dst[3].y); + match_x1 = dst[0].x + scene_x; match_y1 = dst[0].y + scene_y; + match_x2 = dst[1].x + scene_x; match_y2 = dst[1].y + scene_y; + match_x3 = dst[2].x + scene_x; match_y3 = dst[2].y + scene_y; + match_x4 = dst[3].x + scene_x; match_y4 = dst[3].y + scene_y; +} + + +static double area(float x1, float y1, float x2, float y2, + float x3, float y3, float x4, float y4) +{ // quadrelateral area, sign is +ccw,-cw, use abs + double dx1 = x3-x1, dy1 = y3-y1; + double dx2 = x4-x2, dy2 = y4-y2; + return 0.5 * (dx1 * dy2 - dx2 * dy1); +} +static double dist(float x1,float y1, float x2, float y2) +{ + double dx = x2-x1, dy = y2-y1; + return sqrt(dx*dx + dy*dy); +} +static int intersects(double x1, double y1, double x2, double y2, + double x3, double y3, double x4, double y4) +{ + double dx12 = x2 - x1, dy12 = y2 - y1; + double dx34 = x4 - x3, dy34 = y4 - y3; + double d = dx12*dy34 - dx34*dy12; + if( !d ) return 0; // parallel + double dx13 = x3 - x1, dy13 = y3 - y1; + double u = (dx13*dy34 - dx34*dy13) / d; + if( u < 0 || u > 1 ) return 0; + double v = (dx13*dy12 - dx12*dy13) / d; + if( v < 0 || v > 1 ) return 0; + return 1; +} + +/* + * 4---------3 1---------2 + * |0,h w,h| |0,0 w,0| + * | + | | + | + * |0,0 w,0| |0,h w,h| + * 1---------2 1---------2 + * pt locations screen pts + */ +void FindObjMain::reshape() +{ + if( config.mode == MODE_NONE ) return; + const double pi = M_PI; + double x1 = match_x1, y1 = match_y1; + double x2 = match_x2, y2 = match_y2; + double x3 = match_x3, y3 = match_y3; + double x4 = match_x4, y4 = match_y4; + double ia = area(x1,y1, x2,y2, x3,y3, x4,y4); +// centroid + double cx = (x1 + x2 + x3 + x4) / 4; + double cy = (y1 + y2 + y3 + y4) / 4; +// centered + x1 -= cx; x2 -= cx; x3 -= cx; x4 -= cx; + y1 -= cy; y2 -= cy; y3 -= cy; y4 -= cy; +// bowtied + if( intersects(x1,y1, x2,y2, x3,y3, x4,y4) ) { + double x = x2, y = y2; + x2 = x3; y2 = y3; + x3 = x; y3 = y; + } + else if( intersects(x1,y1, x4,y4, x3,y3, x2,y2) ) { + double x = x4, y = y4; + x4 = x3; y4 = y3; + x3 = x; y3 = y; + } + +// rotation, if mode is quad: reverse rotate + double r = 0; + if( (config.mode == MODE_QUADRILATERAL) ^ (config.rotate != 0) ) { +// edge centers + double cx12 = (x1 + x2) / 2, cy12 = (y1 + y2) / 2; + double cx23 = (x2 + x3) / 2, cy23 = (y2 + y3) / 2; + double cx34 = (x3 + x4) / 2, cy34 = (y3 + y4) / 2; + double cx41 = (x4 + x1) / 2, cy41 = (y4 + y1) / 2; + double vx = cx34 - cx12, vy = cy34 - cy12; + double hx = cx23 - cx41, hy = cy23 - cy41; + double v = atan2(vy, vx); + double h = atan2(hy, hx); + r = (h + v - pi/2) / 2; + if( config.mode != MODE_QUADRILATERAL ) r = -r; + } +// diagonal length + double a = dist(x1,y1, x3,y3) / 2; + double b = dist(x2,y2, x4,y4) / 2; + if( config.mode == MODE_SQUARE || + config.mode == MODE_RECTANGLE ) + a = b = (a + b) / 2; +// central angles + double a1 = atan2(y1, x1); + double a2 = atan2(y2, x2); + double a3 = atan2(y3, x3); + double a4 = atan2(y4, x4); +// edge angles + double a12 = a2 - a1, a23 = a3 - a2; + double a34 = a4 - a3, a41 = a1 - a4; + double dt = (a12 - a23 + a34 - a41)/4; +// mirrored + if( ia < 0 ) { ia = -ia; dt = -dt; r = -r; } + switch( config.mode ) { + case MODE_SQUARE: + case MODE_RHOMBUS: + dt = pi/2; + case MODE_RECTANGLE: + case MODE_PARALLELOGRAM: { + double t = -(pi+dt)/2; + x1 = a*cos(t); y1 = a*sin(t); t += dt; + x2 = b*cos(t); y2 = b*sin(t); t += pi - dt; + x3 = a*cos(t); y3 = a*sin(t); t += dt; + x4 = b*cos(t); y4 = b*sin(t); } + case MODE_QUADRILATERAL: + break; + } +// aspect + if( !config.aspect ) { + double cx12 = (x1 + x2) / 2, cy12 = (y1 + y2) / 2; + double cx23 = (x2 + x3) / 2, cy23 = (y2 + y3) / 2; + double cx34 = (x3 + x4) / 2, cy34 = (y3 + y4) / 2; + double cx41 = (x4 + x1) / 2, cy41 = (y4 + y1) / 2; + double iw = dist(cx41,cy41, cx23,cy23); + double ih = dist(cx12,cy12, cx34,cy34); + double ow = object_w, oh = object_h; + double sx = iw && ih ? sqrt((ih*ow)/(iw*oh)) : 1; + double sy = sx ? 1 / sx : 1; + x1 *= sx; x2 *= sx; x3 *= sx; x4 *= sx; + y1 *= sy; y2 *= sy; y3 *= sy; y4 *= sy; + } +// rotation + if( r ) { + double ct = cos(r), st = sin(r), x, y; + x = x1*ct + y1*st; y = y1*ct - x1*st; x1 = x; y1 = y; + x = x2*ct + y2*st; y = y2*ct - x2*st; x2 = x; y2 = y; + x = x3*ct + y3*st; y = y3*ct - x3*st; x3 = x; y3 = y; + x = x4*ct + y4*st; y = y4*ct - x4*st; x4 = x; y4 = y; + } +// scaling + ia = !config.scale ? object_w * object_h : ia; + double oa = abs(area(x1,y1, x2,y2, x3,y3, x4,y4)); + double sf = oa ? sqrt(ia / oa) : 0; + x1 *= sf; x2 *= sf; x3 *= sf; x4 *= sf; + y1 *= sf; y2 *= sf; y3 *= sf; y4 *= sf; +// translation + double ox = !config.translate ? object_x + object_w/2. : cx; + double oy = !config.translate ? object_y + object_h/2. : cy; + x1 += ox; x2 += ox; x3 += ox; x4 += ox; + y1 += oy; y2 += oy; y3 += oy; y4 += oy; + + shape_x1 = x1; shape_y1 = y1; + shape_x2 = x2; shape_y2 = y2; + shape_x3 = x3; shape_y3 = y3; + shape_x4 = x4; shape_y4 = y4; } int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double frame_rate) @@ -481,34 +714,33 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f matcher.release(); } - w = frame[0]->get_w(); - h = frame[0]->get_h(); - object_layer = config.object_layer; scene_layer = config.scene_layer; replace_layer = config.replace_layer; + Track *track = server->plugin->track; + w = track->track_w; + h = track->track_h; int max_layer = PluginClient::get_total_buffers() - 1; object_layer = bclip(config.object_layer, 0, max_layer); scene_layer = bclip(config.scene_layer, 0, max_layer); replace_layer = bclip(config.replace_layer, 0, max_layer); - int cfg_w, cfg_h, cfg_x1, cfg_y1, cfg_x2, cfg_y2; - cfg_w = (int)(config.object_w * w / 100); - cfg_h = (int)(config.object_h * h / 100); - cfg_x1 = (int)(config.object_x * w / 100 - cfg_w / 2); - cfg_y1 = (int)(config.object_y * h / 100 - cfg_h / 2); - cfg_x2 = cfg_x1 + cfg_w; - cfg_y2 = cfg_y1 + cfg_h; + int cfg_w = (int)(w * config.object_w / 100.); + int cfg_h = (int)(h * config.object_h / 100.); + int cfg_x1 = (int)(w * config.object_x / 100. - cfg_w / 2); + int cfg_y1 = (int)(h * config.object_y / 100. - cfg_h / 2); + int cfg_x2 = cfg_x1 + cfg_w; + int cfg_y2 = cfg_y1 + cfg_h; bclamp(cfg_x1, 0, w); object_x = cfg_x1; bclamp(cfg_y1, 0, h); object_y = cfg_y1; bclamp(cfg_x2, 0, w); object_w = cfg_x2 - cfg_x1; bclamp(cfg_y2, 0, h); object_h = cfg_y2 - cfg_y1; - cfg_w = (int)(config.scene_w * w / 100); - cfg_h = (int)(config.scene_h * h / 100); - cfg_x1 = (int)(config.scene_x * w / 100 - cfg_w / 2); - cfg_y1 = (int)(config.scene_y * h / 100 - cfg_h / 2); + cfg_w = (int)(w * config.scene_w / 100.); + cfg_h = (int)(h * config.scene_h / 100.); + cfg_x1 = (int)(w * config.scene_x / 100. - cfg_w / 2); + cfg_y1 = (int)(h * config.scene_y / 100. - cfg_h / 2); cfg_x2 = cfg_x1 + cfg_w; cfg_y2 = cfg_y1 + cfg_h; bclamp(cfg_x1, 0, w); scene_x = cfg_x1; @@ -516,6 +748,22 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f bclamp(cfg_x2, 0, w); scene_w = cfg_x2 - cfg_x1; bclamp(cfg_y2, 0, h); scene_h = cfg_y2 - cfg_y1; + cfg_w = (int)(w * config.replace_w / 100.); + cfg_h = (int)(h * config.replace_h / 100.); + cfg_x1 = (int)(w * config.replace_x / 100. - cfg_w / 2); + cfg_y1 = (int)(h * config.replace_y / 100. - cfg_h / 2); + cfg_x2 = cfg_x1 + cfg_w; + cfg_y2 = cfg_y1 + cfg_h; + bclamp(cfg_x1, 0, w); replace_x = cfg_x1; + bclamp(cfg_y1, 0, h); replace_y = cfg_y1; + bclamp(cfg_x2, 0, w); replace_w = cfg_x2 - cfg_x1; + bclamp(cfg_y2, 0, h); replace_h = cfg_y2 - cfg_y1; + + int cfg_dx = (int)(w * config.replace_dx / 100.); + int cfg_dy = (int)(h * config.replace_dy / 100.); + bclamp(cfg_dx, -h, h); replace_dx = cfg_dx; + bclamp(cfg_dy, -w, w); replace_dy = cfg_dy; + // Read in the input frames for( int i = 0; i < PluginClient::get_total_buffers(); i++ ) { read_frame(frame[i], i, start_position, frame_rate, 0); @@ -525,21 +773,22 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f scene = frame[scene_layer]; replace = frame[replace_layer]; - border_x1 = obj_x1; border_y1 = obj_y1; - border_x2 = obj_x2; border_y2 = obj_y2; - border_x3 = obj_x3; border_y3 = obj_y3; - border_x4 = obj_x4; border_y4 = obj_y4; + shape_x1 = out_x1; shape_y1 = out_y1; + shape_x2 = out_x2; shape_y2 = out_y2; + shape_x3 = out_x3; shape_y3 = out_y3; + shape_x4 = out_x4; shape_y4 = out_y4; if( scene_w > 0 && scene_h > 0 && object_w > 0 && object_h > 0 ) { process_match(); + reshape(); } double w0 = init_border ? 1. : config.blend/100., w1 = 1. - w0; - obj_x1 = border_x1*w0 + obj_x1*w1; obj_y1 = border_y1*w0 + obj_y1*w1; - obj_x2 = border_x2*w0 + obj_x2*w1; obj_y2 = border_y2*w0 + obj_y2*w1; - obj_x3 = border_x3*w0 + obj_x3*w1; obj_y3 = border_y3*w0 + obj_y3*w1; - obj_x4 = border_x4*w0 + obj_x4*w1; obj_y4 = border_y4*w0 + obj_y4*w1; - + init_border = 0; + out_x1 = shape_x1*w0 + out_x1*w1; out_y1 = shape_y1*w0 + out_y1*w1; + out_x2 = shape_x2*w0 + out_x2*w1; out_y2 = shape_y2*w0 + out_y2*w1; + out_x3 = shape_x3*w0 + out_x3*w1; out_y3 = shape_y3*w0 + out_y3*w1; + out_x4 = shape_x4*w0 + out_x4*w1; out_y4 = shape_y4*w0 + out_y4*w1; // Replace object in the scene layer if( config.replace_object ) { int cpus1 = get_project_smp() + 1; @@ -547,32 +796,48 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f affine = new AffineEngine(cpus1, cpus1); if( !overlayer ) overlayer = new OverlayFrame(cpus1); - - VFrame *temp = new_temp(scene->get_w(), scene->get_h(), scene->get_color_model()); + VFrame *temp = new_temp(w, h, scene->get_color_model()); temp->clear_frame(); - float sx = 100./w, sy = 100./h; - float x1 = sx * obj_x1, y1 = sy * obj_y1; - float x2 = sx * obj_x2, y2 = sy * obj_y2; - float x3 = sx * obj_x3, y3 = sy * obj_y3; - float x4 = sx * obj_x4, y4 = sy * obj_y4; - affine->process(temp, replace, 0, AffineEngine::PERSPECTIVE, - x1,y1, x2,y2, x3,y3, x4,y4, 1); + affine->set_in_viewport(replace_x, replace_y, replace_w, replace_h); + float ix1 = replace_x, ix2 = ix1 + replace_w; + float iy1 = replace_y, iy2 = iy1 + replace_h; + float dx = replace_dx, dy = replace_dy; + float ox1 = out_x1+dx, ox2 = out_x2+dx, ox3 = out_x3+dx, ox4 = out_x4+dx; + float oy1 = out_y1-dy, oy2 = out_y2-dy, oy3 = out_y3-dy, oy4 = out_y4-dy; + affine->set_matrix(ix1,iy1, ix2,iy2, ox1,oy1, ox2,oy2, ox4,oy4, ox3,oy3); + affine->process(temp, replace, 0, + AffineEngine::TRANSFORM, 0,0, 100,0, 100,100, 0,100, 1); overlayer->overlay(scene, temp, 0,0, w,h, 0,0, w,h, 1, TRANSFER_NORMAL, NEAREST_NEIGHBOR); } - if( config.draw_border ) { - int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1; - scene->set_pixel_color(WHITE); scene->set_stiple(ss*2); - draw_line(scene, obj_x1, obj_y1, obj_x2, obj_y2); - draw_line(scene, obj_x2, obj_y2, obj_x3, obj_y3); - draw_line(scene, obj_x3, obj_y3, obj_x4, obj_y4); - draw_line(scene, obj_x4, obj_y4, obj_x1, obj_y1); + int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1; + if( config.draw_scene_border ) { + scene->set_stiple(ss*2); + scene->set_pixel_color(WHITE); + draw_rect(scene, scene_x, scene_y, scene_x+scene_w, scene_y+scene_h); } - + if( config.draw_object_border ) { + scene->set_stiple(ss*3); + scene->set_pixel_color(YELLOW); + draw_rect(scene, object_x, object_y, object_x+object_w, object_y+object_h); + } + if( config.draw_replace_border ) { + scene->set_stiple(ss*3); + scene->set_pixel_color(GREEN); + draw_rect(scene, replace_x, replace_y, replace_x+replace_w, replace_y+replace_h); + } + scene->set_stiple(0); if( config.draw_keypoints ) { - scene->set_pixel_color(RED); scene->set_stiple(0); + scene->set_pixel_color(GREEN); + for( int i=0,n=obj_keypts.size(); iset_pixel_color(RED); for( int i=0,n=scn_keypts.size(); iset_pixel_color(BLUE); + draw_quad(scene, match_x1, match_y1, match_x2, match_y2, + match_x3, match_y3, match_x4, match_y4); + scene->set_pixel_color(LTGREEN); + draw_point(scene, match_x1, match_y1); + } -// Draw object outline in the object layer - if( config.draw_object_border ) { - int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1; - scene->set_pixel_color(YELLOW); scene->set_stiple(ss*3); - int x1 = object_x, x2 = x1 + object_w - 1; - int y1 = object_y, y2 = y1 + object_h - 1; - draw_rect(scene, x1, y1, x2, y2); - scene->set_pixel_color(GREEN); scene->set_stiple(0); - x1 = scene_x, x2 = x1 + scene_w - 1; - y1 = scene_y, y2 = y1 + scene_h - 1; - draw_rect(scene, x1, y1, x2, y2); + if( gui_open() ) { + if( config.drag_scene ) { + scene->set_pixel_color(WHITE); + DragCheckBox::draw_boundary(scene, scene_x, scene_y, scene_w, scene_h); + } + if( config.drag_object ) { + scene->set_pixel_color(YELLOW); + DragCheckBox::draw_boundary(scene, object_x, object_y, object_w, object_h); + } + if( config.drag_replace ) { + scene->set_pixel_color(GREEN); + DragCheckBox::draw_boundary(scene, replace_x, replace_y, replace_w, replace_h); + } } scene->set_pixel_color(BLACK);