From: Good Guy Date: Mon, 23 Apr 2018 22:17:17 +0000 (-0600) Subject: findobj mode/xlat/scale/rotate, save backup shortcut, undo limit bug, title boundary... X-Git-Url: https://git.cinelerra-gg.org/git/?a=commitdiff_plain;h=a94468d6de897136e77c70662177f4b8b4454b6b;p=goodguy%2Fhistory.git findobj mode/xlat/scale/rotate, save backup shortcut, undo limit bug, title boundary fraction fix, shmmni as user fix --- diff --git a/cinelerra-5.1/cinelerra/affine.C b/cinelerra-5.1/cinelerra/affine.C index 2842f990..a59d6e3e 100644 --- a/cinelerra-5.1/cinelerra/affine.C +++ b/cinelerra-5.1/cinelerra/affine.C @@ -145,6 +145,38 @@ void AffineMatrix::copy_from(AffineMatrix *src) memcpy(&values[0][0], &src->values[0][0], sizeof(values)); } +void AffineMatrix::set_matrix( + double in_x1, double in_y1, double in_x2, double in_y2, + double out_x1, double out_y1, double out_x2, double out_y2, + double out_x3, double out_y3, double out_x4, double out_y4) +{ + double scalex = in_x2 > in_x1 ? 1./(in_x2 - in_x1) : 1.0; + double scaley = in_y2 > in_y1 ? 1./(in_y2 - in_y1) : 1.0; + double dx1 = out_x2 - out_x4, dx2 = out_x3 - out_x4; + double dx3 = out_x1 - out_x2 + out_x4 - out_x3; + + double dy1 = out_y2 - out_y4, dy2 = out_y3 - out_y4; + double dy3 = out_y1 - out_y2 + out_y4 - out_y3; + double det = dx1 * dy2 - dy1 * dx2; + if( !det ) { identity(); return; } + + AffineMatrix m; + m.values[2][0] = (dx3 * dy2 - dy3 * dx2) / det; + m.values[2][1] = (dx1 * dy3 - dy1 * dx3) / det; + m.values[0][0] = out_x2 - out_x1 + m.values[2][0] * out_x2; + m.values[0][1] = out_x3 - out_x1 + m.values[2][1] * out_x3; + m.values[0][2] = out_x1; + m.values[1][0] = out_y2 - out_y1 + m.values[2][0] * out_y2; + m.values[1][1] = out_y3 - out_y1 + m.values[2][1] * out_y3; + m.values[1][2] = out_y1; + m.values[2][2] = 1.0; + + identity(); + translate(-in_x1, -in_y1); + scale(scalex, scaley); + m.multiply(this); +} + void AffineMatrix::transform_point(float x, float y, float *newx, @@ -186,91 +218,6 @@ AffineUnit::AffineUnit(AffineEngine *server) } - - - - - - - -void AffineUnit::calculate_matrix( - double in_x1, double in_y1, double in_x2, double in_y2, - double out_x1, double out_y1, double out_x2, double out_y2, - double out_x3, double out_y3, double out_x4, double out_y4, - AffineMatrix *result) -{ - AffineMatrix matrix; - double scalex; - double scaley; - - scalex = scaley = 1.0; - - if( (in_x2 - in_x1) > 0 ) - scalex = 1.0 / (double)(in_x2 - in_x1); - - if( (in_y2 - in_y1) > 0 ) - scaley = 1.0 / (double)(in_y2 - in_y1); - -/* Determine the perspective transform that maps from - * the unit cube to the transformed coordinates - */ - double dx1, dx2, dx3, dy1, dy2, dy3; - double det1, det2; - - dx1 = out_x2 - out_x4; - dx2 = out_x3 - out_x4; - dx3 = out_x1 - out_x2 + out_x4 - out_x3; - - dy1 = out_y2 - out_y4; - dy2 = out_y3 - out_y4; - dy3 = out_y1 - out_y2 + out_y4 - out_y3; -// printf("AffineUnit::calculate_matrix %f %f %f %f %f %f\n", -// dx1, dx2, dx3, dy1, dy2, dy3 ); - -/* Is the mapping affine? */ - if((dx3 == 0.0) && (dy3 == 0.0)) { - matrix.values[0][0] = out_x2 - out_x1; - matrix.values[0][1] = out_x4 - out_x2; - matrix.values[0][2] = out_x1; - matrix.values[1][0] = out_y2 - out_y1; - matrix.values[1][1] = out_y4 - out_y2; - matrix.values[1][2] = out_y1; - matrix.values[2][0] = 0.0; - matrix.values[2][1] = 0.0; - } - else { - det1 = dx3 * dy2 - dy3 * dx2; - det2 = dx1 * dy2 - dy1 * dx2; - matrix.values[2][0] = det1 / det2; - det1 = dx1 * dy3 - dy1 * dx3; - det2 = dx1 * dy2 - dy1 * dx2; - matrix.values[2][1] = det1 / det2; - - matrix.values[0][0] = out_x2 - out_x1 + matrix.values[2][0] * out_x2; - matrix.values[0][1] = out_x3 - out_x1 + matrix.values[2][1] * out_x3; - matrix.values[0][2] = out_x1; - - matrix.values[1][0] = out_y2 - out_y1 + matrix.values[2][0] * out_y2; - matrix.values[1][1] = out_y3 - out_y1 + matrix.values[2][1] * out_y3; - matrix.values[1][2] = out_y1; - } - - matrix.values[2][2] = 1.0; - -// printf("AffineUnit::calculate_matrix 1 %f %f\n", dx3, dy3); -// matrix.dump(); - - result->identity(); - result->translate(-in_x1, -in_y1); - result->scale(scalex, scaley); - matrix.multiply(result); -// double test[3][3] = -// { { 0.0896, 0.0, 0.0 }, { 0.0, 0.0896, 0.0 }, { -0.00126, 0.0, 1.0 } }; -// memcpy(&result->values[0][0], test, sizeof(test)); -// printf("AffineUnit::calculate_matrix 4 %p\n", result); -// result->dump(); -} - static inline float transform_cubic(float dx, float p0, float p1, float p2, float p3) { @@ -410,12 +357,11 @@ void AffineUnit::process_package(LoadPackage *package) if( server->mode != AffineEngine::TRANSFORM ) { - calculate_matrix( server->in_x, server->in_y, + matrix.set_matrix(server->in_x, server->in_y, server->in_x + server->in_w, server->in_y + server->in_h, out_x1, out_y1, out_x2, out_y2, - out_x3, out_y3, out_x4, out_y4, - &matrix); + out_x3, out_y3, out_x4, out_y4); } else { matrix.copy_from(&server->matrix); @@ -815,7 +761,14 @@ void AffineEngine::process(VFrame *output, VFrame *input, VFrame *temp, int mode } } - +void AffineEngine::set_matrix( + double in_x1, double in_y1, double in_x2, double in_y2, + double out_x1, double out_y1, double out_x2, double out_y2, + double out_x3, double out_y3, double out_x4, double out_y4) +{ + matrix.set_matrix(in_x1, in_y1, in_x2, in_y2, + out_x1, out_y1, out_x2, out_y2, out_x3, out_y3, out_x4, out_y4); +} void AffineEngine::rotate(VFrame *output, @@ -903,49 +856,6 @@ void AffineEngine::rotate(VFrame *output, } } -void AffineEngine::set_matrix(AffineMatrix *matrix) -{ - for( int i=0; i<3; ++i ) { - for( int j=0; j<3; ++j ) { - this->matrix.values[i][j] = matrix->values[i][j]; - } - } -} - -// in x1,y1 - x2,y1 out x1,y1 - x2,y2 clockwise -// | | | | -// x1,y2 - x2,y2 x4,y4 - x3,y3 -void AffineEngine::set_matrix( - double in_x1, double in_y1, double in_x2, double in_y2, - double out_x1, double out_y1, double out_x2, double out_y2, - double out_x3, double out_y3, double out_x4, double out_y4) -{ - AffineMatrix m; - double in_w = in_x2 - in_x1, scalex = in_w > 0 ? 1./in_w : 1.0; - double in_h = in_y2 - in_y1, scaley = in_h > 0 ? 1./in_h : 1.0; - double dx1 = out_x2 - out_x3; - double dy1 = out_y2 - out_y3; - double dx2 = out_x4 - out_x3; - double dy2 = out_y4 - out_y3; - double dx3 = out_x1 - out_x2 + out_x3 - out_x4; - double dy3 = out_y1 - out_y2 + out_y3 - out_y4; - double det = dx1 * dy2 - dy1 * dx2; - m.values[2][0] = det ? (dx3 * dy2 - dy3 * dx2) / det : 0; - m.values[2][1] = det ? (dx1 * dy3 - dy1 * dx3) / det : 0; - m.values[2][2] = 1.0; - m.values[0][0] = out_x2 - out_x1 + matrix.values[2][0] * out_x2; - m.values[0][1] = out_x4 - out_x1 + matrix.values[2][1] * out_x4; - m.values[0][2] = out_x1; - m.values[1][0] = out_y2 - out_y1 + matrix.values[2][0] * out_y2; - m.values[1][1] = out_y4 - out_y1 + matrix.values[2][1] * out_y4; - m.values[1][2] = out_y1; - matrix.identity(); - matrix.translate(-in_x1, -in_y1); - matrix.scale(scalex, scaley); - m.multiply(&matrix); -} - - void AffineEngine::set_in_viewport(int x, int y, int w, int h) { this->in_x = x; this->in_y = y; diff --git a/cinelerra-5.1/cinelerra/affine.h b/cinelerra-5.1/cinelerra/affine.h index be74d572..1740d905 100644 --- a/cinelerra-5.1/cinelerra/affine.h +++ b/cinelerra-5.1/cinelerra/affine.h @@ -42,6 +42,11 @@ public: void multiply(AffineMatrix *dst); void copy_from(AffineMatrix *src); void invert(AffineMatrix *dst); +// in x1,y1 x2,y1 out x1,y1 x2,y2 +// x1,y2 x2,y2 x3,y3 x4,y4 + void set_matrix(double in_x1, double in_y1, double in_x2, double in_y2, + double out_x1, double out_y1, double out_x2, double out_y2, + double out_x3, double out_y3, double out_x4, double out_y4); void transform_point(float x, float y, float *newx, float *newy); double determinant(); void dump(); @@ -60,20 +65,6 @@ class AffineUnit : public LoadClient public: AffineUnit(AffineEngine *server); void process_package(LoadPackage *package); - void calculate_matrix( - double in_x1, - double in_y1, - double in_x2, - double in_y2, - double out_x1, - double out_y1, - double out_x2, - double out_y2, - double out_x3, - double out_y3, - double out_x4, - double out_y4, - AffineMatrix *result); // float transform_cubic(float dx, float jm1, float j, float jp1, float jp2); AffineEngine *server; }; @@ -90,18 +81,13 @@ public: float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int forward); + void set_matrix( + double in_x1, double in_y1, double in_x2, double in_y2, + double out_x1, double out_y1, double out_x2, double out_y2, + double out_x3, double out_y3, double out_x4, double out_y4); // Do rotation with the affine/perspective transform. // This removes some of the extremely faint artifacts in the trig rotation. void rotate(VFrame *output, VFrame *input, float angle); - void set_matrix(AffineMatrix *matrix); -// set_matrix: -// in x1,y1 - x2,y1 out x1,y1 - x2,y2 clockwise -// | | | | -// x1,y2 - x2,y2 x4,y4 - x3,y3 -// - void set_matrix( double in_x1, double in_y1, double in_x2, double in_y2, - double out_x1, double out_y1, double out_x2, double out_y2, - double out_x3, double out_y3, double out_x4, double out_y4); // Set the viewport to transform. The transform is based on the input viewport. // The output viewport clips the transformed output. void set_in_viewport(int x, int y, int w, int h); diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C index 202a7687..6150f954 100644 --- a/cinelerra-5.1/cinelerra/mwindow.C +++ b/cinelerra-5.1/cinelerra/mwindow.C @@ -2275,10 +2275,9 @@ void MWindow::init_shm(const char *pfn, int64_t min) } fd = fopen(pfn, "w"); - if( fd ) { - fprintf(fd, "0x%jx", min); - fclose(fd); - } + if( !fd ) return; + fprintf(fd, "0x%jx", min); + fclose(fd); fd = fopen(pfn, "r"); if( !fd ) { diff --git a/cinelerra-5.1/cinelerra/savefile.C b/cinelerra-5.1/cinelerra/savefile.C index fc757cec..b38aec14 100644 --- a/cinelerra-5.1/cinelerra/savefile.C +++ b/cinelerra-5.1/cinelerra/savefile.C @@ -46,7 +46,7 @@ SaveBackup::SaveBackup(MWindow *mwindow) - : BC_MenuItem(_("Save backup")) + : BC_MenuItem(_("Save backup"), "b", 'b') { this->mwindow = mwindow; } diff --git a/cinelerra-5.1/cinelerra/undostack.C b/cinelerra-5.1/cinelerra/undostack.C index 59eadada..23f33bc1 100644 --- a/cinelerra-5.1/cinelerra/undostack.C +++ b/cinelerra-5.1/cinelerra/undostack.C @@ -27,6 +27,9 @@ #include "undostack.h" #include +// undo can be incremental or direct, from key to current +//#define UNDO_INCREMENTAL + UndoStack::UndoStack() : List() { current = 0; @@ -55,37 +58,30 @@ UndoStackItem *UndoStack::get_current_redo() UndoStackItem* UndoStack::push() { -// current is only 0 if before first undo - if( current ) - current = insert_after(current); - else - current = insert_before(first); - -// delete future undos if necessary - if( current && current->next ) { - while( current->next ) remove(last); - } - // delete oldest 2 undos if necessary if( total() > UNDOLEVELS ) { - for( int i=0; i<2; ++i ) { - UndoStackItem *second = first->next; - char *temp_data = 0; - - - if( !second->is_key() ) { - temp_data = second->get_data(); - } - remove(first); - -// Convert new first to key buffer. - if( !second->is_key() ) { - second->set_data(temp_data); - } - delete [] temp_data; + UndoStackItem *item = first, *key = item; +#ifdef UNDO_INCREMENTAL + for( int i=2; --i>=0; item=item->next ); +#else + for( int i=2; --i>=0; item=item->next ) + if( item->is_key() ) key = item; +#endif + char *data = !item->is_key() ? key->get_data() : 0; + while( first != item ) { + if( current == first ) current = first->next; + delete first; + } + if( data ) { + item->set_data(data); + delete [] data; } } +// current is only 0 if before first undo + current = current ? insert_after(current) : insert_before(first); +// delete future undos if necessary + while( current->next ) remove(last); return current; } @@ -120,9 +116,6 @@ void UndoStack::dump(FILE *fp) } } -// undo can be incremental or direct, from key to current -//#define UNDO_INCREMENTAL - class undo_record { public: int32_t new_ofs; diff --git a/cinelerra-5.1/guicast/test4.C b/cinelerra-5.1/guicast/test4.C index 114ed49a..522b8441 100644 --- a/cinelerra-5.1/guicast/test4.C +++ b/cinelerra-5.1/guicast/test4.C @@ -107,7 +107,7 @@ void write_ppm(uint8_t *tp, int w, int h, const char *fmt, ...) if( fp ) { fprintf(fp,"P6\n%d %d\n255\n",w,h); fwrite(tp,3*w,h,fp); - fclose(fp); + if( fp != sdtout ) fclose(fp); } } diff --git a/cinelerra-5.1/plugins/findobj/findobj.C b/cinelerra-5.1/plugins/findobj/findobj.C index 7909170a..24c67cf8 100644 --- a/cinelerra-5.1/plugins/findobj/findobj.C +++ b/cinelerra-5.1/plugins/findobj/findobj.C @@ -46,6 +46,10 @@ void FindObjConfig::reset() { algorithm = NO_ALGORITHM; use_flann = 1; + mode = MODE_QUADRILATERAL; + scale = 1; + translate = 1; + rotate = 1; draw_keypoints = 0; draw_scene_border = 0; replace_object = 0; @@ -84,6 +88,10 @@ int FindObjConfig::equivalent(FindObjConfig &that) int result = algorithm == that.algorithm && use_flann == that.use_flann && + mode == that.mode && + scale == that.scale && + translate == that.translate && + rotate == that.rotate && draw_keypoints == that.draw_keypoints && draw_scene_border == that.draw_scene_border && replace_object == that.replace_object && @@ -110,6 +118,10 @@ void FindObjConfig::copy_from(FindObjConfig &that) { algorithm = that.algorithm; use_flann = that.use_flann; + mode = that.mode; + scale = that.scale; + translate = that.translate; + rotate = that.rotate; draw_keypoints = that.draw_keypoints; draw_scene_border = that.draw_scene_border; replace_object = that.replace_object; @@ -201,6 +213,10 @@ 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("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); @@ -246,6 +262,10 @@ 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.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); @@ -429,12 +449,10 @@ void FindObjMain::set_brisk() } #endif + void FindObjMain::process_match() { if( config.algorithm == NO_ALGORITHM ) return; - if( !config.replace_object && - !config.draw_scene_border && - !config.draw_keypoints ) return; if( detector.empty() ) { switch( config.algorithm ) { @@ -482,16 +500,116 @@ void FindObjMain::process_match() src.push_back(Point2f(obj_x1,obj_y2)); perspectiveTransform(src, dst, H); - float dx = scene_x + replace_dx; - float dy = scene_y + replace_dy; - border_x1 = dst[0].x + dx; border_y1 = dst[0].y + dy; - border_x2 = dst[1].x + dx; border_y2 = dst[1].y + dy; - border_x3 = dst[2].x + dx; border_y3 = dst[2].y + dy; - border_x4 = dst[3].x + dx; border_y4 = dst[3].y + dy; -//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); + border_x1 = dst[0].x; border_y1 = dst[0].y; + border_x2 = dst[1].x; border_y2 = dst[1].y; + border_x3 = dst[2].x; border_y3 = dst[2].y; + border_x4 = dst[3].x; border_y4 = dst[3].y; +} + + +static double area(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) +{ // quadrelateral area + double dx1 = x3-x1, dy1 = y3-y1; + double dx2 = x4-x2, dy2 = y4-y2; + return 0.5 * abs(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); +} + +/* + * 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 = border_x1, y1 = border_y1; + double x2 = border_x2, y2 = border_y2; + double x3 = border_x3, y3 = border_y3; + double x4 = border_x4, y4 = border_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; +// rotation, if mode is quad: reverse rotate + double r = 0; + if( (config.mode == MODE_QUADRILATERAL) ^ config.rotate ) { +// 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; + } +// 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; + 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; + } +// 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 + double ia = !config.scale ? object_w * object_h : + area(border_x1,border_y1, border_x2,border_y2, + border_x3,border_y3, border_x4,border_y4); + double oa = 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; + + border_x1 = x1; border_y1 = y1; + border_x2 = x2; border_y2 = y2; + border_x3 = x3; border_y3 = y3; + border_x4 = x4; border_y4 = y4; } int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double frame_rate) @@ -574,14 +692,15 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f if( scene_w > 0 && scene_h > 0 && object_w > 0 && object_h > 0 ) { process_match(); + reshape(); } - double w0 = init_border ? (init_border=0, 1.) : config.blend/100., w1 = 1. - w0; + double w0 = init_border ? 1. : config.blend/100., w1 = 1. - w0; + init_border = 0; 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; - // Replace object in the scene layer if( config.replace_object ) { int cpus1 = get_project_smp() + 1; @@ -592,13 +711,12 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f VFrame *temp = new_temp(w, h, scene->get_color_model()); temp->clear_frame(); affine->set_in_viewport(replace_x, replace_y, replace_w, replace_h); - int x1 = obj_x1, x2 = obj_x2, x3 = obj_x3, x4 = obj_x4; - int y1 = obj_y1, y2 = obj_y2, y3 = obj_y3, y4 = obj_y4; - bclamp(x1, 0, w); bclamp(x2, 0, w); bclamp(x3, 0, w); bclamp(x4, 0, w); - bclamp(y1, 0, h); bclamp(y2, 0, h); bclamp(y3, 0, h); bclamp(y4, 0, h); + float dx = replace_dx, dy = replace_dy; + float x1 = obj_x1+dx, x2 = obj_x2+dx, x3 = obj_x3+dx, x4 = obj_x4+dx; + float y1 = obj_y1-dy, y2 = obj_y2-dy, y3 = obj_y3-dy, y4 = obj_y4-dy; affine->set_matrix( replace_x, replace_y, replace_x+replace_w, replace_y+replace_h, - x1,y1, x2,y2, x3,y3, x4,y4); + x1,y1, x2,y2, x4,y4, x3,y3); 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, @@ -622,6 +740,13 @@ int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double f draw_rect(scene, replace_x, replace_y, replace_x+replace_w, replace_y+replace_h); } if( config.draw_keypoints ) { + scene->set_pixel_color(GREEN); scene->set_stiple(0); + for( int i=0,n=obj_keypts.size(); iset_pixel_color(RED); scene->set_stiple(0); for( int i=0,n=scn_keypts.size(); iget_w() + 10, y)); algorithm->create_objects(); - add_subwindow(reset = new FindObjReset(plugin, this, get_w() - 15, y)); + int x0 = get_w() - 15; + add_subwindow(reset = new FindObjReset(plugin, this, x0, y)); y += algorithm->get_h() + plugin->get_theme()->widget_border; add_subwindow(use_flann = new FindObjUseFlann(plugin, this, x, y)); - y += use_flann->get_h() + plugin->get_theme()->widget_border + 20; + x0 -= FindObjMode::calculate_w(this) + 30; + add_subwindow(mode = new FindObjMode(plugin, this, x0, y)); + mode->create_objects(); + x0 -= BC_Title::calculate_w(this, _("Mode:")) + 10; + add_subwindow(title = new BC_Title(x0, y, _("Mode:"))); + y += use_flann->get_h() + plugin->get_theme()->widget_border + 10; - int x0 = x + 200; + int y1 = y; + add_subwindow(scale = new FindObjScale(plugin, this, x3, y)); + y += scale->get_h() + 10; + add_subwindow(rotate = new FindObjRotate(plugin, this, x3, y)); + y += rotate->get_h() + 10; + add_subwindow(translate = new FindObjTranslate(plugin, this, x3, y)); + y += translate->get_h() + 10; + add_subwindow(replace_object = new FindObjReplace(plugin, this,x3, y)); + + x0 = x + 200; y = y1 + 10; add_subwindow(title = new BC_Title(x, y, _("Output/scene layer:"))); scene_layer = new FindObjLayer(plugin, this, x0, y, &plugin->config.scene_layer); @@ -79,7 +94,7 @@ void FindObjWindow::create_objects() add_subwindow(title = new BC_Title(x+15, y, _("Units: 0 to 100 percent"))); y += title->get_h(); - int y1 = y; + y1 = y; add_subwindow(title = new BC_Title(x1, y + 10, _("Scene X:"))); Track *track = plugin->server->plugin->track; int trk_w = track->track_w, trk_h = track->track_h; @@ -184,9 +199,6 @@ void FindObjWindow::create_objects() object_h_text->center = object_h; y = y1; - add_subwindow(replace_object = new FindObjReplace(plugin, this, - x3, y - title->get_h() - 15)); - add_subwindow(title = new BC_Title(x3, y + 10, _("Replace X:"))); drag_w = trk_w * plugin->config.replace_w / 100.; drag_h = trk_h * plugin->config.replace_h / 100.; @@ -322,6 +334,9 @@ void FindObjWindow::update_gui() FindObjConfig &conf = plugin->config; algorithm->update(conf.algorithm); use_flann->update(conf.use_flann); + scale->update(conf.scale); + rotate->update(conf.rotate); + translate->update(conf.translate); drag_object->update(conf.drag_object); object_x->update(conf.object_x); object_x_text->update((float)conf.object_x); @@ -732,6 +747,108 @@ int FindObjUseFlann::handle_event() return 1; } +FindObjScale::FindObjScale(FindObjMain *plugin, FindObjWindow *gui, + int x, int y) + : BC_CheckBox(x, y, plugin->config.scale, _("Scale")) +{ + this->gui = gui; + this->plugin = plugin; +} + +int FindObjScale::handle_event() +{ + plugin->config.scale = get_value(); + plugin->send_configure_change(); + return 1; +} + +FindObjRotate::FindObjRotate(FindObjMain *plugin, FindObjWindow *gui, + int x, int y) + : BC_CheckBox(x, y, plugin->config.rotate, _("Rotate")) +{ + this->gui = gui; + this->plugin = plugin; +} + +int FindObjRotate::handle_event() +{ + plugin->config.rotate = get_value(); + plugin->send_configure_change(); + return 1; +} + +FindObjTranslate::FindObjTranslate(FindObjMain *plugin, FindObjWindow *gui, + int x, int y) + : BC_CheckBox(x, y, plugin->config.translate, _("Translate")) +{ + this->gui = gui; + this->plugin = plugin; +} + +int FindObjTranslate::handle_event() +{ + plugin->config.translate = get_value(); + plugin->send_configure_change(); + return 1; +} + +FindObjMode::FindObjMode(FindObjMain *plugin, FindObjWindow *gui, int x, int y) + : BC_PopupMenu(x, y, calculate_w(gui), to_text(plugin->config.mode)) +{ + this->plugin = plugin; + this->gui = gui; +} + +int FindObjMode::handle_event() +{ + plugin->config.mode = from_text(get_text()); + plugin->send_configure_change(); + return 1; +} + +void FindObjMode::create_objects() +{ + add_item(new BC_MenuItem(to_text(MODE_SQUARE))); + add_item(new BC_MenuItem(to_text(MODE_RHOMBUS))); + add_item(new BC_MenuItem(to_text(MODE_RECTANGLE))); + add_item(new BC_MenuItem(to_text(MODE_PARALLELOGRAM))); + add_item(new BC_MenuItem(to_text(MODE_QUADRILATERAL))); +} +int FindObjMode::from_text(char *text) +{ + if(!strcmp(text, _("Square"))) return MODE_SQUARE; + if(!strcmp(text, _("Rhombus"))) return MODE_RHOMBUS; + if(!strcmp(text, _("Rectangle"))) return MODE_RECTANGLE; + if(!strcmp(text, _("Parallelogram"))) return MODE_PARALLELOGRAM; + if(!strcmp(text, _("Quadrilateral"))) return MODE_QUADRILATERAL; + return MODE_NONE; +} + +void FindObjMode::update(int mode) +{ + set_text(to_text(mode)); +} + +char* FindObjMode::to_text(int mode) +{ + switch( mode ) { + case MODE_SQUARE: return _("Square"); + case MODE_RHOMBUS: return _("Rhombus"); + case MODE_RECTANGLE: return _("Rectangle"); + case MODE_PARALLELOGRAM: return _("Parallelogram"); + case MODE_QUADRILATERAL: return _("Quadrilateral"); + } + return _("None"); +} + +int FindObjMode::calculate_w(FindObjWindow *gui) +{ + int result = 0; + for( int mode=MODE_NONE; modeget_text_width(MEDIUMFONT, to_text(mode))); + return result + 50; +} + FindObjLayer::FindObjLayer(FindObjMain *plugin, FindObjWindow *gui, int x, int y, int *value) diff --git a/cinelerra-5.1/plugins/findobj/findobjwindow.h b/cinelerra-5.1/plugins/findobj/findobjwindow.h index 2bc48117..02feee23 100644 --- a/cinelerra-5.1/plugins/findobj/findobjwindow.h +++ b/cinelerra-5.1/plugins/findobj/findobjwindow.h @@ -40,6 +40,10 @@ class FindObjDragObject; class FindObjDragScene; class FindObjDragReplace; class FindObjAlgorithm; +class FindObjMode; +class FindObjScale; +class FindObjRotate; +class FindObjTranslate; class FindObjBlend; class FindObjWindow; @@ -205,6 +209,47 @@ public: FindObjWindow *gui; }; +class FindObjScale : public BC_CheckBox +{ +public: + FindObjScale(FindObjMain *plugin, FindObjWindow *gui, int x, int y); + int handle_event(); + FindObjMain *plugin; + FindObjWindow *gui; +}; + +class FindObjRotate : public BC_CheckBox +{ +public: + FindObjRotate(FindObjMain *plugin, FindObjWindow *gui, int x, int y); + int handle_event(); + FindObjMain *plugin; + FindObjWindow *gui; +}; + +class FindObjTranslate : public BC_CheckBox +{ +public: + FindObjTranslate(FindObjMain *plugin, FindObjWindow *gui, int x, int y); + int handle_event(); + FindObjMain *plugin; + FindObjWindow *gui; +}; + +class FindObjMode : public BC_PopupMenu +{ +public: + FindObjMode(FindObjMain *plugin, FindObjWindow *gui, int x, int y); + int handle_event(); + void create_objects(); + void update(int mode); + static int calculate_w(FindObjWindow *gui); + static int from_text(char *text); + static char *to_text(int mode); + FindObjMain *plugin; + FindObjWindow *gui; +}; + class FindObjBlend : public BC_IPot { public: @@ -226,6 +271,10 @@ public: FindObjReset *reset; FindObjAlgorithm *algorithm; FindObjUseFlann *use_flann; + FindObjMode *mode; + FindObjScale *scale; + FindObjRotate *rotate; + FindObjTranslate *translate; FindObjScanFloat *object_x, *object_y, *object_w, *object_h; FindObjScanFloatText *object_x_text, *object_y_text, *object_w_text, *object_h_text; FindObjScanFloat *scene_x, *scene_y, *scene_w, *scene_h; diff --git a/cinelerra-5.1/plugins/moveobj/moveobj.C b/cinelerra-5.1/plugins/moveobj/moveobj.C index e6457555..77a80a3b 100644 --- a/cinelerra-5.1/plugins/moveobj/moveobj.C +++ b/cinelerra-5.1/plugins/moveobj/moveobj.C @@ -334,7 +334,7 @@ int MoveObj::process_buffer(VFrame *frame, int64_t start_position, double frame_ // interpolate with identity matrix accum_matrix = w0*identity + w1*accum_matrix; - AffineMatrix matrix; + AffineMatrix &matrix = affine->matrix; for( int i=0,k=0; i<3; ++i ) for( int j=0; j<3; ++j ) matrix.values[i][j] = amat[k++]; @@ -342,7 +342,6 @@ int MoveObj::process_buffer(VFrame *frame, int64_t start_position, double frame_ //printf("MoveObj::process_buffer %d %jd matrix=\n", __LINE__, start_position); //matrix.dump(); - affine->set_matrix(&matrix); // iframe is always temp, if we get here output->clear_frame(); affine->process(output, iframe, 0, AffineEngine::TRANSFORM, diff --git a/cinelerra-5.1/plugins/titler/titler.C b/cinelerra-5.1/plugins/titler/titler.C index 8d964918..fefbbdb1 100644 --- a/cinelerra-5.1/plugins/titler/titler.C +++ b/cinelerra-5.1/plugins/titler/titler.C @@ -2224,16 +2224,20 @@ TitleTranslateUnit::TitleTranslateUnit(TitleMain *plugin, TitleTranslate *server type **out_rows = (type**)output->get_rows(); \ float fr = 1./(256.-max), fs = max/255.; \ float r = max > 1 ? 0.5 : 0; \ - for( int y=y1; y=iy ? fy - iy : fy+1-iy; \ + int ix1= x1, iy1 = y1, ix2= x2, iy2 = y2; \ + float fy = y1 + yofs; \ + for( int y=iy1; y