| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // $Id: dbreg.cpp,v 1.31 2011/06/17 14:04:32 mbansal Exp $ |
| #include "dbreg.h" |
| #include <string.h> |
| #include <stdio.h> |
| |
| |
| #if PROFILE |
| #endif |
| |
| //#include <iostream> |
| |
| db_FrameToReferenceRegistration::db_FrameToReferenceRegistration() : |
| m_initialized(false),m_nr_matches(0),m_over_allocation(256),m_nr_bins(20),m_max_cost_pix(30), m_quarter_resolution(false) |
| { |
| m_reference_image = NULL; |
| m_aligned_ins_image = NULL; |
| |
| m_quarter_res_image = NULL; |
| m_horz_smooth_subsample_image = NULL; |
| |
| m_x_corners_ref = NULL; |
| m_y_corners_ref = NULL; |
| |
| m_x_corners_ins = NULL; |
| m_y_corners_ins = NULL; |
| |
| m_match_index_ref = NULL; |
| m_match_index_ins = NULL; |
| |
| m_inlier_indices = NULL; |
| |
| m_num_inlier_indices = 0; |
| |
| m_temp_double = NULL; |
| m_temp_int = NULL; |
| |
| m_corners_ref = NULL; |
| m_corners_ins = NULL; |
| |
| m_sq_cost = NULL; |
| m_cost_histogram = NULL; |
| |
| profile_string = NULL; |
| |
| db_Identity3x3(m_K); |
| db_Identity3x3(m_H_ref_to_ins); |
| db_Identity3x3(m_H_dref_to_ref); |
| |
| m_sq_cost_computed = false; |
| m_reference_set = false; |
| |
| m_reference_update_period = 0; |
| m_nr_frames_processed = 0; |
| |
| return; |
| } |
| |
| db_FrameToReferenceRegistration::~db_FrameToReferenceRegistration() |
| { |
| Clean(); |
| } |
| |
| void db_FrameToReferenceRegistration::Clean() |
| { |
| if ( m_reference_image ) |
| db_FreeImage_u(m_reference_image,m_im_height); |
| |
| if ( m_aligned_ins_image ) |
| db_FreeImage_u(m_aligned_ins_image,m_im_height); |
| |
| if ( m_quarter_res_image ) |
| { |
| db_FreeImage_u(m_quarter_res_image, m_im_height); |
| } |
| |
| if ( m_horz_smooth_subsample_image ) |
| { |
| db_FreeImage_u(m_horz_smooth_subsample_image, m_im_height*2); |
| } |
| |
| delete [] m_x_corners_ref; |
| delete [] m_y_corners_ref; |
| |
| delete [] m_x_corners_ins; |
| delete [] m_y_corners_ins; |
| |
| delete [] m_match_index_ref; |
| delete [] m_match_index_ins; |
| |
| delete [] m_temp_double; |
| delete [] m_temp_int; |
| |
| delete [] m_corners_ref; |
| delete [] m_corners_ins; |
| |
| delete [] m_sq_cost; |
| delete [] m_cost_histogram; |
| |
| delete [] m_inlier_indices; |
| |
| if(profile_string) |
| delete [] profile_string; |
| |
| m_reference_image = NULL; |
| m_aligned_ins_image = NULL; |
| |
| m_quarter_res_image = NULL; |
| m_horz_smooth_subsample_image = NULL; |
| |
| m_x_corners_ref = NULL; |
| m_y_corners_ref = NULL; |
| |
| m_x_corners_ins = NULL; |
| m_y_corners_ins = NULL; |
| |
| m_match_index_ref = NULL; |
| m_match_index_ins = NULL; |
| |
| m_inlier_indices = NULL; |
| |
| m_temp_double = NULL; |
| m_temp_int = NULL; |
| |
| m_corners_ref = NULL; |
| m_corners_ins = NULL; |
| |
| m_sq_cost = NULL; |
| m_cost_histogram = NULL; |
| } |
| |
| void db_FrameToReferenceRegistration::Init(int width, int height, |
| int homography_type, |
| int max_iterations, |
| bool linear_polish, |
| bool quarter_resolution, |
| double scale, |
| unsigned int reference_update_period, |
| bool do_motion_smoothing, |
| double motion_smoothing_gain, |
| int nr_samples, |
| int chunk_size, |
| int cd_target_nr_corners, |
| double cm_max_disparity, |
| bool cm_use_smaller_matching_window, |
| int cd_nr_horz_blocks, |
| int cd_nr_vert_blocks |
| ) |
| { |
| Clean(); |
| |
| m_reference_update_period = reference_update_period; |
| m_nr_frames_processed = 0; |
| |
| m_do_motion_smoothing = do_motion_smoothing; |
| m_motion_smoothing_gain = motion_smoothing_gain; |
| |
| m_stab_smoother.setSmoothingFactor(m_motion_smoothing_gain); |
| |
| m_quarter_resolution = quarter_resolution; |
| |
| profile_string = new char[10240]; |
| |
| if (m_quarter_resolution == true) |
| { |
| width = width/2; |
| height = height/2; |
| |
| m_horz_smooth_subsample_image = db_AllocImage_u(width,height*2,m_over_allocation); |
| m_quarter_res_image = db_AllocImage_u(width,height,m_over_allocation); |
| } |
| |
| m_im_width = width; |
| m_im_height = height; |
| |
| double temp[9]; |
| db_Approx3DCalMat(m_K,temp,m_im_width,m_im_height); |
| |
| m_homography_type = homography_type; |
| m_max_iterations = max_iterations; |
| m_scale = 2/(m_K[0]+m_K[4]); |
| m_nr_samples = nr_samples; |
| m_chunk_size = chunk_size; |
| |
| double outlier_t1 = 5.0; |
| |
| m_outlier_t2 = outlier_t1*outlier_t1;//*m_scale*m_scale; |
| |
| m_current_is_reference = false; |
| |
| m_linear_polish = linear_polish; |
| |
| m_reference_image = db_AllocImage_u(m_im_width,m_im_height,m_over_allocation); |
| m_aligned_ins_image = db_AllocImage_u(m_im_width,m_im_height,m_over_allocation); |
| |
| // initialize feature detection and matching: |
| //m_max_nr_corners = m_cd.Init(m_im_width,m_im_height,cd_target_nr_corners,cd_nr_horz_blocks,cd_nr_vert_blocks,0.0,0.0); |
| m_max_nr_corners = m_cd.Init(m_im_width,m_im_height,cd_target_nr_corners,cd_nr_horz_blocks,cd_nr_vert_blocks,DB_DEFAULT_ABS_CORNER_THRESHOLD/500.0,0.0); |
| |
| int use_21 = 0; |
| m_max_nr_matches = m_cm.Init(m_im_width,m_im_height,cm_max_disparity,m_max_nr_corners,DB_DEFAULT_NO_DISPARITY,cm_use_smaller_matching_window,use_21); |
| |
| // allocate space for corner feature locations for reference and inspection images: |
| m_x_corners_ref = new double [m_max_nr_corners]; |
| m_y_corners_ref = new double [m_max_nr_corners]; |
| |
| m_x_corners_ins = new double [m_max_nr_corners]; |
| m_y_corners_ins = new double [m_max_nr_corners]; |
| |
| // allocate space for match indices: |
| m_match_index_ref = new int [m_max_nr_matches]; |
| m_match_index_ins = new int [m_max_nr_matches]; |
| |
| m_temp_double = new double [12*DB_DEFAULT_NR_SAMPLES+10*m_max_nr_matches]; |
| m_temp_int = new int [db_maxi(DB_DEFAULT_NR_SAMPLES,m_max_nr_matches)]; |
| |
| // allocate space for homogenous image points: |
| m_corners_ref = new double [3*m_max_nr_corners]; |
| m_corners_ins = new double [3*m_max_nr_corners]; |
| |
| // allocate cost array and histogram: |
| m_sq_cost = new double [m_max_nr_matches]; |
| m_cost_histogram = new int [m_nr_bins]; |
| |
| // reserve array: |
| //m_inlier_indices.reserve(m_max_nr_matches); |
| m_inlier_indices = new int[m_max_nr_matches]; |
| |
| m_initialized = true; |
| |
| m_max_inlier_count = 0; |
| } |
| |
| |
| #define MB 0 |
| // Save the reference image, detect features and update the dref-to-ref transformation |
| int db_FrameToReferenceRegistration::UpdateReference(const unsigned char * const * im, bool subsample, bool detect_corners) |
| { |
| double temp[9]; |
| db_Multiply3x3_3x3(temp,m_H_dref_to_ref,m_H_ref_to_ins); |
| db_Copy9(m_H_dref_to_ref,temp); |
| |
| const unsigned char * const * imptr = im; |
| |
| if (m_quarter_resolution && subsample) |
| { |
| GenerateQuarterResImage(im); |
| imptr = m_quarter_res_image; |
| } |
| |
| // save the reference image, detect features and quit |
| db_CopyImage_u(m_reference_image,imptr,m_im_width,m_im_height,m_over_allocation); |
| |
| if(detect_corners) |
| { |
| #if MB |
| m_cd.DetectCorners(imptr, m_x_corners_ref,m_y_corners_ref,&m_nr_corners_ref); |
| int nr = 0; |
| for(int k=0; k<m_nr_corners_ref; k++) |
| { |
| if(m_x_corners_ref[k]>m_im_width/3) |
| { |
| m_x_corners_ref[nr] = m_x_corners_ref[k]; |
| m_y_corners_ref[nr] = m_y_corners_ref[k]; |
| nr++; |
| } |
| |
| } |
| m_nr_corners_ref = nr; |
| #else |
| m_cd.DetectCorners(imptr, m_x_corners_ref,m_y_corners_ref,&m_nr_corners_ref); |
| #endif |
| } |
| else |
| { |
| m_nr_corners_ref = m_nr_corners_ins; |
| |
| for(int k=0; k<m_nr_corners_ins; k++) |
| { |
| m_x_corners_ref[k] = m_x_corners_ins[k]; |
| m_y_corners_ref[k] = m_y_corners_ins[k]; |
| } |
| |
| } |
| |
| db_Identity3x3(m_H_ref_to_ins); |
| |
| m_max_inlier_count = 0; // Reset to 0 as no inliers seen until now |
| m_sq_cost_computed = false; |
| m_reference_set = true; |
| m_current_is_reference = true; |
| return 1; |
| } |
| |
| void db_FrameToReferenceRegistration::Get_H_dref_to_ref(double H[9]) |
| { |
| db_Copy9(H,m_H_dref_to_ref); |
| } |
| |
| void db_FrameToReferenceRegistration::Get_H_dref_to_ins(double H[9]) |
| { |
| db_Multiply3x3_3x3(H,m_H_dref_to_ref,m_H_ref_to_ins); |
| } |
| |
| void db_FrameToReferenceRegistration::Set_H_dref_to_ins(double H[9]) |
| { |
| double H_ins_to_ref[9]; |
| |
| db_Identity3x3(H_ins_to_ref); // Ensure it has proper values |
| db_InvertAffineTransform(H_ins_to_ref,m_H_ref_to_ins); // Invert to get ins to ref |
| db_Multiply3x3_3x3(m_H_dref_to_ref,H,H_ins_to_ref); // Update dref to ref using the input H from dref to ins |
| } |
| |
| |
| void db_FrameToReferenceRegistration::ResetDisplayReference() |
| { |
| db_Identity3x3(m_H_dref_to_ref); |
| } |
| |
| bool db_FrameToReferenceRegistration::NeedReferenceUpdate() |
| { |
| // If less than 50% of the starting number of inliers left, then its time to update the reference. |
| if(m_max_inlier_count>0 && float(m_num_inlier_indices)/float(m_max_inlier_count)<0.5) |
| return true; |
| else |
| return false; |
| } |
| |
| int db_FrameToReferenceRegistration::AddFrame(const unsigned char * const * im, double H[9],bool force_reference,bool prewarp) |
| { |
| m_current_is_reference = false; |
| if(!m_reference_set || force_reference) |
| { |
| db_Identity3x3(m_H_ref_to_ins); |
| db_Copy9(H,m_H_ref_to_ins); |
| |
| UpdateReference(im,true,true); |
| return 0; |
| } |
| |
| const unsigned char * const * imptr = im; |
| |
| if (m_quarter_resolution) |
| { |
| if (m_quarter_res_image) |
| { |
| GenerateQuarterResImage(im); |
| } |
| |
| imptr = (const unsigned char * const* )m_quarter_res_image; |
| } |
| |
| double H_last[9]; |
| db_Copy9(H_last,m_H_ref_to_ins); |
| db_Identity3x3(m_H_ref_to_ins); |
| |
| m_sq_cost_computed = false; |
| |
| // detect corners on inspection image and match to reference image features:s |
| |
| // @jke - Adding code to time the functions. TODO: Remove after test |
| #if PROFILE |
| double iTimer1, iTimer2; |
| char str[255]; |
| strcpy(profile_string,"\n"); |
| sprintf(str,"[%dx%d] %p\n",m_im_width,m_im_height,im); |
| strcat(profile_string, str); |
| #endif |
| |
| // @jke - Adding code to time the functions. TODO: Remove after test |
| #if PROFILE |
| iTimer1 = now_ms(); |
| #endif |
| m_cd.DetectCorners(imptr, m_x_corners_ins,m_y_corners_ins,&m_nr_corners_ins); |
| // @jke - Adding code to time the functions. TODO: Remove after test |
| # if PROFILE |
| iTimer2 = now_ms(); |
| double elapsedTimeCorner = iTimer2 - iTimer1; |
| sprintf(str,"Corner Detection [%d corners] = %g ms\n",m_nr_corners_ins, elapsedTimeCorner); |
| strcat(profile_string, str); |
| #endif |
| |
| // @jke - Adding code to time the functions. TODO: Remove after test |
| #if PROFILE |
| iTimer1 = now_ms(); |
| #endif |
| if(prewarp) |
| m_cm.Match(m_reference_image,imptr,m_x_corners_ref,m_y_corners_ref,m_nr_corners_ref, |
| m_x_corners_ins,m_y_corners_ins,m_nr_corners_ins, |
| m_match_index_ref,m_match_index_ins,&m_nr_matches,H,0); |
| else |
| m_cm.Match(m_reference_image,imptr,m_x_corners_ref,m_y_corners_ref,m_nr_corners_ref, |
| m_x_corners_ins,m_y_corners_ins,m_nr_corners_ins, |
| m_match_index_ref,m_match_index_ins,&m_nr_matches); |
| // @jke - Adding code to time the functions. TODO: Remove after test |
| # if PROFILE |
| iTimer2 = now_ms(); |
| double elapsedTimeMatch = iTimer2 - iTimer1; |
| sprintf(str,"Matching [%d] = %g ms\n",m_nr_matches,elapsedTimeMatch); |
| strcat(profile_string, str); |
| #endif |
| |
| |
| // copy out matching features: |
| for ( int i = 0; i < m_nr_matches; ++i ) |
| { |
| int offset = 3*i; |
| m_corners_ref[offset ] = m_x_corners_ref[m_match_index_ref[i]]; |
| m_corners_ref[offset+1] = m_y_corners_ref[m_match_index_ref[i]]; |
| m_corners_ref[offset+2] = 1.0; |
| |
| m_corners_ins[offset ] = m_x_corners_ins[m_match_index_ins[i]]; |
| m_corners_ins[offset+1] = m_y_corners_ins[m_match_index_ins[i]]; |
| m_corners_ins[offset+2] = 1.0; |
| } |
| |
| // @jke - Adding code to time the functions. TODO: Remove after test |
| #if PROFILE |
| iTimer1 = now_ms(); |
| #endif |
| // perform the alignment: |
| db_RobImageHomography(m_H_ref_to_ins, m_corners_ref, m_corners_ins, m_nr_matches, m_K, m_K, m_temp_double, m_temp_int, |
| m_homography_type,NULL,m_max_iterations,m_max_nr_matches,m_scale, |
| m_nr_samples, m_chunk_size); |
| // @jke - Adding code to time the functions. TODO: Remove after test |
| # if PROFILE |
| iTimer2 = now_ms(); |
| double elapsedTimeHomography = iTimer2 - iTimer1; |
| sprintf(str,"Homography = %g ms\n",elapsedTimeHomography); |
| strcat(profile_string, str); |
| #endif |
| |
| |
| SetOutlierThreshold(); |
| |
| // Compute the inliers for the db compute m_H_ref_to_ins |
| ComputeInliers(m_H_ref_to_ins); |
| |
| // Update the max inlier count |
| m_max_inlier_count = (m_max_inlier_count > m_num_inlier_indices)?m_max_inlier_count:m_num_inlier_indices; |
| |
| // Fit a least-squares model to just the inliers and put it in m_H_ref_to_ins |
| if(m_linear_polish) |
| Polish(m_inlier_indices, m_num_inlier_indices); |
| |
| if (m_quarter_resolution) |
| { |
| m_H_ref_to_ins[2] *= 2.0; |
| m_H_ref_to_ins[5] *= 2.0; |
| } |
| |
| #if PROFILE |
| sprintf(str,"#Inliers = %d \n",m_num_inlier_indices); |
| strcat(profile_string, str); |
| #endif |
| /* |
| ///// CHECK IF CURRENT TRANSFORMATION GOOD OR BAD //// |
| ///// IF BAD, then update reference to the last correctly aligned inspection frame; |
| if(m_num_inlier_indices<5)//0.9*m_nr_matches || m_nr_matches < 20) |
| { |
| db_Copy9(m_H_ref_to_ins,H_last); |
| UpdateReference(imptr,false); |
| // UpdateReference(m_aligned_ins_image,false); |
| } |
| else |
| { |
| ///// IF GOOD, then update the last correctly aligned inspection frame to be this; |
| //db_CopyImage_u(m_aligned_ins_image,imptr,m_im_width,m_im_height,m_over_allocation); |
| */ |
| if(m_do_motion_smoothing) |
| SmoothMotion(); |
| |
| db_PrintDoubleMatrix(m_H_ref_to_ins,3,3); |
| |
| db_Copy9(H, m_H_ref_to_ins); |
| |
| m_nr_frames_processed++; |
| { |
| if ( (m_nr_frames_processed % m_reference_update_period) == 0 ) |
| { |
| //UpdateReference(imptr,false, false); |
| |
| #if MB |
| UpdateReference(imptr,false, true); |
| #else |
| UpdateReference(imptr,false, false); |
| #endif |
| } |
| |
| |
| } |
| |
| |
| |
| return 1; |
| } |
| |
| //void db_FrameToReferenceRegistration::ComputeInliers(double H[9],std::vector<int> &inlier_indices) |
| void db_FrameToReferenceRegistration::ComputeInliers(double H[9]) |
| { |
| double totnummatches = m_nr_matches; |
| int inliercount=0; |
| |
| m_num_inlier_indices = 0; |
| // inlier_indices.clear(); |
| |
| for(int c=0; c < totnummatches; c++ ) |
| { |
| if (m_sq_cost[c] <= m_outlier_t2) |
| { |
| m_inlier_indices[inliercount] = c; |
| inliercount++; |
| } |
| } |
| |
| m_num_inlier_indices = inliercount; |
| double frac=inliercount/totnummatches; |
| } |
| |
| //void db_FrameToReferenceRegistration::Polish(std::vector<int> &inlier_indices) |
| void db_FrameToReferenceRegistration::Polish(int *inlier_indices, int &num_inlier_indices) |
| { |
| db_Zero(m_polish_C,36); |
| db_Zero(m_polish_D,6); |
| for (int i=0;i<num_inlier_indices;i++) |
| { |
| int j = 3*inlier_indices[i]; |
| m_polish_C[0]+=m_corners_ref[j]*m_corners_ref[j]; |
| m_polish_C[1]+=m_corners_ref[j]*m_corners_ref[j+1]; |
| m_polish_C[2]+=m_corners_ref[j]; |
| m_polish_C[7]+=m_corners_ref[j+1]*m_corners_ref[j+1]; |
| m_polish_C[8]+=m_corners_ref[j+1]; |
| m_polish_C[14]+=1; |
| m_polish_D[0]+=m_corners_ref[j]*m_corners_ins[j]; |
| m_polish_D[1]+=m_corners_ref[j+1]*m_corners_ins[j]; |
| m_polish_D[2]+=m_corners_ins[j]; |
| m_polish_D[3]+=m_corners_ref[j]*m_corners_ins[j+1]; |
| m_polish_D[4]+=m_corners_ref[j+1]*m_corners_ins[j+1]; |
| m_polish_D[5]+=m_corners_ins[j+1]; |
| } |
| |
| double a=db_maxd(m_polish_C[0],m_polish_C[7]); |
| m_polish_C[0]/=a; m_polish_C[1]/=a; m_polish_C[2]/=a; |
| m_polish_C[7]/=a; m_polish_C[8]/=a; m_polish_C[14]/=a; |
| |
| m_polish_D[0]/=a; m_polish_D[1]/=a; m_polish_D[2]/=a; |
| m_polish_D[3]/=a; m_polish_D[4]/=a; m_polish_D[5]/=a; |
| |
| |
| m_polish_C[6]=m_polish_C[1]; |
| m_polish_C[12]=m_polish_C[2]; |
| m_polish_C[13]=m_polish_C[8]; |
| |
| m_polish_C[21]=m_polish_C[0]; m_polish_C[22]=m_polish_C[1]; m_polish_C[23]=m_polish_C[2]; |
| m_polish_C[28]=m_polish_C[7]; m_polish_C[29]=m_polish_C[8]; |
| m_polish_C[35]=m_polish_C[14]; |
| |
| |
| double d[6]; |
| db_CholeskyDecomp6x6(m_polish_C,d); |
| db_CholeskyBacksub6x6(m_H_ref_to_ins,m_polish_C,d,m_polish_D); |
| } |
| |
| void db_FrameToReferenceRegistration::EstimateSecondaryModel(double H[9]) |
| { |
| /* if ( m_current_is_reference ) |
| { |
| db_Identity3x3(H); |
| return; |
| } |
| */ |
| |
| // select the outliers of the current model: |
| SelectOutliers(); |
| |
| // perform the alignment: |
| db_RobImageHomography(m_H_ref_to_ins, m_corners_ref, m_corners_ins, m_nr_matches, m_K, m_K, m_temp_double, m_temp_int, |
| m_homography_type,NULL,m_max_iterations,m_max_nr_matches,m_scale, |
| m_nr_samples, m_chunk_size); |
| |
| db_Copy9(H,m_H_ref_to_ins); |
| } |
| |
| void db_FrameToReferenceRegistration::ComputeCostArray() |
| { |
| if ( m_sq_cost_computed ) return; |
| |
| for( int c=0, k=0 ;c < m_nr_matches; c++, k=k+3) |
| { |
| m_sq_cost[c] = SquaredInhomogenousHomographyError(m_corners_ins+k,m_H_ref_to_ins,m_corners_ref+k); |
| } |
| |
| m_sq_cost_computed = true; |
| } |
| |
| void db_FrameToReferenceRegistration::SelectOutliers() |
| { |
| int nr_outliers=0; |
| |
| ComputeCostArray(); |
| |
| for(int c=0, k=0 ;c<m_nr_matches;c++,k=k+3) |
| { |
| if (m_sq_cost[c] > m_outlier_t2) |
| { |
| int offset = 3*nr_outliers++; |
| db_Copy3(m_corners_ref+offset,m_corners_ref+k); |
| db_Copy3(m_corners_ins+offset,m_corners_ins+k); |
| } |
| } |
| |
| m_nr_matches = nr_outliers; |
| } |
| |
| void db_FrameToReferenceRegistration::ComputeCostHistogram() |
| { |
| ComputeCostArray(); |
| |
| for ( int b = 0; b < m_nr_bins; ++b ) |
| m_cost_histogram[b] = 0; |
| |
| for(int c = 0; c < m_nr_matches; c++) |
| { |
| double error = db_SafeSqrt(m_sq_cost[c]); |
| int bin = (int)(error/m_max_cost_pix*m_nr_bins); |
| if ( bin < m_nr_bins ) |
| m_cost_histogram[bin]++; |
| else |
| m_cost_histogram[m_nr_bins-1]++; |
| } |
| |
| /* |
| for ( int i = 0; i < m_nr_bins; ++i ) |
| std::cout << m_cost_histogram[i] << " "; |
| std::cout << std::endl; |
| */ |
| } |
| |
| void db_FrameToReferenceRegistration::SetOutlierThreshold() |
| { |
| ComputeCostHistogram(); |
| |
| int i = 0, last=0; |
| for (; i < m_nr_bins-1; ++i ) |
| { |
| if ( last > m_cost_histogram[i] ) |
| break; |
| last = m_cost_histogram[i]; |
| } |
| |
| //std::cout << "I " << i << std::endl; |
| |
| int max = m_cost_histogram[i]; |
| |
| for (; i < m_nr_bins-1; ++i ) |
| { |
| if ( m_cost_histogram[i] < (int)(0.1*max) ) |
| //if ( last < m_cost_histogram[i] ) |
| break; |
| last = m_cost_histogram[i]; |
| } |
| //std::cout << "J " << i << std::endl; |
| |
| m_outlier_t2 = db_sqr(i*m_max_cost_pix/m_nr_bins); |
| |
| //std::cout << "m_outlier_t2 " << m_outlier_t2 << std::endl; |
| } |
| |
| void db_FrameToReferenceRegistration::SmoothMotion(void) |
| { |
| VP_MOTION inmot,outmot; |
| |
| double H[9]; |
| |
| Get_H_dref_to_ins(H); |
| |
| MXX(inmot) = H[0]; |
| MXY(inmot) = H[1]; |
| MXZ(inmot) = H[2]; |
| MXW(inmot) = 0.0; |
| |
| MYX(inmot) = H[3]; |
| MYY(inmot) = H[4]; |
| MYZ(inmot) = H[5]; |
| MYW(inmot) = 0.0; |
| |
| MZX(inmot) = H[6]; |
| MZY(inmot) = H[7]; |
| MZZ(inmot) = H[8]; |
| MZW(inmot) = 0.0; |
| |
| MWX(inmot) = 0.0; |
| MWY(inmot) = 0.0; |
| MWZ(inmot) = 0.0; |
| MWW(inmot) = 1.0; |
| |
| inmot.type = VP_MOTION_AFFINE; |
| |
| int w = m_im_width; |
| int h = m_im_height; |
| |
| if(m_quarter_resolution) |
| { |
| w = w*2; |
| h = h*2; |
| } |
| |
| #if 0 |
| m_stab_smoother.smoothMotionAdaptive(w,h,&inmot,&outmot); |
| #else |
| m_stab_smoother.smoothMotion(&inmot,&outmot); |
| #endif |
| |
| H[0] = MXX(outmot); |
| H[1] = MXY(outmot); |
| H[2] = MXZ(outmot); |
| |
| H[3] = MYX(outmot); |
| H[4] = MYY(outmot); |
| H[5] = MYZ(outmot); |
| |
| H[6] = MZX(outmot); |
| H[7] = MZY(outmot); |
| H[8] = MZZ(outmot); |
| |
| Set_H_dref_to_ins(H); |
| } |
| |
| void db_FrameToReferenceRegistration::GenerateQuarterResImage(const unsigned char* const* im) |
| { |
| int input_h = m_im_height*2; |
| int input_w = m_im_width*2; |
| |
| for (int j = 0; j < input_h; j++) |
| { |
| const unsigned char* in_row_ptr = im[j]; |
| unsigned char* out_row_ptr = m_horz_smooth_subsample_image[j]+1; |
| |
| for (int i = 2; i < input_w-2; i += 2) |
| { |
| int smooth_val = ( |
| 6*in_row_ptr[i] + |
| ((in_row_ptr[i-1]+in_row_ptr[i+1])<<2) + |
| in_row_ptr[i-2]+in_row_ptr[i+2] |
| ) >> 4; |
| *out_row_ptr++ = (unsigned char) smooth_val; |
| |
| if ( (smooth_val < 0) || (smooth_val > 255)) |
| { |
| return; |
| } |
| |
| } |
| } |
| |
| for (int j = 2; j < input_h-2; j+=2) |
| { |
| |
| unsigned char* in_row_ptr = m_horz_smooth_subsample_image[j]; |
| unsigned char* out_row_ptr = m_quarter_res_image[j/2]; |
| |
| for (int i = 1; i < m_im_width-1; i++) |
| { |
| int smooth_val = ( |
| 6*in_row_ptr[i] + |
| ((in_row_ptr[i-m_im_width]+in_row_ptr[i+m_im_width]) << 2)+ |
| in_row_ptr[i-2*m_im_width]+in_row_ptr[i+2*m_im_width] |
| ) >> 4; |
| *out_row_ptr++ = (unsigned char)smooth_val; |
| |
| if ( (smooth_val < 0) || (smooth_val > 255)) |
| { |
| return; |
| } |
| |
| } |
| } |
| } |