int Mosaic::balanceRotations()
{
    // Normalize to the mean angle of rotation (Smiley face)
    double sineAngle = 0.0;

    for (int i = 0; i < frames_size; i++) sineAngle += frames[i]->trs[0][1];
    sineAngle /= frames_size;
    // Calculate the cosineAngle (1 - sineAngle*sineAngle) = cosineAngle*cosineAngle
    double cosineAngle = sqrt(1.0 - sineAngle*sineAngle);
    double m[3][3] = {
        { cosineAngle, -sineAngle, 0 },
        { sineAngle, cosineAngle, 0},
        { 0, 0, 1}};
    double tmp[3][3];

    for (int i = 0; i < frames_size; i++) {
        memcpy(tmp, frames[i]->trs, sizeof(tmp));
        mult33d(frames[i]->trs, m, tmp);
    }

    return MOSAIC_RET_OK;
}
// Get current transformation
int Align::getLastTRS(double trs[3][3])
{
  if (frame_number < 1)
  {
    trs[0][0] = 1.0;
    trs[0][1] = 0.0;
    trs[0][2] = 0.0;
    trs[1][0] = 0.0;
    trs[1][1] = 1.0;
    trs[1][2] = 0.0;
    trs[2][0] = 0.0;
    trs[2][1] = 0.0;
    trs[2][2] = 1.0;
    return ALIGN_RET_ERROR;
  }

  // Note that the logic here handles the case, where a frame is not used for
  // mosaicing but is captured and used in the preview-rendering.
  // For these frames, we don't set Hcurr to identity in AddFrame() and the
  // logic here appends their transformation to Hprev to render them with the
  // correct transformation. For the frames we do use for mosaicing, we already
  // append their Hcurr to Hprev in AddFrame() and then set Hcurr to identity.

  double Hinv33[3][3];
  double Hprev33[3][3];
  double Hcurr33[3][3];

  Matrix33::convert9to33(Hcurr33, Hcurr);
  normProjMat33d(Hcurr33);
  inv33d(Hcurr33, Hinv33);

  Matrix33::convert9to33(Hprev33, Hprev);

  mult33d(trs, Hprev33, Hinv33);
  normProjMat33d(trs);

  return ALIGN_RET_OK;
}
int Align::addFrame(ImageType imageGray_)
{
  int ret_code = ALIGN_RET_OK;

 // Obtain a vector of pointers to rows in image and pass in to dbreg
  ImageType *m_rows = ImageUtils::imageTypeToRowPointers(imageGray_, width, height);

  if (frame_number == 0)
  {
      reg.AddFrame(m_rows, Hcurr, true);    // Force this to be a reference frame
      int num_corner_ref = reg.GetNrRefCorners();

      if (num_corner_ref < MIN_NR_REF_CORNERS)
      {
          return ALIGN_RET_LOW_TEXTURE;
      }
  }
  else
  {
      reg.AddFrame(m_rows, Hcurr, false);
  }

  // Average translation per frame =
  //    [Translation from Frame0 to Frame(n-1)] / [(n-1)]
  average_tx_per_frame = (num_frames_captured < 2) ? 0.0 :
        Hprev[2] / (num_frames_captured - 1);

  // Increment the captured frame counter if we already have a reference frame
  num_frames_captured++;

  if (frame_number != 0)
  {
    int num_inliers = reg.GetNrInliers();

    if(num_inliers < MIN_NR_INLIERS)
    {
        ret_code = ALIGN_RET_FEW_INLIERS;

        Hcurr[0] = 1.0;
        Hcurr[1] = 0.0;
        // Set this as the average per frame translation taking into acccount
        // the separation of the current frame from the reference frame...
        Hcurr[2] = -average_tx_per_frame *
                (num_frames_captured - reference_frame_index);
        Hcurr[3] = 0.0;
        Hcurr[4] = 1.0;
        Hcurr[5] = 0.0;
        Hcurr[6] = 0.0;
        Hcurr[7] = 0.0;
        Hcurr[8] = 1.0;
    }

    if(fabs(Hcurr[2])<thresh_still && fabs(Hcurr[5])<thresh_still)  // Still camera
    {
        return ALIGN_RET_ERROR;
    }

    // compute the homography:
    double Hinv33[3][3];
    double Hprev33[3][3];
    double Hcurr33[3][3];

    // Invert and multiple with previous transformation
    Matrix33::convert9to33(Hcurr33, Hcurr);
    Matrix33::convert9to33(Hprev33, Hprev);
    normProjMat33d(Hcurr33);

    inv33d(Hcurr33, Hinv33);

    mult33d(Hcurr33, Hprev33, Hinv33);
    normProjMat33d(Hcurr33);
    Matrix9::convert33to9(Hprev, Hcurr33);
    // Since we have already factored the current transformation
    // into Hprev, we can reset the Hcurr to identity
    db_Identity3x3(Hcurr);

    // Update the reference frame to be the current frame
    reg.UpdateReference(m_rows,quarter_res,false);

    // Update the reference frame index
    reference_frame_index = num_frames_captured;
  }

  frame_number++;

  return ret_code;
}