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