Vista     Main Page   Class List   Function List   File List   Examples  


Warping.cpp

Example of warped images generation.


This example shows how to generate warped images using a 2D affine motion model.

To get help or to see the available options try:

 
  ./Warping -?
  

To generate a synthetic sequence based on warping image 20 and 21 of the round-about sequence by using an affine motion model specified for these two images in ../../test/motion/model.txt try:

 
  cp ../../test/sequence/png/rond-point002{0,1}.png /tmp
  ./Warping -p /tmp/rond-point%04d.png -f 20 -i 2 -m ../../test/motion/model.txt -w /tmp/warped%02d.png -v
  

The warped images are available in /tmp/warped20.png and /tmp/warped20.png


Main:

/*

  Copyright (c) 1995-2005 by INRIA.
  All Rights Reserved.

  This software was developed at:
  IRISA/INRIA Rennes
  Campus Universitaire de Beaulieu
  35042 Rennes Cedex

  http://www.irisa.fr

*/

#include <stdio.h>
#include <stdlib.h>
#ifdef __SunOS_
# include <iostream.h>
#else
# include <iostream>
#endif
#include <ctype.h>
#include <string>

// Includes lies a Motion2D
#include <CMotion2DImage.h>
#include <CMotion2DModel.h>
#include <CMotion2DWarping.h>
#include <CReader.h>
#include <CImageReader.h>
#include <CMpeg2Reader.h>
#include "CImageWriter.h"
#include "../src/inc/type.h"
#include "../src/compense/compense.h"

using namespace std;

#define GETOPTARGS      "f:hi:m:p:s:vw:?"
#define max(a,b) (a>b?a:b)

bool findChar(string ch, char *f)
{
  int n = ch.find(f);
  int size = ch.size();
  return (n>0 && n<size);
};

int  getoption (int argc, char** argv, char* pszValidOpts, char** ppszParam);
void getoptions(int argc, char **argv,
                string &ipath, unsigned long &frame,
                int &step, long unsigned &niter,
                string &mfile, string &wpath, bool &verbose);
void usage(char *name, char *badparam);
bool readModel(string filename, unsigned long frame, CMotion2DModel &model);

#define DEBUG_LEVEL1 0
#define DEBUG_LEVEL2 0


/*

  Robust multiresolution estimation of parametric motion model.

*/
int main(int argc, char **argv)
{
  CMotion2DImage<unsigned char> I;      // Image
  CMotion2DImage<unsigned char> W;      // M-estimator weights image
  CMotion2DModel        model;          // Parametric motion model
  CMotion2DWarping      warping;        // Warping
  CReader               *Ireader=NULL;  // Image reader
  CImageReader          imgr;           // PNM or PNG image reader
  CMpeg2Reader          mpegr;          // Mpeg2 image decoder
  CWriter               *Wwriter=NULL;  // Image writer
  CImageWriter          imgw;           // PNM or PNG image writer

  string ipath = "../../test/sequence/rond-point"; // Image path
  string filename;              // Complete filename for an image of the video
  string mfile;                 // Motion model filename
  string wpath;                 // Warped image path
  long unsigned niter = 33;     // Number of images to process
  int  step = 1;                // Step between 2 images
  bool verbose = false;         // Verbose mode
  bool ierr = true;             // Image IO return value
  unsigned long frame  = 1; // Current frame number to process

  // Read the program options
  getoptions(argc, argv, ipath, frame, step, niter,
             mfile, wpath, verbose);

  // Set the image reader format by regarding the image extension
  if (findChar(ipath, _mpg) || findChar(ipath, _mpeg)) {
    cout << "Reader mpeg\n";
    Ireader = &mpegr;
  }
  else {
    cout << "Reader PNM\n";
    Ireader = &imgr;
  }

  Ireader->setFileName(ipath);
  Ireader->setFrameNumber(frame);
  filename = Ireader->getFileName();

  if (!Ireader->openStream()) {
    cout <<"Can't open stream "<< ipath <<endl;
    exit(-1);
  }

  // Set the image writer
  Wwriter = &imgw;

  // Start the warping loop
  long unsigned i=0;
  do {

    // Load the image
    Ireader->setFileName(ipath);
    Ireader->setFrameNumber(frame);
    filename = Ireader->getFileName();
    if (verbose)
      cout << "Load image: " << filename << endl ;
    ierr = Ireader->getFrame(I);
    if (ierr == false) {
      cout << "Can not read the image: " << filename << endl;
      exit(-1);
    }

    if (readModel(mfile, frame, model) == false)
      exit(0);

    if (verbose) {
      double row, col;
      double p[CMotion2DModel::MDL_NMAX_COEF]; // model parameters
      model.getOrigin(row, col);
      model.getParameters(p);
      cout << "Warp image: " << filename.c_str() << endl;
      cout << "\tMotion model: " << model.idToString() << endl;
      cout << "\t  origin: " << row << " " << col << endl;
      cout << "\t  x: " << p[0] <<" | " << p[2] << " " << p[3] << " | "
           << p[6] << " " << p[7] << " " << p[8] << endl;
      cout << "\t  y: " << p[1] <<" | " << p[4] << " " << p[5] << " | "
           << p[9] << " " << p[10] << " " << p[11] << endl;
    }

    // Initialize the warped image size
    W.Init(I.GetRows(), I.GetCols());

    // warp the input image
    warping.warp(I.bitmap, W.bitmap, I.GetRows(), I.GetCols(), model);

    // Construct the backwarped image filename
    Wwriter->setFileName(wpath);
    Wwriter->setFrameNumber(frame);
    filename = Wwriter->getFileName();
    if (verbose)
      cout << "\tWrite warped image: " << filename << endl ;
    ierr = Wwriter->writeFrame(W);    // Write the backwarped image
    if (ierr == false) {
      cout << "Can not write the backwarped image: " << filename << endl;
      exit(-1);
    }

    frame += step; // Update the image frame number

  } while (++i < niter);

  Ireader->closeStream();

  return 0;
}



/*

  Print the program options.

 */
void usage(char *name, char *badparam)
{
  if (badparam)
    fprintf(stderr, "\nBad parameter [%s]\n", badparam);

  fprintf(stdout, "\n\
  Copyright (c) 1995-2005 by INRIA.\n\
  All Rights Reserved.\n\
\n\
  This software was developed at:\n\
  IRISA/INRIA Rennes\n\
  Campus Universitaire de Beaulieu \n\
  35042 Rennes Cedex\n\
\n\
  http://www.irisa.fr\n\
\n\
SYNOPSIS\n\
  %s [-p image_path] [-e image_extension] [-f first_frame]\n\
  [-s step] [-i iterations] [-m model_filename] [-w warped_image_path]\n\
  [-v] [-h] [-?]\n\
\n\
DESCRIPTION\n\
  This software generates warped images using a parametric motion model.\n\
\n\
\n", name);

#ifndef __NO_IMAGEIO_PNG_
  fprintf(stdout, "\
INPUT SEQUENCE OPTIONS:                                       Default\n\
\n\
  -p image_path [%%s]                  ../../test/sequence/rond-point\n\
     Specify the path and the generic name of the files \n\
     containing the images to process. The following image\n\
     file formats PNG and PNM are supported. The different\n\
     PNM formats are PGM (P5) and PPM (P6).\n\
\n\
  -e image_extension [%%s]                                       .pgm\n\
     Specify the image extension. Supported image formats \n\
     are PNG (use -e .png), PGM P5 (use -e .pgm) and PPM P6\n\
     (use -e .ppm). \n\
\n");
#else
  fprintf(stdout, "\
INPUT SEQUENCE OPTIONS:                                       Default\n\
\n\
  -p image_path [%%s]                  ../../test/sequence/rond-point\n\
     Specify the path and the generic name of the files \n\
     containing the images to process. Only the PNM formats \n\
     PGM (P5) and PPM (P6) are supported.\n\
\n\
  -e image_extension [%%s]                                       .pgm\n\
     Specify the image extension. Supported image formats \n\
     are PGM P5 (use -e .pgm) and PPM P6 (use -e .ppm). \n\
\n");
#endif

  fprintf(stdout, "\
  -f first_frame [%%s]                                           0001\n\
     Specify the number of the first frame in the video \n\
     sequence. If the image sequence numbering uses a fixed \n\
     number of digits, complete whith 0 before the image number.\n\
\n\
  -s step [%%d]                                                     1\n\
     Specify the step between two frames in the video sequence.\n\
     If step > 0 images are processed forward. If step < 0 images\n\
     are processed backward.\n\
\n\
  -i iterations [%%lu]                                             33\n\
     Specify the number of motion estimation iterations to\n\
     process. The number of the last image computed is given by:\n\
     first_frame + iterations * step.\n\
\n\
  -m model_filename [%%s]                       \n\
     Specify the name of the file containing the values of the\n\
     parametric motion model coefficients.\n\
\n\
\n\
RESULTS OPTIONS:\n\
\n\
  -w warped_image_path [%%s]                           \n\
     Specify the path and the generic name of the files contain-\n\
     ing the back-warped images built using the estimated motion\n\
     model. The generated images format depends on the treated  \n\
     image extension specified by option -e.\n\
\n");

  fprintf(stdout, "\n\
OTHER OPTIONS:\n\
\n\
  -v\n\
     Activate the verbose mode.\n\
\n\
  -h\n\
     Print the help.\n\
\n\
  -?\n\
     Print the help.\n\
\n\
\n");

  exit(0);
}

/*

  Set the program options.

*/
void getoptions(int argc, char **argv,
                string &ipath, unsigned long &frame,
                int &step, long unsigned &niter,
                string &mfile, string &wpath, bool &verbose)
{
  char *optarg;
  int   c;
  while ((c = getoption(argc, argv, GETOPTARGS, &optarg)) > 1) {

    switch (c) {
    case 'f': frame = (unsigned long) atoi(optarg); break;
    case 'h': usage(argv[0], NULL); break;
    case 'i': niter = atoi(optarg); break;
    case 'm': mfile = optarg; break;
    case 'p': ipath = optarg; break;
    case 's': step = atoi(optarg); break;
    case 'v': verbose = true; break;
    case 'w': wpath = optarg; break;
    case '?': usage(argv[0], NULL); break;

    default:  usage(argv[0], NULL); break;
    }
  }

  // Some option tests
  if (wpath.empty()) {
    // standalone param or error
    fprintf(stderr, "Option -w [warped_image_path] not specified\n");
    usage(argv[0], NULL);
    exit(0);


  }
  if ((c == 1) || (c == -1)) {
    // standalone param or error
    fprintf(stderr, "Bad argument %s\n", optarg);

    usage(argv[0], NULL);

    exit(0);
  }

  if ( mfile.empty() ) {
    cout << endl << "Error: argument -m <filename> not specified " << endl;
    exit(0);
  }
  else {
    FILE *fd = fopen(mfile.c_str(), "rb");
    if (fd == NULL) {
      cout << endl
           << "Bad argument -m: "
           << "Cannot open the filename specified "
           << endl
           << "with this option."
           << endl;
      exit(0);
    }
    fclose(fd);
  }
}

/*

  Get next command line option and parameter

  PARAMETERS:

      argc - count of command line arguments
      argv - array of command line argument strings
      pszValidOpts - string of valid, case-sensitive option characters,
                     a colon ':' following a given character means that
                     option can take a parameter
      ppszParam - pointer to a pointer to a string for output

  RETURNS:

      If valid option is found, the character value of that option
          is returned, and *ppszParam points to the parameter if given,
          or is NULL if no param
      If standalone parameter (with no option) is found, 1 is returned,
          and *ppszParam points to the standalone parameter
      If option is found, but it is not in the list of valid options,
          -1 is returned, and *ppszParam points to the invalid argument
      When end of argument list is reached, 0 is returned, and
          *ppszParam is NULL
*/
int getoption (
    int argc,
    char** argv,
    char* pszValidOpts,
    char** ppszParam)
{
  static int iArg = 1;
  int chOpt;
  char* psz = NULL;
  char* pszParam = NULL;

  if (iArg < argc) {
    psz = &(argv[iArg][0]);
    if (*psz == '-') { // || *psz == '/')  {
      // we have an option specifier
      chOpt = argv[iArg][1];
      if (isalnum(chOpt) || ispunct(chOpt)) {
        // we have an option character
        psz = strchr(pszValidOpts, chOpt);
        if (psz != NULL) {
          // option is valid, we want to return chOpt
          if (psz[1] == ':') {
            // option can have a parameter
            psz = &(argv[iArg][2]);
            if (*psz == '\0') {
              // must look at next argv for param
              if (iArg+1 < argc) {
                psz = &(argv[iArg+1][0]);
                // next argv is the param
                iArg++;
                pszParam = psz;
              }
              else {
                // reached end of args looking for param
              }

            }
            else {
              // param is attached to option
              pszParam = psz;
            }
          }
          else {
            // option is alone, has no parameter
          }
        }
        else {
          // option specified is not in list of valid options
          chOpt = -1;
          pszParam = &(argv[iArg][0]);
        }
      }
      else {
        // though option specifier was given, option character
        // is not alpha or was was not specified
        chOpt = -1;
        pszParam = &(argv[iArg][0]);
      }
    }
    else {
      // standalone arg given with no option specifier
      chOpt = 1;
      pszParam = &(argv[iArg][0]);
    }
  }
  else {
    // end of argument list
    chOpt = 0;
  }

  iArg++;
  *ppszParam = pszParam;
  return (chOpt);
}

bool readModel(string filename, unsigned long frame, CMotion2DModel &model)
{
#define MAX_LEN 512

  FILE *fd = NULL;
  char  str[MAX_LEN];
  int   line;
  char* cerr;
  int   ierr;

  if ( filename.empty() ) {
    fprintf(stderr, "Error in readModel: no filename\n");
    return false;
  }

  fd = fopen(filename.c_str(), "rb");
  if (fd == NULL) {
    fprintf(stderr, "Error in readModel: couldn't read file %s\n",
            filename.c_str());
    return false;
  }

  // Jump the possible comment, or empty line and read the following line
  line = 0;
  do {
    cerr = fgets(str, MAX_LEN - 1, fd);

    line++;
    if (cerr == NULL) {
      fprintf(stderr, "Error in readModel: couldn't read line %d of file %s\n",
              line, filename.c_str());
      fclose (fd);
      return false;
    }
  } while ((str[0] == '#') || (str[0] == '\n'));

  // Extract model id
  char _text[255];
  char _egal[255];
  char _id[255];
  string s = str;
  ierr = s.find("MODEL_ID");
  if (ierr != -1) {
    ierr = sscanf(str, "%s %s %s", _text, _egal, _id);
    //    printf("text: %s\n", _text);
    //   printf("_egal: %s\n", _egal);
    //  printf("_id: %s\n", _id);
  }
  else {
     ierr = sscanf(str, "%s", _id);
  }

  if (ierr == EOF) {
    fprintf(stderr,
            "Error in readModel: premature EOF on line %d of file %s\n",
            line, filename.c_str());
    fclose (fd);
    return false;
  }

  unsigned long _frame;
  double _row, _col; // model origin
  double _p[CMotion2DModel::MDL_NMAX_COEF]; // model parameters
  double _multfactor = 1.0;
  bool multfactor_was_read = false;

  do {
    // Read a line
    cerr = fgets(str, MAX_LEN - 1, fd);
    //printf("line2: %s\n", str);
    line ++;
    if (cerr == NULL) {
      fprintf(stderr, "Error in readModel: couldn't read line %d of file %s\n",
              line, filename.c_str());
      fclose (fd);
      return false;
    }

    // Get the multiplier factor if it exists
    if (multfactor_was_read == false) {
      s = str;
      ierr = s.find("MULTIPLIER_FACTOR");
      multfactor_was_read = true;
      if (ierr != -1) {
        ierr = sscanf(str, "%s %s %lf", _text, _egal, &_multfactor);
        cout << "multfactor: " << _multfactor << endl;
        if (ierr == EOF) {
          fprintf(stderr,
                  "Error in readModel: premature EOF on line %d of file %s\n",
                  line, filename.c_str());
          fclose (fd);
          return false;
        }
        continue;
      }
    }

    // Extract information
    ierr = sscanf(str,
                  "%ld %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
                  &_frame, &_row, &_col,
                  &_p[0], &_p[1], // c1, c2
                  &_p[2], &_p[3], &_p[4], &_p[5], //a1, a2, a3, a4
                  &_p[6], &_p[7], &_p[8], &_p[9], &_p[10], &_p[11]); //q1...q6
    if (ierr == EOF) {
      fprintf(stderr,
              "Error in readModel: premature EOF on line %d of file %s\n",
              line, filename.c_str());
      fclose (fd);
      return false;

    }
  } while (frame != _frame);

  // rescale the parameters
  for (int i=0; i < CMotion2DModel::MDL_NMAX_COEF; i ++) {
    _p[i] /= _multfactor;
  }

  string id = _id;

  model.reset();        // Set all the parameters to zero
  model.setIdModel(id); // Set the model id
  model.setVarLight(false); // Set the illumination variation
  model.setOrigin(_row, _col); // Set the origin
  model.setParameters(_p);

  fclose (fd);

  return true;

#undef MAX_LEN
}



Motion2D is Copyright © 1995-2005 by Inria
This documentation was generated on 31 Jan 2005 by Fabien Spindler for Motion2D 1.3.11 using doxygen1.2.18 written by Dimitri van Heesch, © 1997-2005