Home | History | Annotate | Download | only in mosaic
      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