findobj mode/xlat/scale/rotate, save backup shortcut, undo limit bug, title boundary...
authorGood Guy <good1.2guy@gmail.com>
Mon, 23 Apr 2018 22:17:17 +0000 (16:17 -0600)
committerGood Guy <good1.2guy@gmail.com>
Mon, 23 Apr 2018 22:17:17 +0000 (16:17 -0600)
12 files changed:
cinelerra-5.1/cinelerra/affine.C
cinelerra-5.1/cinelerra/affine.h
cinelerra-5.1/cinelerra/mwindow.C
cinelerra-5.1/cinelerra/savefile.C
cinelerra-5.1/cinelerra/undostack.C
cinelerra-5.1/guicast/test4.C
cinelerra-5.1/plugins/findobj/findobj.C
cinelerra-5.1/plugins/findobj/findobj.h
cinelerra-5.1/plugins/findobj/findobjwindow.C
cinelerra-5.1/plugins/findobj/findobjwindow.h
cinelerra-5.1/plugins/moveobj/moveobj.C
cinelerra-5.1/plugins/titler/titler.C

index 2842f9909feb81d974801ce87a54e171a7895e40..a59d6e3ee9997372f5b9c4eede18f44ac0d96a17 100644 (file)
@@ -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;
index be74d572827a92ec5c54e78dcc9378fdc849519d..1740d90545e1e3923fd2931fba8c3ad20ab7d065 100644 (file)
@@ -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);
index 202a7687d073b3e4c0202258fe48942ca3e0f3da..6150f954131af90569483dc305304075ff4c09d8 100644 (file)
@@ -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 ) {
index fc757cecd085601ecf013516287d5ea7c161ccb5..b38aec142c4ec8e4d49aba1f97535354de22f191 100644 (file)
@@ -46,7 +46,7 @@
 
 
 SaveBackup::SaveBackup(MWindow *mwindow)
- : BC_MenuItem(_("Save backup"))
+ : BC_MenuItem(_("Save backup"), "b", 'b')
 {
        this->mwindow = mwindow;
 }
index 59eadada8047ecd3cdf7c02670037515754b4141..23f33bc193148fadc237dc9ed85d8e8133429778 100644 (file)
@@ -27,6 +27,9 @@
 #include "undostack.h"
 #include <string.h>
 
+// undo can be incremental or direct, from key to current
+//#define UNDO_INCREMENTAL
+
 UndoStack::UndoStack() : List<UndoStackItem>()
 {
        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;
index 114ed49aff9baae38090522778c360d73a849928..522b844132eb94a3cf3e77983639a84b3689e057 100644 (file)
@@ -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);
   }
 }
 
index 7909170a3941a0cc1f3d8746eba2d2b329ff2c72..24c67cf80abb7f5a0afa6e773c8d9423e3a814b1 100644 (file)
@@ -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(); i<n; ++i ) {
+                       Point2f &pt = obj_keypts[i].pt;
+                       int r = obj_keypts[i].size * 1.2/9 * 2;
+                       int x = pt.x + object_x, y = pt.y + object_y;
+                       draw_circle(scene, x, y, r);
+               }
                scene->set_pixel_color(RED);  scene->set_stiple(0);
                for( int i=0,n=scn_keypts.size(); i<n; ++i ) {
                        Point2f &pt = scn_keypts[i].pt;
index 03b4fa8802bd287190341ce8c20e605d7fa7526d..7396f31b92b091f80563f9d7631fe790ab8a7c62 100644 (file)
@@ -83,13 +83,21 @@ using namespace cvflann;
 #define MIN_BLEND 1
 #define MAX_BLEND 100
 
-#define NO_ALGORITHM 0
+#define NO_ALGORITHM   -1
 #define ALGORITHM_SIFT  1
 #define ALGORITHM_SURF  2
 #define ALGORITHM_ORB   3
 #define ALGORITHM_AKAZE 4
 #define ALGORITHM_BRISK 5
 
+#define MODE_NONE          -1
+#define MODE_SQUARE         0
+#define MODE_RHOMBUS        1
+#define MODE_RECTANGLE      2
+#define MODE_PARALLELOGRAM  3
+#define MODE_QUADRILATERAL  4
+#define MODE_MAX            5
+
 class FindObjConfig
 {
 public:
@@ -109,6 +117,7 @@ public:
        float replace_x, replace_y, replace_w, replace_h;
        float replace_dx, replace_dy;
 
+       int mode, scale, translate, rotate;
        int draw_keypoints;
        int draw_scene_border;
        int replace_object;
@@ -144,6 +153,7 @@ public:
        void set_brisk();
 #endif
        void process_match();
+       void reshape();
 
        void draw_vectors(VFrame *frame);
        int is_multichannel();
@@ -162,10 +172,10 @@ public:
        static void draw_rect(VFrame *vframe, int x1, int y1, int x2, int y2);
        static void draw_circle(VFrame *vframe, int x, int y, int r);
 
-       int object_x, object_y, object_w, object_h;
-       int scene_x, scene_y, scene_w, scene_h;
-       int replace_x, replace_y, replace_w, replace_h;
-       int replace_dx, replace_dy;
+       float object_x, object_y, object_w, object_h;
+       float scene_x, scene_y, scene_w, scene_h;
+       float replace_x, replace_y, replace_w, replace_h;
+       float replace_dx, replace_dy;
 
        int w, h;
        int object_layer;
@@ -173,10 +183,10 @@ public:
        int replace_layer;
 
 // Latest coordinates of object in scene
-       int border_x1, border_y1;
-       int border_x2, border_y2;
-       int border_x3, border_y3;
-       int border_x4, border_y4;
+       float border_x1, border_y1;
+       float border_x2, border_y2;
+       float border_x3, border_y3;
+       float border_x4, border_y4;
 // Coordinates of object in scene with blending
        float obj_x1, obj_y1;
        float obj_x2, obj_y2;
index e9efbc0f573e4515c4c86f130154dd54846842cd..87d3dbd0e4f4451a3b45966bd670a9d97643ebb5 100644 (file)
@@ -51,13 +51,28 @@ void FindObjWindow::create_objects()
        add_subwindow(algorithm = new FindObjAlgorithm(plugin, this,
                x1 + title->get_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; mode<MODE_MAX; ++mode )
+               result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(mode)));
+       return result + 50;
+}
+
 
 FindObjLayer::FindObjLayer(FindObjMain *plugin, FindObjWindow *gui,
        int x, int y, int *value)
index 2bc48117c51031b8e7cf0f075c0f2ebbb397b136..02feee23bd21941503372df59e011acc8b7634d8 100644 (file)
@@ -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;
index e64575552c1974989b34608d61f4eee62e3902e3..77a80a3bbd59f8cbeb6ae77de38f115e75a0f6b9 100644 (file)
@@ -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,
index 8d964918177dbe488f46e9b6b95227ee106e5b2a..fefbbdb119c371a3e860ee45a72382f9c0836a1d 100644 (file)
@@ -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<y2; ++y ) { \
-               float fy = y+yofs;  int iy = fy; \
-               float yf1 = fy>=iy ? fy - iy : fy+1-iy; \
+       int ix1= x1, iy1 = y1, ix2= x2, iy2 = y2; \
+       float fy = y1 + yofs; \
+       for( int y=iy1; y<iy2; ++y,++fy ) { \
+               int iy = fy;  float yf1 = fy - iy; \
+               if( yf1 < 0 ) ++yf1; \
                float yf0 = 1. - yf1; \
                unsigned char *in_row0 = in_rows[iy<0 ? 0 : iy]; \
                unsigned char *in_row1 = in_rows[iy<ih1 ? iy+1 : ih1]; \
-               for( int x=x1; x<x2; ++x ) { \
+               float fx = x1 + xofs; \
+               for( int x=ix1; x<ix2; ++x,++fx ) { \
                        type *op = out_rows[y] + x*comps; \
-                       float fx = x+xofs;  int ix = fx; \
-                       float xf1 = fx - ix, xf0 = 1. - xf1; \
+                       int ix = fx;  float xf1 = fx - ix; \
+                       if( xf1 < 0 ) ++xf1; \
+                       float xf0 = 1. - xf1; \
                        int i0 = (ix<0 ? 0 : ix)*4, i1 = (ix<iw1 ? ix+1 : iw1)*4; \
                        uint8_t *cp00 = in_row0 + i0, *cp01 = in_row0 + i1; \
                        uint8_t *cp10 = in_row1 + i0, *cp11 = in_row1 + i1; \