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