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