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#pragma once 19e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 20e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#ifdef _WIN32 21e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#ifdef DBREG_EXPORTS 22e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#define DBREG_API __declspec(dllexport) 23e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#else 24e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#define DBREG_API __declspec(dllimport) 25e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#endif 26e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#else 27e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#define DBREG_API 28e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#endif 29e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 30e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// @jke - the next few lines are for extracting timing data. TODO: Remove after test 31e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#define PROFILE 0 32e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 33e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include "dbstabsmooth.h" 34e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 35e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <db_feature_detection.h> 36e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <db_feature_matching.h> 37e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#include <db_rob_image_homography.h> 38e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 39e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#if PROFILE 40e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen #include <sys/time.h> 41e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#endif 42e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 43e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen/*! \mainpage db_FrameToReferenceRegistration 44e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 45e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \section intro Introduction 46e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 47e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen db_FrameToReferenceRegistration provides a simple interface to a set of sophisticated algorithms for stabilizing 48e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen video sequences. As its name suggests, the class is used to compute parameters that will allow us to warp incoming video 49e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen frames and register them with respect to a so-called <i>reference</i> frame. The reference frame is simply the first 50e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen frame of a sequence; the registration process is that of estimating the parameters of a warp that can be applied to 51e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen subsequent frames to make those frames align with the reference. A video made up of these warped frames will be more 52e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen stable than the input video. 53e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 54e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen For more technical information on the internal structure of the algorithms used within the db_FrameToRegistration class, 55e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen please follow this <a href="../Sarnoff image registration.docx">link</a>. 56e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 57e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \section usage Usage 58e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen In addition to the class constructor, there are two main functions of db_FrameToReferenceRegistration that are of 59e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen interest to the programmer. db_FrameToReferenceRegistration::Init(...) is used to initialize the parameters of the 60e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen registration algorithm. db_FrameToReferenceRegistration::AddFrame(...) is the method by which each new video frame 61e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen is introduced to the registration algorithm, and produces the estimated registration warp parameters. 62e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 63e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen The following example illustrates how the major methods of the class db_FrameToReferenceRegistration can be used together 64e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen to calculate the registration parameters for an image sequence. In the example, the calls to the methods of 65e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen db_FrameToReferenceRegistration match those found in the API, but supporting code should be considered pseudo-code. 66e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen For a more complete example, please consult the source code for dbregtest. 67e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 68e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 69e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \code 70e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // feature-based image registration class: 71e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen db_FrameToReferenceRegistration reg; 72e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 73e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Image data 74e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen const unsigned char * const * image_storage; 75e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 76e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // The 3x3 frame to reference registration parameters 77e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double frame_to_ref_homography[9]; 78e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 79e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // a counter to count the number of frames processed. 80e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned long frame_counter; 81e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // ... 82e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 83e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // main loop - keep going while there are images to process. 84e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen while (ImagesAreAvailable) 85e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 86e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Call functions to place latest data into image_storage 87e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // ... 88e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 89e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // if the registration object is not yet initialized, then do so 90e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // The arguments to this function are explained in the accompanying 91e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // html API documentation 92e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (!reg.Initialized()) 93e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 94e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen reg.Init(w,h,motion_model_type,25,linear_polish,quarter_resolution, 95e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen DB_POINT_STANDARDDEV,reference_update_period, 96e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen do_motion_smoothing,motion_smoothing_gain, 97e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen DB_DEFAULT_NR_SAMPLES,DB_DEFAULT_CHUNK_SIZE, 98e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen nr_corners,max_disparity); 99e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 100e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 101e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Present the new image data to the registration algorithm, 102e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // with the result being stored in the frame_to_ref_homography 103e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // variable. 104e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen reg.AddFrame(image_storage,frame_to_ref_homography); 105e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 106e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // frame_to_ref_homography now contains the stabilizing transform 107e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // use this to warp the latest image for display, etc. 108e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 109e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // if this is the first frame, we need to tell the registration 110e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // class to store the image as its reference. Otherwise, AddFrame 111e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // takes care of that. 112e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if (frame_counter == 0) 113e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 114e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen reg.UpdateReference(image_storage); 115e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 116e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 117e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // increment the frame counter 118e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen frame_counter++; 119e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 120e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 121e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \endcode 122e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 123e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 124e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 125e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen/*! 126e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Performs feature-based frame to reference image registration. 127e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 128e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenclass DBREG_API db_FrameToReferenceRegistration 129e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 130e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenpublic: 131e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen db_FrameToReferenceRegistration(void); 132e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen ~db_FrameToReferenceRegistration(); 133e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 134e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 135e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Set parameters and allocate memory. Note: The default values of these parameters have been set to the values used for the android implementation (i.e. the demo APK). 136e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param width image width 137e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param height image height 138e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param homography_type see definitions in \ref LMRobImageHomography 139e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param max_iterations max number of polishing steps 140e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param linear_polish whether to perform a linear polishing step after RANSAC 141e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param quarter_resolution whether to process input images at quarter resolution (for computational efficiency) 142e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param scale Cauchy scale coefficient (see db_ExpCauchyReprojectionError() ) 143e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param reference_update_period how often to update the alignment reference (in units of number of frames) 144e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param do_motion_smoothing whether to perform display reference smoothing 145e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param motion_smoothing_gain weight factor to reflect how fast the display reference must follow the current frame if motion smoothing is enabled 146e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param nr_samples number of times to compute a hypothesis 147e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param chunk_size size of cost chunks 148e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param cd_target_nr_corners target number of corners for corner detector 149e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param cm_max_disparity maximum disparity search range for corner matcher (in units of ratio of image width) 150e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param cm_use_smaller_matching_window if set to true, uses a correlation window of 5x5 instead of the default 11x11 151e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param cd_nr_horz_blocks the number of horizontal blocks for the corner detector to partition the image 152e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param cd_nr_vert_blocks the number of vertical blocks for the corner detector to partition the image 153e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 154e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void Init(int width, int height, 155e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int homography_type = DB_HOMOGRAPHY_TYPE_DEFAULT, 156e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int max_iterations = DB_DEFAULT_MAX_ITERATIONS, 157e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool linear_polish = false, 158e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool quarter_resolution = true, 159e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double scale = DB_POINT_STANDARDDEV, 160e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned int reference_update_period = 3, 161e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool do_motion_smoothing = false, 162e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double motion_smoothing_gain = 0.75, 163e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int nr_samples = DB_DEFAULT_NR_SAMPLES, 164e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int chunk_size = DB_DEFAULT_CHUNK_SIZE, 165e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int cd_target_nr_corners = 500, 166e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double cm_max_disparity = 0.2, 167e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool cm_use_smaller_matching_window = false, 168e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int cd_nr_horz_blocks = 5, 169e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int cd_nr_vert_blocks = 5); 170e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 171e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 172e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Reset the transformation type that is being use to perform alignment. Use this to change the alignment type at run time. 173e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param homography_type the type of transformation to use for performing alignment (see definitions in \ref LMRobImageHomography) 174e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 175e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void ResetHomographyType(int homography_type) { m_homography_type = homography_type; } 176e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 177e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 178e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Enable/Disable motion smoothing. Use this to turn motion smoothing on/off at run time. 179e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param enable flag indicating whether to turn the motion smoothing on or off. 180e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 181e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void ResetSmoothing(bool enable) { m_do_motion_smoothing = enable; } 182e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 183e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 184e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Align an inspection image to an existing reference image, update the reference image if due and perform motion smoothing if enabled. 185e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param im new inspection image 186e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param H computed transformation from reference to inspection coordinate frame. Identity is returned if no reference frame was set. 187e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param force_reference make this the new reference image 188e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 189e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int AddFrame(const unsigned char * const * im, double H[9], bool force_reference=false, bool prewarp=false); 190e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 191e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 192e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Returns true if Init() was run. 193e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 194e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool Initialized() const { return m_initialized; } 195e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 196e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 197e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Returns true if the current frame is being used as the alignment reference. 198e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 199e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool IsCurrentReference() const { return m_current_is_reference; } 200e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 201e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 202e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Returns true if we need to call UpdateReference now. 203e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 204e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool NeedReferenceUpdate(); 205e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 206e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 207e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Returns the pointer reference to the alignment reference image data 208e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 209e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned char ** GetReferenceImage() { return m_reference_image; } 210e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 211e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 212e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Returns the pointer reference to the double array containing the homogeneous coordinates for the matched reference image corners. 213e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 214e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double * GetRefCorners() { return m_corners_ref; } 215e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 216e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Returns the pointer reference to the double array containing the homogeneous coordinates for the matched inspection image corners. 217e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 218e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double * GetInsCorners() { return m_corners_ins; } 219e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 220e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Returns the number of correspondences between the reference and inspection images. 221e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 222e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int GetNrMatches() { return m_nr_matches; } 223e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 224e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 225dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal * Returns the number of corners detected in the current reference image. 226dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal */ 227dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal int GetNrRefCorners() { return m_nr_corners_ref; } 228dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal 229dd28e1cc00373c02adf88dff878dbbe5d8be9e59mbansal /*! 230e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Returns the pointer to an array of indices that were found to be RANSAC inliers from the matched corner lists. 231e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 232e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int* GetInliers() { return m_inlier_indices; } 233e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 234e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 235e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Returns the number of inliers from the RANSAC matching step. 236e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 237e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int GetNrInliers() { return m_num_inlier_indices; } 238e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 239e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen //std::vector<int>& GetInliers(); 240e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen //void Polish(std::vector<int> &inlier_indices); 241e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 242e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 243e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Perform a linear polishing step by re-estimating the alignment transformation using the RANSAC inliers. 244e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param inlier_indices pointer to an array of indices that were found to be RANSAC inliers from the matched corner lists. 245e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param num_inlier_indices number of inliers i.e. the length of the array passed as the first argument. 246e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 247e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void Polish(int *inlier_indices, int &num_inlier_indices); 248e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 249e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 250e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Reset the motion smoothing parameters to their initial values. 251e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 252e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void ResetMotionSmoothingParameters() { m_stab_smoother.Init(); } 253e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 254e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 255e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Update the alignment reference image to the specified image. 256e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param im pointer to the image data to be used as the new alignment reference. 257e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param subsample boolean flag to control whether the function should internally subsample the provided image to the size provided in the Init() function. 258e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 259e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int UpdateReference(const unsigned char * const * im, bool subsample = true, bool detect_corners = true); 260e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 261e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 262e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Returns the transformation from the display reference to the alignment reference frame 263e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 264e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void Get_H_dref_to_ref(double H[9]); 265e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 266e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Returns the transformation from the display reference to the inspection reference frame 267e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 268e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void Get_H_dref_to_ins(double H[9]); 269e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 270e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Set the transformation from the display reference to the inspection reference frame 271e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param H the transformation to set 272e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 273e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void Set_H_dref_to_ins(double H[9]); 274e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 275e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 276e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Reset the display reference to the current frame. 277e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 278e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void ResetDisplayReference(); 279e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 280e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 281e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Estimate a secondary motion model starting from the specified transformation. 282e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param H the primary motion model to start from 283e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 284e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void EstimateSecondaryModel(double H[9]); 285e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 286e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen /*! 287e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * 288e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 289e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void SelectOutliers(); 290e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 291e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen char *profile_string; 292e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 293e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenprotected: 294e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void Clean(); 295e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void GenerateQuarterResImage(const unsigned char* const * im); 296e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 297e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_im_width; 298e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_im_height; 299e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 300e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // RANSAC and refinement parameters: 301e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_homography_type; 302e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_max_iterations; 303e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double m_scale; 304e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_nr_samples; 305e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_chunk_size; 306e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double m_outlier_t2; 307e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 308e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Whether to fit a linear model to just the inliers at the end 309e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool m_linear_polish; 310e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double m_polish_C[36]; 311e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double m_polish_D[6]; 312e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 313e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // local state 314e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool m_current_is_reference; 315e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool m_initialized; 316e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 317e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // inspection to reference homography: 318e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double m_H_ref_to_ins[9]; 319e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double m_H_dref_to_ref[9]; 320e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 321e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // feature extraction and matching: 322e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen db_CornerDetector_u m_cd; 323e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen db_Matcher_u m_cm; 324e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 325e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // length of corner arrays: 326e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned long m_max_nr_corners; 327e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 328e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // corner locations of reference image features: 329e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double * m_x_corners_ref; 330e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double * m_y_corners_ref; 331e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_nr_corners_ref; 332e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 333e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // corner locations of inspection image features: 334e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double * m_x_corners_ins; 335e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double * m_y_corners_ins; 336e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_nr_corners_ins; 337e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 338e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // length of match index arrays: 339e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned long m_max_nr_matches; 340e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 341e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // match indices: 342e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int * m_match_index_ref; 343e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int * m_match_index_ins; 344e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_nr_matches; 345e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 346e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // pointer to internal copy of the reference image: 347e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned char ** m_reference_image; 348e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 349e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // pointer to internal copy of last aligned inspection image: 350e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned char ** m_aligned_ins_image; 351e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 352e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // pointer to quarter resolution image, if used. 353e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned char** m_quarter_res_image; 354e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 355e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // temporary storage for the quarter resolution image processing 356e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned char** m_horz_smooth_subsample_image; 357e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 358e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // temporary space for homography computation: 359e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double * m_temp_double; 360e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int * m_temp_int; 361e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 362e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // homogenous image point arrays: 363e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double * m_corners_ref; 364e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double * m_corners_ins; 365e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 366e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Indices of the points within the match lists 367e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int * m_inlier_indices; 368e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_num_inlier_indices; 369e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 370e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen //void ComputeInliers(double H[9], std::vector<int> &inlier_indices); 371e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void ComputeInliers(double H[9]); 372e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 373e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // cost arrays: 374e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void ComputeCostArray(); 375e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool m_sq_cost_computed; 376e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double * m_sq_cost; 377e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 378e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // cost histogram: 379e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void ComputeCostHistogram(); 380e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int *m_cost_histogram; 381e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 382e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void SetOutlierThreshold(); 383e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 384e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // utility function for smoothing the motion parameters. 385e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen void SmoothMotion(void); 386e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 387e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenprivate: 388e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double m_K[9]; 389e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen const int m_over_allocation; 390e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 391e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool m_reference_set; 392e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 393e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Maximum number of inliers seen until now w.r.t the current reference frame 394e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_max_inlier_count; 395e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 396e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Number of cost histogram bins: 397e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_nr_bins; 398e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // All costs above this threshold get put into the last bin: 399e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int m_max_cost_pix; 400e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 401e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // whether to quarter the image resolution for processing, or not 402e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool m_quarter_resolution; 403e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 404e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // the period (in number of frames) for reference update. 405e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned int m_reference_update_period; 406e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 407e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // the number of frames processed so far. 408e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned int m_nr_frames_processed; 409e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 410e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // smoother for motion transformations 411e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen db_StabilizationSmoother m_stab_smoother; 412e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 413e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // boolean to control whether motion smoothing occurs (or not) 414e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen bool m_do_motion_smoothing; 415e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 416e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // double to set the gain for motion smoothing 417e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double m_motion_smoothing_gain; 418e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen}; 419e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen/*! 420e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen Create look-up tables to undistort images. Only Bougeut (Matlab toolkit) 421e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen is currently supported. Can be used with db_WarpImageLut_u(). 422e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \code 423e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen xd = H*xs; 424e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen xd = xd/xd(3); 425e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \endcode 426e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \param lut_x pre-allocated float image 427e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \param lut_y pre-allocated float image 428e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \param w width 429e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \param h height 430e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \param H image homography from source to destination 431e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 432e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Cheninline void db_GenerateHomographyLut(float ** lut_x,float ** lut_y,int w,int h,const double H[9]) 433e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 434e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen assert(lut_x && lut_y); 435e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double x[3] = {0.0,0.0,1.0}; 436e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double xb[3]; 437e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 438e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen/* 439e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double xl[3]; 440e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 441e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen // Determine the output coordinate system ROI 442e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double Hinv[9]; 443e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen db_InvertAffineTransform(Hinv,H); 444e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen db_Multiply3x3_3x1(xl, Hinv, x); 445e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen xl[0] = db_SafeDivision(xl[0],xl[2]); 446e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen xl[1] = db_SafeDivision(xl[1],xl[2]); 447e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen*/ 448e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 449e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for ( int i = 0; i < w; ++i ) 450e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for ( int j = 0; j < h; ++j ) 451e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 452e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen x[0] = double(i); 453e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen x[1] = double(j); 454e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen db_Multiply3x3_3x1(xb, H, x); 455e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen xb[0] = db_SafeDivision(xb[0],xb[2]); 456e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen xb[1] = db_SafeDivision(xb[1],xb[2]); 457e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 458e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen lut_x[j][i] = float(xb[0]); 459e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen lut_y[j][i] = float(xb[1]); 460e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 461e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 462e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 463e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen/*! 464e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * Perform a look-up table warp for packed RGB ([rgbrgbrgb...]) images. 465e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * The LUTs must be float images of the same size as source image. 466e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * The source value x_s is determined from destination (x_d,y_d) through lut_x 467e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * and y_s is determined from lut_y: 468e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \code 469e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen x_s = lut_x[y_d][x_d]; 470e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen y_s = lut_y[y_d][x_d]; 471e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen \endcode 472e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 473e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param src source image (w*3 by h) 474e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param dst destination image (w*3 by h) 475e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param w width 476e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param h height 477e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param lut_x LUT for x 478e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen * \param lut_y LUT for y 479e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen */ 480e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Cheninline void db_WarpImageLutFast_rgb(const unsigned char * const * src, unsigned char ** dst, int w, int h, 481e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen const float * const * lut_x, const float * const * lut_y) 482e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 483e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen assert(src && dst); 484e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int xd=0, yd=0; 485e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 486e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for ( int i = 0; i < w; ++i ) 487e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for ( int j = 0; j < h; ++j ) 488e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 489e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen xd = static_cast<unsigned int>(lut_x[j][i]); 490e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen yd = static_cast<unsigned int>(lut_y[j][i]); 491e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if ( xd >= w || yd >= h || 492e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen xd < 0 || yd < 0) 493e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 494e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i ] = 0; 495e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i+1] = 0; 496e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i+2] = 0; 497e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 498e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 499e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 500e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i ] = src[yd][3*xd ]; 501e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i+1] = src[yd][3*xd+1]; 502e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i+2] = src[yd][3*xd+2]; 503e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 504e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 505e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 506e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 507e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Cheninline unsigned char db_BilinearInterpolationRGB(double y, double x, const unsigned char * const * v, int offset) 508e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 509e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int floor_x=(int) x; 510e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int floor_y=(int) y; 511e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 512e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int ceil_x=floor_x+1; 513e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen int ceil_y=floor_y+1; 514e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 515e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned char f00 = v[floor_y][3*floor_x+offset]; 516e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned char f01 = v[floor_y][3*ceil_x+offset]; 517e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned char f10 = v[ceil_y][3*floor_x+offset]; 518e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen unsigned char f11 = v[ceil_y][3*ceil_x+offset]; 519e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 520e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double xl = x-floor_x; 521e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double yl = y-floor_y; 522e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 523e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return (unsigned char)(f00*(1-yl)*(1-xl) + f10*yl*(1-xl) + f01*(1-yl)*xl + f11*yl*xl); 524e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 525e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 526e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Cheninline void db_WarpImageLutBilinear_rgb(const unsigned char * const * src, unsigned char ** dst, int w, int h, 527e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen const float * const * lut_x, const float * const * lut_y) 528e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 529e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen assert(src && dst); 530e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double xd=0.0, yd=0.0; 531e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 532e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for ( int i = 0; i < w; ++i ) 533e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen for ( int j = 0; j < h; ++j ) 534e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 535e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen xd = static_cast<double>(lut_x[j][i]); 536e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen yd = static_cast<double>(lut_y[j][i]); 537e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen if ( xd > w-2 || yd > h-2 || 538e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen xd < 0.0 || yd < 0.0) 539e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 540e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i ] = 0; 541e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i+1] = 0; 542e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i+2] = 0; 543e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 544e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen else 545e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen { 546e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i ] = db_BilinearInterpolationRGB(yd,xd,src,0); 547e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i+1] = db_BilinearInterpolationRGB(yd,xd,src,1); 548e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen dst[j][3*i+2] = db_BilinearInterpolationRGB(yd,xd,src,2); 549e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 550e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen } 551e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 552e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 553e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Cheninline double SquaredInhomogenousHomographyError(double y[3],double H[9],double x[3]){ 554e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double x0,x1,x2,mult; 555e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen double sd; 556e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 557e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen x0=H[0]*x[0]+H[1]*x[1]+H[2]; 558e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen x1=H[3]*x[0]+H[4]*x[1]+H[5]; 559e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen x2=H[6]*x[0]+H[7]*x[1]+H[8]; 560e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen mult=1.0/((x2!=0.0)?x2:1.0); 561e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen sd=(y[0]-x0*mult)*(y[0]-x0*mult)+(y[1]-x1*mult)*(y[1]-x1*mult); 562e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 563e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return(sd); 564e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 565e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 566e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 567e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen// functions related to profiling 568e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#if PROFILE 569e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 570e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen/* return current time in milliseconds */ 571e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chenstatic double 572e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chennow_ms(void) 573e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen{ 574e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen //struct timespec res; 575e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen struct timeval res; 576e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen //clock_gettime(CLOCK_REALTIME, &res); 577e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen gettimeofday(&res, NULL); 578e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen return 1000.0*res.tv_sec + (double)res.tv_usec/1e3; 579e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen} 580e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen 581e295e32b68cf04f0d99138bf4a6d25555f3aef99Wei-Ta Chen#endif 582