1e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen/*
2e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Copyright (C) 2011 The Android Open Source Project
3e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
4e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License");
5e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * you may not use this file except in compliance with the License.
6e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * You may obtain a copy of the License at
7e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
8e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *      http://www.apache.org/licenses/LICENSE-2.0
9e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen *
10e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Unless required by applicable law or agreed to in writing, software
11e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS,
12e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * See the License for the specific language governing permissions and
14e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * limitations under the License.
15e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */
16e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
17e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen///////////////////////////////////////////////////
18e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// AlignFeatures.cpp
19e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// S.O. # :
20e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// Author(s): zkira, mbansal, bsouthall, narodits
21e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// $Id: AlignFeatures.cpp,v 1.20 2011/06/17 13:35:47 mbansal Exp $
22e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
23e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <stdio.h>
24e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <string.h>
25e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
26e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "trsMatrix.h"
27e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "MatrixUtils.h"
28e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "AlignFeatures.h"
29dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal#include "Log.h"
30dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
31dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal#define LOG_TAG "AlignFeatures"
32e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
33e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenAlign::Align()
34e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
35e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  width = height = 0;
36e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  frame_number = 0;
37dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  num_frames_captured = 0;
38dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  reference_frame_index = 0;
39e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  db_Identity3x3(Hcurr);
40dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  db_Identity3x3(Hprev);
41e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
42e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
43e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta ChenAlign::~Align()
44e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
45e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  // Free gray-scale image
46e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  if (imageGray != ImageUtils::IMAGE_TYPE_NOIMAGE)
47e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    ImageUtils::freeImage(imageGray);
48e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
49e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
50e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenchar* Align::getRegProfileString()
51e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
52e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  return reg.profile_string;
53e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
54e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
55e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Align::initialize(int width, int height, bool _quarter_res, float _thresh_still)
56e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
57e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int    nr_corners = DEFAULT_NR_CORNERS;
58e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  double max_disparity = DEFAULT_MAX_DISPARITY;
59e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int    motion_model_type = DEFAULT_MOTION_MODEL;
60e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int nrsamples = DB_DEFAULT_NR_SAMPLES;
61e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  double scale = DB_POINT_STANDARDDEV;
62e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  int chunk_size = DB_DEFAULT_CHUNK_SIZE;
63dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  int nrhorz = width/48;  // Empirically determined number of horizontal
64dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  int nrvert = height/60; // and vertical buckets for harris corner detection.
65e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  bool linear_polish = false;
66e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  unsigned int reference_update_period = DEFAULT_REFERENCE_UPDATE_PERIOD;
67e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
68e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  const bool DEFAULT_USE_SMALLER_MATCHING_WINDOW = false;
69e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  bool   use_smaller_matching_window = DEFAULT_USE_SMALLER_MATCHING_WINDOW;
70e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
71e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  quarter_res = _quarter_res;
72e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  thresh_still = _thresh_still;
73e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
74e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  frame_number = 0;
75dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  num_frames_captured = 0;
76dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  reference_frame_index = 0;
77e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  db_Identity3x3(Hcurr);
78dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  db_Identity3x3(Hprev);
79dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
80e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  if (!reg.Initialized())
81e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  {
82dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    reg.Init(width, height, motion_model_type, 20, linear_polish, quarter_res,
83dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            scale, reference_update_period, false, 0, nrsamples, chunk_size,
84dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            nr_corners, max_disparity, use_smaller_matching_window,
85dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal            nrhorz, nrvert);
86e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
87e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  this->width = width;
88e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  this->height = height;
89e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
90e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  imageGray = ImageUtils::allocateImage(width, height, 1);
91e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
92e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  if (reg.Initialized())
93e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return ALIGN_RET_OK;
94e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  else
95e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return ALIGN_RET_ERROR;
96e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
97e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
98e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Align::addFrameRGB(ImageType imageRGB)
99e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
100e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageUtils::rgb2gray(imageGray, imageRGB, width, height);
101e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  return addFrame(imageGray);
102e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
103e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
104e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Align::addFrame(ImageType imageGray_)
105e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
106dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  int ret_code = ALIGN_RET_OK;
107e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
108e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Obtain a vector of pointers to rows in image and pass in to dbreg
109e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  ImageType *m_rows = ImageUtils::imageTypeToRowPointers(imageGray_, width, height);
110e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
111dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  if (frame_number == 0)
112dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  {
113dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal      reg.AddFrame(m_rows, Hcurr, true);    // Force this to be a reference frame
114dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal      int num_corner_ref = reg.GetNrRefCorners();
115dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
116dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal      if (num_corner_ref < MIN_NR_REF_CORNERS)
117dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal      {
118dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal          return ALIGN_RET_LOW_TEXTURE;
119dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal      }
120dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  }
121dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  else
122dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  {
123dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal      reg.AddFrame(m_rows, Hcurr, false);
124dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  }
125dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
126dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  // Average translation per frame =
127dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  //    [Translation from Frame0 to Frame(n-1)] / [(n-1)]
128dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  average_tx_per_frame = (num_frames_captured < 2) ? 0.0 :
129dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        Hprev[2] / (num_frames_captured - 1);
130dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
131dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  // Increment the captured frame counter if we already have a reference frame
132dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  num_frames_captured++;
133e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
134e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  if (frame_number != 0)
135e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  {
136dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    int num_inliers = reg.GetNrInliers();
137dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
138dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    if(num_inliers < MIN_NR_INLIERS)
139dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    {
140dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        ret_code = ALIGN_RET_FEW_INLIERS;
141dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
142dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        Hcurr[0] = 1.0;
143dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        Hcurr[1] = 0.0;
144dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        // Set this as the average per frame translation taking into acccount
145dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        // the separation of the current frame from the reference frame...
146dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        Hcurr[2] = -average_tx_per_frame *
147dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal                (num_frames_captured - reference_frame_index);
148dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        Hcurr[3] = 0.0;
149dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        Hcurr[4] = 1.0;
150dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        Hcurr[5] = 0.0;
151dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        Hcurr[6] = 0.0;
152dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        Hcurr[7] = 0.0;
153dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal        Hcurr[8] = 1.0;
154dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    }
155e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
156e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    if(fabs(Hcurr[2])<thresh_still && fabs(Hcurr[5])<thresh_still)  // Still camera
157e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    {
158e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen        return ALIGN_RET_ERROR;
159e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    }
160e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
161dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    // compute the homography:
162dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    double Hinv33[3][3];
163dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    double Hprev33[3][3];
164dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    double Hcurr33[3][3];
165dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
166e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    // Invert and multiple with previous transformation
167e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    Matrix33::convert9to33(Hcurr33, Hcurr);
168e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    Matrix33::convert9to33(Hprev33, Hprev);
169e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    normProjMat33d(Hcurr33);
170e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
171e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    inv33d(Hcurr33, Hinv33);
172e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
173e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    mult33d(Hcurr33, Hprev33, Hinv33);
174e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    normProjMat33d(Hcurr33);
175dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    Matrix9::convert33to9(Hprev, Hcurr33);
176dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    // Since we have already factored the current transformation
177dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    // into Hprev, we can reset the Hcurr to identity
178dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    db_Identity3x3(Hcurr);
179e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
180dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    // Update the reference frame to be the current frame
181e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    reg.UpdateReference(m_rows,quarter_res,false);
182dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
183dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    // Update the reference frame index
184dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    reference_frame_index = num_frames_captured;
185e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
186e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
187e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  frame_number++;
188e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
189dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  return ret_code;
190e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
191e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
192e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// Get current transformation
193e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenint Align::getLastTRS(double trs[3][3])
194e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{
195e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  if (frame_number < 1)
196e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  {
197dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    trs[0][0] = 1.0;
198dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    trs[0][1] = 0.0;
199dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    trs[0][2] = 0.0;
200dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    trs[1][0] = 0.0;
201dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    trs[1][1] = 1.0;
202dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    trs[1][2] = 0.0;
203dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    trs[2][0] = 0.0;
204dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    trs[2][1] = 0.0;
205dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal    trs[2][2] = 1.0;
206e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen    return ALIGN_RET_ERROR;
207e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  }
208e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
209dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  // Note that the logic here handles the case, where a frame is not used for
210dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  // mosaicing but is captured and used in the preview-rendering.
211dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  // For these frames, we don't set Hcurr to identity in AddFrame() and the
212dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  // logic here appends their transformation to Hprev to render them with the
213dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  // correct transformation. For the frames we do use for mosaicing, we already
214dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  // append their Hcurr to Hprev in AddFrame() and then set Hcurr to identity.
215dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
216dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  double Hinv33[3][3];
217dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  double Hprev33[3][3];
218dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  double Hcurr33[3][3];
219dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
220dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  Matrix33::convert9to33(Hcurr33, Hcurr);
221dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  normProjMat33d(Hcurr33);
222dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  inv33d(Hcurr33, Hinv33);
223dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
224dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  Matrix33::convert9to33(Hprev33, Hprev);
225dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
226dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  mult33d(trs, Hprev33, Hinv33);
227dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal  normProjMat33d(trs);
228dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal
229e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen  return ALIGN_RET_OK;
230e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}
231e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen
232