• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // $Id: dbreg.cpp,v 1.31 2011/06/17 14:04:32 mbansal Exp $
18 #include "dbreg.h"
19 #include <string.h>
20 #include <stdio.h>
21 
22 
23 #if PROFILE
24 #endif
25 
26 //#include <iostream>
27 
db_FrameToReferenceRegistration()28 db_FrameToReferenceRegistration::db_FrameToReferenceRegistration() :
29   m_initialized(false),m_nr_matches(0),m_over_allocation(256),m_nr_bins(20),m_max_cost_pix(30), m_quarter_resolution(false)
30 {
31   m_reference_image = NULL;
32   m_aligned_ins_image = NULL;
33 
34   m_quarter_res_image = NULL;
35   m_horz_smooth_subsample_image = NULL;
36 
37   m_x_corners_ref = NULL;
38   m_y_corners_ref = NULL;
39 
40   m_x_corners_ins = NULL;
41   m_y_corners_ins = NULL;
42 
43   m_match_index_ref = NULL;
44   m_match_index_ins = NULL;
45 
46   m_inlier_indices = NULL;
47 
48   m_num_inlier_indices = 0;
49 
50   m_temp_double = NULL;
51   m_temp_int = NULL;
52 
53   m_corners_ref = NULL;
54   m_corners_ins = NULL;
55 
56   m_sq_cost = NULL;
57   m_cost_histogram = NULL;
58 
59   profile_string = NULL;
60 
61   db_Identity3x3(m_K);
62   db_Identity3x3(m_H_ref_to_ins);
63   db_Identity3x3(m_H_dref_to_ref);
64 
65   m_sq_cost_computed = false;
66   m_reference_set = false;
67 
68   m_reference_update_period = 0;
69   m_nr_frames_processed = 0;
70 
71   return;
72 }
73 
~db_FrameToReferenceRegistration()74 db_FrameToReferenceRegistration::~db_FrameToReferenceRegistration()
75 {
76   Clean();
77 }
78 
Clean()79 void db_FrameToReferenceRegistration::Clean()
80 {
81   if ( m_reference_image )
82     db_FreeImage_u(m_reference_image,m_im_height);
83 
84   if ( m_aligned_ins_image )
85     db_FreeImage_u(m_aligned_ins_image,m_im_height);
86 
87   if ( m_quarter_res_image )
88   {
89     db_FreeImage_u(m_quarter_res_image, m_im_height);
90   }
91 
92   if ( m_horz_smooth_subsample_image )
93   {
94     db_FreeImage_u(m_horz_smooth_subsample_image, m_im_height*2);
95   }
96 
97   delete [] m_x_corners_ref;
98   delete [] m_y_corners_ref;
99 
100   delete [] m_x_corners_ins;
101   delete [] m_y_corners_ins;
102 
103   delete [] m_match_index_ref;
104   delete [] m_match_index_ins;
105 
106   delete [] m_temp_double;
107   delete [] m_temp_int;
108 
109   delete [] m_corners_ref;
110   delete [] m_corners_ins;
111 
112   delete [] m_sq_cost;
113   delete [] m_cost_histogram;
114 
115   delete [] m_inlier_indices;
116 
117   if(profile_string)
118     delete [] profile_string;
119 
120   m_reference_image = NULL;
121   m_aligned_ins_image = NULL;
122 
123   m_quarter_res_image = NULL;
124   m_horz_smooth_subsample_image = NULL;
125 
126   m_x_corners_ref = NULL;
127   m_y_corners_ref = NULL;
128 
129   m_x_corners_ins = NULL;
130   m_y_corners_ins = NULL;
131 
132   m_match_index_ref = NULL;
133   m_match_index_ins = NULL;
134 
135   m_inlier_indices = NULL;
136 
137   m_temp_double = NULL;
138   m_temp_int = NULL;
139 
140   m_corners_ref = NULL;
141   m_corners_ins = NULL;
142 
143   m_sq_cost = NULL;
144   m_cost_histogram = NULL;
145 }
146 
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)147 void db_FrameToReferenceRegistration::Init(int width, int height,
148                        int    homography_type,
149                        int    max_iterations,
150                        bool   linear_polish,
151                        bool   quarter_resolution,
152                        double scale,
153                        unsigned int reference_update_period,
154                        bool   do_motion_smoothing,
155                        double motion_smoothing_gain,
156                        int    nr_samples,
157                        int    chunk_size,
158                        int    cd_target_nr_corners,
159                        double cm_max_disparity,
160                            bool   cm_use_smaller_matching_window,
161                        int    cd_nr_horz_blocks,
162                        int    cd_nr_vert_blocks
163                        )
164 {
165   Clean();
166 
167   m_reference_update_period = reference_update_period;
168   m_nr_frames_processed = 0;
169 
170   m_do_motion_smoothing = do_motion_smoothing;
171   m_motion_smoothing_gain = motion_smoothing_gain;
172 
173   m_stab_smoother.setSmoothingFactor(m_motion_smoothing_gain);
174 
175   m_quarter_resolution = quarter_resolution;
176 
177   profile_string = new char[10240];
178 
179   if (m_quarter_resolution == true)
180   {
181     width = width/2;
182     height = height/2;
183 
184     m_horz_smooth_subsample_image = db_AllocImage_u(width,height*2,m_over_allocation);
185     m_quarter_res_image = db_AllocImage_u(width,height,m_over_allocation);
186   }
187 
188   m_im_width = width;
189   m_im_height = height;
190 
191   double temp[9];
192   db_Approx3DCalMat(m_K,temp,m_im_width,m_im_height);
193 
194   m_homography_type = homography_type;
195   m_max_iterations = max_iterations;
196   m_scale = 2/(m_K[0]+m_K[4]);
197   m_nr_samples = nr_samples;
198   m_chunk_size = chunk_size;
199 
200   double outlier_t1 = 5.0;
201 
202   m_outlier_t2 = outlier_t1*outlier_t1;//*m_scale*m_scale;
203 
204   m_current_is_reference = false;
205 
206   m_linear_polish = linear_polish;
207 
208   m_reference_image = db_AllocImage_u(m_im_width,m_im_height,m_over_allocation);
209   m_aligned_ins_image = db_AllocImage_u(m_im_width,m_im_height,m_over_allocation);
210 
211   // initialize feature detection and matching:
212   //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);
213   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);
214 
215     int use_21 = 0;
216   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);
217 
218   // allocate space for corner feature locations for reference and inspection images:
219   m_x_corners_ref = new double [m_max_nr_corners];
220   m_y_corners_ref = new double [m_max_nr_corners];
221 
222   m_x_corners_ins = new double [m_max_nr_corners];
223   m_y_corners_ins = new double [m_max_nr_corners];
224 
225   // allocate space for match indices:
226   m_match_index_ref = new int [m_max_nr_matches];
227   m_match_index_ins = new int [m_max_nr_matches];
228 
229   m_temp_double = new double [12*DB_DEFAULT_NR_SAMPLES+10*m_max_nr_matches];
230   m_temp_int = new int [db_maxi(DB_DEFAULT_NR_SAMPLES,m_max_nr_matches)];
231 
232   // allocate space for homogenous image points:
233   m_corners_ref = new double [3*m_max_nr_corners];
234   m_corners_ins = new double [3*m_max_nr_corners];
235 
236   // allocate cost array and histogram:
237   m_sq_cost = new double [m_max_nr_matches];
238   m_cost_histogram = new int [m_nr_bins];
239 
240   // reserve array:
241   //m_inlier_indices.reserve(m_max_nr_matches);
242   m_inlier_indices = new int[m_max_nr_matches];
243 
244   m_initialized = true;
245 
246   m_max_inlier_count = 0;
247 }
248 
249 
250 #define MB 0
251 // Save the reference image, detect features and update the dref-to-ref transformation
UpdateReference(const unsigned char * const * im,bool subsample,bool detect_corners)252 int db_FrameToReferenceRegistration::UpdateReference(const unsigned char * const * im, bool subsample, bool detect_corners)
253 {
254   double temp[9];
255   db_Multiply3x3_3x3(temp,m_H_dref_to_ref,m_H_ref_to_ins);
256   db_Copy9(m_H_dref_to_ref,temp);
257 
258   const unsigned char * const * imptr = im;
259 
260   if (m_quarter_resolution && subsample)
261   {
262     GenerateQuarterResImage(im);
263     imptr = m_quarter_res_image;
264   }
265 
266   // save the reference image, detect features and quit
267   db_CopyImage_u(m_reference_image,imptr,m_im_width,m_im_height,m_over_allocation);
268 
269   if(detect_corners)
270   {
271     #if MB
272     m_cd.DetectCorners(imptr, m_x_corners_ref,m_y_corners_ref,&m_nr_corners_ref);
273     int nr = 0;
274     for(int k=0; k<m_nr_corners_ref; k++)
275     {
276         if(m_x_corners_ref[k]>m_im_width/3)
277         {
278             m_x_corners_ref[nr] = m_x_corners_ref[k];
279             m_y_corners_ref[nr] = m_y_corners_ref[k];
280             nr++;
281         }
282 
283     }
284     m_nr_corners_ref = nr;
285     #else
286     m_cd.DetectCorners(imptr, m_x_corners_ref,m_y_corners_ref,&m_nr_corners_ref);
287     #endif
288   }
289   else
290   {
291     m_nr_corners_ref = m_nr_corners_ins;
292 
293     for(int k=0; k<m_nr_corners_ins; k++)
294     {
295         m_x_corners_ref[k] = m_x_corners_ins[k];
296         m_y_corners_ref[k] = m_y_corners_ins[k];
297     }
298 
299   }
300 
301   db_Identity3x3(m_H_ref_to_ins);
302 
303   m_max_inlier_count = 0;   // Reset to 0 as no inliers seen until now
304   m_sq_cost_computed = false;
305   m_reference_set = true;
306   m_current_is_reference = true;
307   return 1;
308 }
309 
Get_H_dref_to_ref(double H[9])310 void db_FrameToReferenceRegistration::Get_H_dref_to_ref(double H[9])
311 {
312   db_Copy9(H,m_H_dref_to_ref);
313 }
314 
Get_H_dref_to_ins(double H[9])315 void db_FrameToReferenceRegistration::Get_H_dref_to_ins(double H[9])
316 {
317   db_Multiply3x3_3x3(H,m_H_dref_to_ref,m_H_ref_to_ins);
318 }
319 
Set_H_dref_to_ins(double H[9])320 void db_FrameToReferenceRegistration::Set_H_dref_to_ins(double H[9])
321 {
322     double H_ins_to_ref[9];
323 
324     db_Identity3x3(H_ins_to_ref);   // Ensure it has proper values
325     db_InvertAffineTransform(H_ins_to_ref,m_H_ref_to_ins);  // Invert to get ins to ref
326     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
327 }
328 
329 
ResetDisplayReference()330 void db_FrameToReferenceRegistration::ResetDisplayReference()
331 {
332   db_Identity3x3(m_H_dref_to_ref);
333 }
334 
NeedReferenceUpdate()335 bool db_FrameToReferenceRegistration::NeedReferenceUpdate()
336 {
337   // If less than 50% of the starting number of inliers left, then its time to update the reference.
338   if(m_max_inlier_count>0 && float(m_num_inlier_indices)/float(m_max_inlier_count)<0.5)
339     return true;
340   else
341     return false;
342 }
343 
AddFrame(const unsigned char * const * im,double H[9],bool force_reference,bool prewarp)344 int db_FrameToReferenceRegistration::AddFrame(const unsigned char * const * im, double H[9],bool force_reference,bool prewarp)
345 {
346   m_current_is_reference = false;
347   if(!m_reference_set || force_reference)
348     {
349       db_Identity3x3(m_H_ref_to_ins);
350       db_Copy9(H,m_H_ref_to_ins);
351 
352       UpdateReference(im,true,true);
353       return 0;
354     }
355 
356   const unsigned char * const * imptr = im;
357 
358   if (m_quarter_resolution)
359   {
360     if (m_quarter_res_image)
361     {
362       GenerateQuarterResImage(im);
363     }
364 
365     imptr = (const unsigned char * const* )m_quarter_res_image;
366   }
367 
368   double H_last[9];
369   db_Copy9(H_last,m_H_ref_to_ins);
370   db_Identity3x3(m_H_ref_to_ins);
371 
372   m_sq_cost_computed = false;
373 
374   // detect corners on inspection image and match to reference image features:s
375 
376   // @jke - Adding code to time the functions.  TODO: Remove after test
377 #if PROFILE
378   double iTimer1, iTimer2;
379   char str[255];
380   strcpy(profile_string,"\n");
381   sprintf(str,"[%dx%d] %p\n",m_im_width,m_im_height,im);
382   strcat(profile_string, str);
383 #endif
384 
385   // @jke - Adding code to time the functions.  TODO: Remove after test
386 #if PROFILE
387   iTimer1 = now_ms();
388 #endif
389   m_cd.DetectCorners(imptr, m_x_corners_ins,m_y_corners_ins,&m_nr_corners_ins);
390   // @jke - Adding code to time the functions.  TODO: Remove after test
391 # if PROFILE
392   iTimer2 = now_ms();
393   double elapsedTimeCorner = iTimer2 - iTimer1;
394   sprintf(str,"Corner Detection [%d corners] = %g ms\n",m_nr_corners_ins, elapsedTimeCorner);
395   strcat(profile_string, str);
396 #endif
397 
398   // @jke - Adding code to time the functions.  TODO: Remove after test
399 #if PROFILE
400   iTimer1 = now_ms();
401 #endif
402     if(prewarp)
403   m_cm.Match(m_reference_image,imptr,m_x_corners_ref,m_y_corners_ref,m_nr_corners_ref,
404          m_x_corners_ins,m_y_corners_ins,m_nr_corners_ins,
405          m_match_index_ref,m_match_index_ins,&m_nr_matches,H,0);
406     else
407   m_cm.Match(m_reference_image,imptr,m_x_corners_ref,m_y_corners_ref,m_nr_corners_ref,
408          m_x_corners_ins,m_y_corners_ins,m_nr_corners_ins,
409          m_match_index_ref,m_match_index_ins,&m_nr_matches);
410   // @jke - Adding code to time the functions.  TODO: Remove after test
411 # if PROFILE
412   iTimer2 = now_ms();
413   double elapsedTimeMatch = iTimer2 - iTimer1;
414   sprintf(str,"Matching [%d] = %g ms\n",m_nr_matches,elapsedTimeMatch);
415   strcat(profile_string, str);
416 #endif
417 
418 
419   // copy out matching features:
420   for ( int i = 0; i < m_nr_matches; ++i )
421     {
422       int offset = 3*i;
423       m_corners_ref[offset  ] = m_x_corners_ref[m_match_index_ref[i]];
424       m_corners_ref[offset+1] = m_y_corners_ref[m_match_index_ref[i]];
425       m_corners_ref[offset+2] = 1.0;
426 
427       m_corners_ins[offset  ] = m_x_corners_ins[m_match_index_ins[i]];
428       m_corners_ins[offset+1] = m_y_corners_ins[m_match_index_ins[i]];
429       m_corners_ins[offset+2] = 1.0;
430     }
431 
432   // @jke - Adding code to time the functions.  TODO: Remove after test
433 #if PROFILE
434   iTimer1 = now_ms();
435 #endif
436   // perform the alignment:
437   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,
438             m_homography_type,NULL,m_max_iterations,m_max_nr_matches,m_scale,
439             m_nr_samples, m_chunk_size);
440   // @jke - Adding code to time the functions.  TODO: Remove after test
441 # if PROFILE
442   iTimer2 = now_ms();
443   double elapsedTimeHomography = iTimer2 - iTimer1;
444   sprintf(str,"Homography = %g ms\n",elapsedTimeHomography);
445   strcat(profile_string, str);
446 #endif
447 
448 
449   SetOutlierThreshold();
450 
451   // Compute the inliers for the db compute m_H_ref_to_ins
452   ComputeInliers(m_H_ref_to_ins);
453 
454   // Update the max inlier count
455   m_max_inlier_count = (m_max_inlier_count > m_num_inlier_indices)?m_max_inlier_count:m_num_inlier_indices;
456 
457   // Fit a least-squares model to just the inliers and put it in m_H_ref_to_ins
458   if(m_linear_polish)
459     Polish(m_inlier_indices, m_num_inlier_indices);
460 
461   if (m_quarter_resolution)
462   {
463     m_H_ref_to_ins[2] *= 2.0;
464     m_H_ref_to_ins[5] *= 2.0;
465   }
466 
467 #if PROFILE
468   sprintf(str,"#Inliers = %d \n",m_num_inlier_indices);
469   strcat(profile_string, str);
470 #endif
471 /*
472   ///// CHECK IF CURRENT TRANSFORMATION GOOD OR BAD ////
473   ///// IF BAD, then update reference to the last correctly aligned inspection frame;
474   if(m_num_inlier_indices<5)//0.9*m_nr_matches || m_nr_matches < 20)
475   {
476     db_Copy9(m_H_ref_to_ins,H_last);
477     UpdateReference(imptr,false);
478 //  UpdateReference(m_aligned_ins_image,false);
479   }
480   else
481   {
482   ///// IF GOOD, then update the last correctly aligned inspection frame to be this;
483   //db_CopyImage_u(m_aligned_ins_image,imptr,m_im_width,m_im_height,m_over_allocation);
484 */
485   if(m_do_motion_smoothing)
486     SmoothMotion();
487 
488    // Disable debug printing
489    // db_PrintDoubleMatrix(m_H_ref_to_ins,3,3);
490 
491   db_Copy9(H, m_H_ref_to_ins);
492 
493   m_nr_frames_processed++;
494 {
495   if ( (m_nr_frames_processed % m_reference_update_period) == 0 )
496   {
497     //UpdateReference(imptr,false, false);
498 
499     #if MB
500     UpdateReference(imptr,false, true);
501     #else
502     UpdateReference(imptr,false, false);
503     #endif
504   }
505 
506 
507   }
508 
509 
510 
511   return 1;
512 }
513 
514 //void db_FrameToReferenceRegistration::ComputeInliers(double H[9],std::vector<int> &inlier_indices)
ComputeInliers(double H[9])515 void db_FrameToReferenceRegistration::ComputeInliers(double H[9])
516 {
517   double totnummatches = m_nr_matches;
518   int inliercount=0;
519 
520   m_num_inlier_indices = 0;
521 //  inlier_indices.clear();
522 
523   for(int c=0; c < totnummatches; c++ )
524     {
525       if (m_sq_cost[c] <= m_outlier_t2)
526     {
527       m_inlier_indices[inliercount] = c;
528       inliercount++;
529     }
530     }
531 
532   m_num_inlier_indices = inliercount;
533   double frac=inliercount/totnummatches;
534 }
535 
536 //void db_FrameToReferenceRegistration::Polish(std::vector<int> &inlier_indices)
Polish(int * inlier_indices,int & num_inlier_indices)537 void db_FrameToReferenceRegistration::Polish(int *inlier_indices, int &num_inlier_indices)
538 {
539   db_Zero(m_polish_C,36);
540   db_Zero(m_polish_D,6);
541   for (int i=0;i<num_inlier_indices;i++)
542     {
543       int j = 3*inlier_indices[i];
544       m_polish_C[0]+=m_corners_ref[j]*m_corners_ref[j];
545       m_polish_C[1]+=m_corners_ref[j]*m_corners_ref[j+1];
546       m_polish_C[2]+=m_corners_ref[j];
547       m_polish_C[7]+=m_corners_ref[j+1]*m_corners_ref[j+1];
548       m_polish_C[8]+=m_corners_ref[j+1];
549       m_polish_C[14]+=1;
550       m_polish_D[0]+=m_corners_ref[j]*m_corners_ins[j];
551       m_polish_D[1]+=m_corners_ref[j+1]*m_corners_ins[j];
552       m_polish_D[2]+=m_corners_ins[j];
553       m_polish_D[3]+=m_corners_ref[j]*m_corners_ins[j+1];
554       m_polish_D[4]+=m_corners_ref[j+1]*m_corners_ins[j+1];
555       m_polish_D[5]+=m_corners_ins[j+1];
556     }
557 
558   double a=db_maxd(m_polish_C[0],m_polish_C[7]);
559   m_polish_C[0]/=a; m_polish_C[1]/=a;   m_polish_C[2]/=a;
560   m_polish_C[7]/=a; m_polish_C[8]/=a; m_polish_C[14]/=a;
561 
562   m_polish_D[0]/=a; m_polish_D[1]/=a;   m_polish_D[2]/=a;
563   m_polish_D[3]/=a; m_polish_D[4]/=a;   m_polish_D[5]/=a;
564 
565 
566   m_polish_C[6]=m_polish_C[1];
567   m_polish_C[12]=m_polish_C[2];
568   m_polish_C[13]=m_polish_C[8];
569 
570   m_polish_C[21]=m_polish_C[0]; m_polish_C[22]=m_polish_C[1]; m_polish_C[23]=m_polish_C[2];
571   m_polish_C[28]=m_polish_C[7]; m_polish_C[29]=m_polish_C[8];
572   m_polish_C[35]=m_polish_C[14];
573 
574 
575   double d[6];
576   db_CholeskyDecomp6x6(m_polish_C,d);
577   db_CholeskyBacksub6x6(m_H_ref_to_ins,m_polish_C,d,m_polish_D);
578 }
579 
EstimateSecondaryModel(double H[9])580 void db_FrameToReferenceRegistration::EstimateSecondaryModel(double H[9])
581 {
582   /*      if ( m_current_is_reference )
583       {
584       db_Identity3x3(H);
585       return;
586       }
587   */
588 
589   // select the outliers of the current model:
590   SelectOutliers();
591 
592   // perform the alignment:
593   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,
594             m_homography_type,NULL,m_max_iterations,m_max_nr_matches,m_scale,
595             m_nr_samples, m_chunk_size);
596 
597   db_Copy9(H,m_H_ref_to_ins);
598 }
599 
ComputeCostArray()600 void db_FrameToReferenceRegistration::ComputeCostArray()
601 {
602   if ( m_sq_cost_computed ) return;
603 
604   for( int c=0, k=0 ;c < m_nr_matches; c++, k=k+3)
605     {
606       m_sq_cost[c] = SquaredInhomogenousHomographyError(m_corners_ins+k,m_H_ref_to_ins,m_corners_ref+k);
607     }
608 
609   m_sq_cost_computed = true;
610 }
611 
SelectOutliers()612 void db_FrameToReferenceRegistration::SelectOutliers()
613 {
614   int nr_outliers=0;
615 
616   ComputeCostArray();
617 
618   for(int c=0, k=0 ;c<m_nr_matches;c++,k=k+3)
619     {
620       if (m_sq_cost[c] > m_outlier_t2)
621     {
622       int offset = 3*nr_outliers++;
623       db_Copy3(m_corners_ref+offset,m_corners_ref+k);
624       db_Copy3(m_corners_ins+offset,m_corners_ins+k);
625     }
626     }
627 
628   m_nr_matches = nr_outliers;
629 }
630 
ComputeCostHistogram()631 void db_FrameToReferenceRegistration::ComputeCostHistogram()
632 {
633   ComputeCostArray();
634 
635   for ( int b = 0; b < m_nr_bins; ++b )
636     m_cost_histogram[b] = 0;
637 
638   for(int c = 0; c < m_nr_matches; c++)
639     {
640       double error = db_SafeSqrt(m_sq_cost[c]);
641       int bin = (int)(error/m_max_cost_pix*m_nr_bins);
642       if ( bin < m_nr_bins )
643     m_cost_histogram[bin]++;
644       else
645     m_cost_histogram[m_nr_bins-1]++;
646     }
647 
648 /*
649   for ( int i = 0; i < m_nr_bins; ++i )
650     std::cout << m_cost_histogram[i] << " ";
651   std::cout << std::endl;
652 */
653 }
654 
SetOutlierThreshold()655 void db_FrameToReferenceRegistration::SetOutlierThreshold()
656 {
657   ComputeCostHistogram();
658 
659   int i = 0, last=0;
660   for (; i < m_nr_bins-1; ++i )
661     {
662       if ( last > m_cost_histogram[i] )
663     break;
664       last = m_cost_histogram[i];
665     }
666 
667   //std::cout << "I " <<  i << std::endl;
668 
669   int max = m_cost_histogram[i];
670 
671   for (; i < m_nr_bins-1; ++i )
672     {
673       if ( m_cost_histogram[i] < (int)(0.1*max) )
674     //if ( last < m_cost_histogram[i] )
675     break;
676       last = m_cost_histogram[i];
677     }
678   //std::cout << "J " <<  i << std::endl;
679 
680   m_outlier_t2 = db_sqr(i*m_max_cost_pix/m_nr_bins);
681 
682   //std::cout << "m_outlier_t2 " <<  m_outlier_t2 << std::endl;
683 }
684 
SmoothMotion(void)685 void db_FrameToReferenceRegistration::SmoothMotion(void)
686 {
687   VP_MOTION inmot,outmot;
688 
689   double H[9];
690 
691   Get_H_dref_to_ins(H);
692 
693       MXX(inmot) = H[0];
694     MXY(inmot) = H[1];
695     MXZ(inmot) = H[2];
696     MXW(inmot) = 0.0;
697 
698     MYX(inmot) = H[3];
699     MYY(inmot) = H[4];
700     MYZ(inmot) = H[5];
701     MYW(inmot) = 0.0;
702 
703     MZX(inmot) = H[6];
704     MZY(inmot) = H[7];
705     MZZ(inmot) = H[8];
706     MZW(inmot) = 0.0;
707 
708     MWX(inmot) = 0.0;
709     MWY(inmot) = 0.0;
710     MWZ(inmot) = 0.0;
711     MWW(inmot) = 1.0;
712 
713     inmot.type = VP_MOTION_AFFINE;
714 
715     int w = m_im_width;
716     int h = m_im_height;
717 
718     if(m_quarter_resolution)
719     {
720     w = w*2;
721     h = h*2;
722     }
723 
724 #if 0
725     m_stab_smoother.smoothMotionAdaptive(w,h,&inmot,&outmot);
726 #else
727     m_stab_smoother.smoothMotion(&inmot,&outmot);
728 #endif
729 
730     H[0] = MXX(outmot);
731     H[1] = MXY(outmot);
732     H[2] = MXZ(outmot);
733 
734     H[3] = MYX(outmot);
735     H[4] = MYY(outmot);
736     H[5] = MYZ(outmot);
737 
738     H[6] = MZX(outmot);
739     H[7] = MZY(outmot);
740     H[8] = MZZ(outmot);
741 
742     Set_H_dref_to_ins(H);
743 }
744 
GenerateQuarterResImage(const unsigned char * const * im)745 void db_FrameToReferenceRegistration::GenerateQuarterResImage(const unsigned char* const* im)
746 {
747   int input_h = m_im_height*2;
748   int input_w = m_im_width*2;
749 
750   for (int j = 0; j < input_h; j++)
751   {
752     const unsigned char* in_row_ptr = im[j];
753     unsigned char* out_row_ptr = m_horz_smooth_subsample_image[j]+1;
754 
755     for (int i = 2; i < input_w-2; i += 2)
756     {
757       int smooth_val = (
758             6*in_row_ptr[i] +
759             ((in_row_ptr[i-1]+in_row_ptr[i+1])<<2) +
760             in_row_ptr[i-2]+in_row_ptr[i+2]
761             ) >> 4;
762       *out_row_ptr++ = (unsigned char) smooth_val;
763 
764       if ( (smooth_val < 0) || (smooth_val > 255))
765       {
766         return;
767       }
768 
769     }
770   }
771 
772   for (int j = 2; j < input_h-2; j+=2)
773   {
774 
775     unsigned char* in_row_ptr = m_horz_smooth_subsample_image[j];
776     unsigned char* out_row_ptr = m_quarter_res_image[j/2];
777 
778     for (int i = 1; i < m_im_width-1; i++)
779     {
780       int smooth_val = (
781             6*in_row_ptr[i] +
782             ((in_row_ptr[i-m_im_width]+in_row_ptr[i+m_im_width]) << 2)+
783             in_row_ptr[i-2*m_im_width]+in_row_ptr[i+2*m_im_width]
784             ) >> 4;
785       *out_row_ptr++ = (unsigned char)smooth_val;
786 
787       if ( (smooth_val < 0) || (smooth_val > 255))
788       {
789         return;
790       }
791 
792     }
793   }
794 }
795