Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/calib3d/src/rho.cpp
16354 views
1
/*
2
IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
3
4
By downloading, copying, installing or using the software you agree to this license.
5
If you do not agree to this license, do not download, install,
6
copy or use the software.
7
8
9
BSD 3-Clause License
10
11
Copyright (C) 2014, Olexa Bilaniuk, Hamid Bazargani & Robert Laganiere, all rights reserved.
12
13
Redistribution and use in source and binary forms, with or without modification,
14
are permitted provided that the following conditions are met:
15
16
* Redistribution's of source code must retain the above copyright notice,
17
this list of conditions and the following disclaimer.
18
19
* Redistribution's in binary form must reproduce the above copyright notice,
20
this list of conditions and the following disclaimer in the documentation
21
and/or other materials provided with the distribution.
22
23
* The name of the copyright holders may not be used to endorse or promote products
24
derived from this software without specific prior written permission.
25
26
This software is provided by the copyright holders and contributors "as is" and
27
any express or implied warranties, including, but not limited to, the implied
28
warranties of merchantability and fitness for a particular purpose are disclaimed.
29
In no event shall the Intel Corporation or contributors be liable for any direct,
30
indirect, incidental, special, exemplary, or consequential damages
31
(including, but not limited to, procurement of substitute goods or services;
32
loss of use, data, or profits; or business interruption) however caused
33
and on any theory of liability, whether in contract, strict liability,
34
or tort (including negligence or otherwise) arising in any way out of
35
the use of this software, even if advised of the possibility of such damage.
36
*/
37
38
/**
39
* Bilaniuk, Olexa, Hamid Bazargani, and Robert Laganiere. "Fast Target
40
* Recognition on Mobile Devices: Revisiting Gaussian Elimination for the
41
* Estimation of Planar Homographies." In Computer Vision and Pattern
42
* Recognition Workshops (CVPRW), 2014 IEEE Conference on, pp. 119-125.
43
* IEEE, 2014.
44
*/
45
46
/* Includes */
47
#include "precomp.hpp"
48
#include <opencv2/core.hpp>
49
#include <stdlib.h>
50
#include <stdio.h>
51
#include <string.h>
52
#include <stddef.h>
53
#include <limits.h>
54
#include <float.h>
55
#include <math.h>
56
#include <vector>
57
#include "rho.h"
58
59
60
61
62
63
/* For the sake of cv:: namespace ONLY: */
64
namespace cv{/* For C support, replace with extern "C" { */
65
66
67
/* Constants */
68
const int MEM_ALIGN = 32;
69
const size_t HSIZE = (3*3*sizeof(float));
70
const double MIN_DELTA_CHNG = 0.1;
71
// const double CHI_STAT = 2.706;
72
const double CHI_SQ = 1.645;
73
// const double RLO = 0.25;
74
// const double RHI = 0.75;
75
const int MAXLEVMARQITERS = 100;
76
const int SMPL_SIZE = 4; /* 4 points required per model */
77
const int SPRT_T_M = 25; /* Guessing 25 match evlauations / 1 model generation */
78
const int SPRT_M_S = 1; /* 1 model per sample */
79
const double SPRT_EPSILON = 0.1; /* No explanation */
80
const double SPRT_DELTA = 0.01; /* No explanation */
81
const double LM_GAIN_LO = 0.25; /* See sacLMGain(). */
82
const double LM_GAIN_HI = 0.75; /* See sacLMGain(). */
83
84
85
/* Data Structures */
86
87
/**
88
* Base Struct for RHO algorithm.
89
*
90
* A RHO estimator has initialization, finalization, capacity, seeding and
91
* homography-estimation APIs that must be implemented.
92
*/
93
94
struct RHO_HEST{
95
/* This is a virtual base class; It should have a virtual destructor. */
96
virtual ~RHO_HEST(){}
97
98
/* External Interface Methods */
99
100
/**
101
* Initialization work.
102
*
103
* @return 0 if initialization is unsuccessful; non-zero otherwise.
104
*/
105
106
virtual inline int initialize(void){return 1;}
107
108
109
/**
110
* Finalization work.
111
*/
112
113
virtual inline void finalize(void){}
114
115
/**
116
* Ensure that the estimator context's internal table for the non-randomness
117
* criterion is at least of the given size, and uses the given beta. The table
118
* should be larger than the maximum number of matches fed into the estimator.
119
*
120
* A value of N of 0 requests deallocation of the table.
121
*
122
* @param [in] N If 0, deallocate internal table. If > 0, ensure that the
123
* internal table is of at least this size, reallocating if
124
* necessary.
125
* @param [in] beta The beta-factor to use within the table.
126
* @return 0 if unsuccessful; non-zero otherwise.
127
*/
128
129
virtual inline int ensureCapacity(unsigned N, double beta){
130
CV_UNUSED(N);
131
CV_UNUSED(beta);
132
133
return 1;
134
}
135
136
137
/**
138
* Generates a random double uniformly distributed in the range [0, 1).
139
*
140
* The default implementation uses the xorshift128+ algorithm from
141
* Sebastiano Vigna. Further scramblings of Marsaglia's xorshift generators.
142
* CoRR, abs/1402.6246, 2014.
143
* http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf
144
*
145
* Source roughly as given in
146
* http://en.wikipedia.org/wiki/Xorshift#Xorshift.2B
147
*/
148
149
virtual inline double fastRandom(void){
150
uint64_t x = prng.s[0];
151
uint64_t y = prng.s[1];
152
x ^= x << 23; // a
153
x ^= x >> 17; // b
154
x ^= y ^ (y >> 26); // c
155
prng.s[0] = y;
156
prng.s[1] = x;
157
uint64_t s = x + y;
158
159
return s * 5.421010862427522e-20;/* 2^-64 */
160
}
161
162
163
/**
164
* Seeds the context's PRNG.
165
*
166
* @param [in] seed A 64-bit unsigned integer seed.
167
*/
168
169
virtual inline void fastSeed(uint64_t seed){
170
int i;
171
172
prng.s[0] = seed;
173
prng.s[1] = ~seed;/* Guarantees one of the elements will be non-zero. */
174
175
/**
176
* Escape from zero-land (see xorshift128+ paper). Approximately 20
177
* iterations required according to the graph.
178
*/
179
180
for(i=0;i<20;i++){
181
fastRandom();
182
}
183
}
184
185
186
/**
187
* Estimates the homography using the given context, matches and parameters to
188
* PROSAC.
189
*
190
* @param [in] src The pointer to the source points of the matches.
191
* Cannot be NULL.
192
* @param [in] dst The pointer to the destination points of the matches.
193
* Cannot be NULL.
194
* @param [out] inl The pointer to the output mask of inlier matches.
195
* May be NULL.
196
* @param [in] N The number of matches.
197
* @param [in] maxD The maximum distance.
198
* @param [in] maxI The maximum number of PROSAC iterations.
199
* @param [in] rConvg The RANSAC convergence parameter.
200
* @param [in] cfd The required confidence in the solution.
201
* @param [in] minInl The minimum required number of inliers.
202
* @param [in] beta The beta-parameter for the non-randomness criterion.
203
* @param [in] flags A union of flags to control the estimation.
204
* @param [in] guessH An extrinsic guess at the solution H, or NULL if
205
* none provided.
206
* @param [out] finalH The final estimation of H, or the zero matrix if
207
* the minimum number of inliers was not met.
208
* Cannot be NULL.
209
* @return The number of inliers if the minimum number of
210
* inliers for acceptance was reached; 0 otherwise.
211
*/
212
213
virtual unsigned rhoHest(const float* src, /* Source points */
214
const float* dst, /* Destination points */
215
char* inl, /* Inlier mask */
216
unsigned N, /* = src.length = dst.length = inl.length */
217
float maxD, /* Works: 3.0 */
218
unsigned maxI, /* Works: 2000 */
219
unsigned rConvg, /* Works: 2000 */
220
double cfd, /* Works: 0.995 */
221
unsigned minInl, /* Minimum: 4 */
222
double beta, /* Works: 0.35 */
223
unsigned flags, /* Works: 0 */
224
const float* guessH, /* Extrinsic guess, NULL if none provided */
225
float* finalH) = 0; /* Final result. */
226
227
228
229
/* PRNG XORshift128+ */
230
struct{
231
uint64_t s[2]; /* PRNG state */
232
} prng;
233
};
234
235
236
237
/**
238
* Generic C implementation of RHO algorithm.
239
*/
240
241
struct RHO_HEST_REFC : RHO_HEST{
242
/**
243
* Virtual Arguments.
244
*
245
* Exactly the same as at function call, except:
246
* - minInl is enforced to be >= 4.
247
*/
248
249
struct{
250
const float* src;
251
const float* dst;
252
char* inl;
253
unsigned N;
254
float maxD;
255
unsigned maxI;
256
unsigned rConvg;
257
double cfd;
258
unsigned minInl;
259
double beta;
260
unsigned flags;
261
const float* guessH;
262
float* finalH;
263
} arg;
264
265
/* PROSAC Control */
266
struct{
267
unsigned i; /* Iteration Number */
268
unsigned phNum; /* Phase Number */
269
unsigned phEndI; /* Phase End Iteration */
270
double phEndFpI; /* Phase floating-point End Iteration */
271
unsigned phMax; /* Termination phase number */
272
unsigned phNumInl; /* Number of inliers for termination phase */
273
unsigned numModels; /* Number of models tested */
274
unsigned* smpl; /* Sample of match indexes */
275
} ctrl;
276
277
/* Current model being tested */
278
struct{
279
float* pkdPts; /* Packed points */
280
float* H; /* Homography */
281
char* inl; /* Mask of inliers */
282
unsigned numInl; /* Number of inliers */
283
} curr;
284
285
/* Best model (so far) */
286
struct{
287
float* H; /* Homography */
288
char* inl; /* Mask of inliers */
289
unsigned numInl; /* Number of inliers */
290
} best;
291
292
/* Non-randomness criterion */
293
struct{
294
std::vector<unsigned> tbl; /* Non-Randomness: Table */
295
unsigned size; /* Non-Randomness: Size */
296
double beta; /* Non-Randomness: Beta */
297
} nr;
298
299
/* SPRT Evaluator */
300
struct{
301
double t_M; /* t_M */
302
double m_S; /* m_S */
303
double epsilon; /* Epsilon */
304
double delta; /* delta */
305
double A; /* SPRT Threshold */
306
unsigned Ntested; /* Number of points tested */
307
unsigned Ntestedtotal; /* Number of points tested in total */
308
int good; /* Good/bad flag */
309
double lambdaAccept; /* Accept multiplier */
310
double lambdaReject; /* Reject multiplier */
311
} eval;
312
313
/* Levenberg-Marquardt Refinement */
314
struct{
315
float (* JtJ)[8]; /* JtJ matrix */
316
float (* tmp1)[8]; /* Temporary 1 */
317
float* Jte; /* Jte vector */
318
} lm;
319
320
/* Memory Management */
321
struct{
322
cv::Mat perObj;
323
cv::Mat perRun;
324
} mem;
325
326
/* Initialized? */
327
int initialized;
328
329
330
/* Empty constructors and destructors */
331
public:
332
RHO_HEST_REFC();
333
private: /* Forbid copying. */
334
RHO_HEST_REFC(const RHO_HEST_REFC&);
335
public:
336
~RHO_HEST_REFC();
337
338
/* Methods to implement external interface */
339
inline int initialize(void) CV_OVERRIDE;
340
inline void finalize(void) CV_OVERRIDE;
341
inline int ensureCapacity(unsigned N, double beta) CV_OVERRIDE;
342
unsigned rhoHest(const float* src, /* Source points */
343
const float* dst, /* Destination points */
344
char* inl, /* Inlier mask */
345
unsigned N, /* = src.length = dst.length = inl.length */
346
float maxD, /* Works: 3.0 */
347
unsigned maxI, /* Works: 2000 */
348
unsigned rConvg, /* Works: 2000 */
349
double cfd, /* Works: 0.995 */
350
unsigned minInl, /* Minimum: 4 */
351
double beta, /* Works: 0.35 */
352
unsigned flags, /* Works: 0 */
353
const float* guessH, /* Extrinsic guess, NULL if none provided */
354
float* finalH /* Final result. */
355
) CV_OVERRIDE;
356
357
358
359
/* Methods to implement internals */
360
inline void allocatePerObj(void);
361
inline void allocatePerRun(void);
362
inline void deallocatePerRun(void);
363
inline void deallocatePerObj(void);
364
inline int initRun(void);
365
inline void finiRun(void);
366
inline int haveExtrinsicGuess(void);
367
inline int hypothesize(void);
368
inline int verify(void);
369
inline int isNREnabled(void);
370
inline int isRefineEnabled(void);
371
inline int isFinalRefineEnabled(void);
372
inline int PROSACPhaseEndReached(void);
373
inline void PROSACGoToNextPhase(void);
374
inline void getPROSACSample(void);
375
inline void rndSmpl(unsigned sampleSize,
376
unsigned* currentSample,
377
unsigned dataSetSize);
378
inline int isSampleDegenerate(void);
379
inline void generateModel(void);
380
inline int isModelDegenerate(void);
381
inline void evaluateModelSPRT(void);
382
inline void updateSPRT(void);
383
inline void designSPRTTest(void);
384
inline int isBestModel(void);
385
inline int isBestModelGoodEnough(void);
386
inline void saveBestModel(void);
387
inline void nStarOptimize(void);
388
inline void updateBounds(void);
389
inline void outputModel(void);
390
inline void outputZeroH(void);
391
inline int canRefine(void);
392
inline void refine(void);
393
};
394
395
396
397
398
/**
399
* Prototypes for purely-computational code.
400
*/
401
402
static inline void sacInitNonRand (double beta,
403
unsigned start,
404
unsigned N,
405
unsigned* nonRandMinInl);
406
static inline double sacInitPEndFpI (const unsigned ransacConvg,
407
const unsigned n,
408
const unsigned s);
409
static inline unsigned sacCalcIterBound (double confidence,
410
double inlierRate,
411
unsigned sampleSize,
412
unsigned maxIterBound);
413
static inline void hFuncRefC (float* packedPoints, float* H);
414
static inline void sacCalcJacobianErrors(const float* H,
415
const float* src,
416
const float* dst,
417
const char* inl,
418
unsigned N,
419
float (* JtJ)[8],
420
float* Jte,
421
float* Sp);
422
static inline float sacLMGain (const float* dH,
423
const float* Jte,
424
const float S,
425
const float newS,
426
const float lambda);
427
static inline int sacChol8x8Damped (const float (*A)[8],
428
float lambda,
429
float (*L)[8]);
430
static inline void sacTRInv8x8 (const float (*L)[8],
431
float (*M)[8]);
432
static inline void sacTRISolve8x8 (const float (*L)[8],
433
const float* Jte,
434
float* dH);
435
static inline void sacSub8x1 (float* Hout,
436
const float* H,
437
const float* dH);
438
439
440
441
/* Functions */
442
443
/**
444
* External access to context constructor.
445
*
446
* @return A pointer to the context if successful; NULL if an error occurred.
447
*/
448
449
Ptr<RHO_HEST> rhoInit(void){
450
/* Select an optimized implementation of RHO here. */
451
452
#if 1
453
/**
454
* For now, only the generic C implementation is available. In the future,
455
* SSE2/AVX/AVX2/FMA/NEON versions may be added, and they will be selected
456
* depending on cv::checkHardwareSupport()'s return values.
457
*/
458
459
Ptr<RHO_HEST> p = Ptr<RHO_HEST>(new RHO_HEST_REFC);
460
#endif
461
462
/* Initialize it. */
463
if(p){
464
if(!p->initialize()){
465
p.release();
466
}
467
}
468
469
/* Return it. */
470
return p;
471
}
472
473
474
/**
475
* External access to non-randomness table resize.
476
*/
477
478
int rhoEnsureCapacity(Ptr<RHO_HEST> p, unsigned N, double beta){
479
return p->ensureCapacity(N, beta);
480
}
481
482
483
/**
484
* Seeds the internal PRNG with the given seed.
485
*/
486
487
void rhoSeed(Ptr<RHO_HEST> p, uint64_t seed){
488
p->fastSeed(seed);
489
}
490
491
492
/**
493
* Estimates the homography using the given context, matches and parameters to
494
* PROSAC.
495
*
496
* @param [in/out] p The context to use for homography estimation. Must
497
* be already initialized. Cannot be NULL.
498
* @param [in] src The pointer to the source points of the matches.
499
* Must be aligned to 4 bytes. Cannot be NULL.
500
* @param [in] dst The pointer to the destination points of the matches.
501
* Must be aligned to 16 bytes. Cannot be NULL.
502
* @param [out] inl The pointer to the output mask of inlier matches.
503
* Must be aligned to 16 bytes. May be NULL.
504
* @param [in] N The number of matches.
505
* @param [in] maxD The maximum distance.
506
* @param [in] maxI The maximum number of PROSAC iterations.
507
* @param [in] rConvg The RANSAC convergence parameter.
508
* @param [in] cfd The required confidence in the solution.
509
* @param [in] minInl The minimum required number of inliers.
510
* @param [in] beta The beta-parameter for the non-randomness criterion.
511
* @param [in] flags A union of flags to control the estimation.
512
* @param [in] guessH An extrinsic guess at the solution H, or NULL if
513
* none provided.
514
* @param [out] finalH The final estimation of H, or the zero matrix if
515
* the minimum number of inliers was not met.
516
* Cannot be NULL.
517
* @return The number of inliers if the minimum number of
518
* inliers for acceptance was reached; 0 otherwise.
519
*/
520
521
unsigned rhoHest(Ptr<RHO_HEST> p, /* Homography estimation context. */
522
const float* src, /* Source points */
523
const float* dst, /* Destination points */
524
char* inl, /* Inlier mask */
525
unsigned N, /* = src.length = dst.length = inl.length */
526
float maxD, /* Works: 3.0 */
527
unsigned maxI, /* Works: 2000 */
528
unsigned rConvg, /* Works: 2000 */
529
double cfd, /* Works: 0.995 */
530
unsigned minInl, /* Minimum: 4 */
531
double beta, /* Works: 0.35 */
532
unsigned flags, /* Works: 0 */
533
const float* guessH, /* Extrinsic guess, NULL if none provided */
534
float* finalH){ /* Final result. */
535
return p->rhoHest(src, dst, inl, N, maxD, maxI, rConvg, cfd, minInl, beta,
536
flags, guessH, finalH);
537
}
538
539
540
541
542
543
544
545
546
547
548
549
550
/*********************** RHO_HEST_REFC implementation **********************/
551
552
/**
553
* Constructor for RHO_HEST_REFC.
554
*
555
* Does nothing. True initialization is done by initialize().
556
*/
557
558
RHO_HEST_REFC::RHO_HEST_REFC() : initialized(0){
559
arg.src = 0;
560
arg.dst = 0;
561
arg.inl = 0;
562
arg.N = 0;
563
arg.maxD = 0;
564
arg.maxI = 0;
565
arg.rConvg = 0;
566
arg.cfd = 0;
567
arg.minInl = 0;
568
arg.beta = 0;
569
arg.flags = 0;
570
arg.guessH = 0;
571
arg.finalH = 0;
572
573
ctrl.i = 0;
574
ctrl.phNum = 0;
575
ctrl.phEndI = 0;
576
ctrl.phEndFpI = 0;
577
ctrl.phMax = 0;
578
ctrl.phNumInl = 0;
579
ctrl.numModels = 0;
580
ctrl.smpl = 0;
581
582
curr.pkdPts = 0;
583
curr.H = 0;
584
curr.inl = 0;
585
curr.numInl = 0;
586
587
best.H = 0;
588
best.inl = 0;
589
best.numInl = 0;
590
591
nr.size = 0;
592
nr.beta = 0;
593
594
eval.t_M = 0;
595
eval.m_S = 0;
596
eval.epsilon = 0;
597
eval.delta = 0;
598
eval.A = 0;
599
eval.Ntested = 0;
600
eval.Ntestedtotal = 0;
601
eval.good = 0;
602
eval.lambdaAccept = 0;
603
eval.lambdaReject = 0;
604
605
lm.JtJ = 0;
606
lm.tmp1 = 0;
607
lm.Jte = 0;
608
}
609
610
/**
611
* Private copy constructor for RHO_HEST_REFC. Disabled.
612
*/
613
614
RHO_HEST_REFC::RHO_HEST_REFC(const RHO_HEST_REFC&) : initialized(0){
615
616
}
617
618
/**
619
* Destructor for RHO_HEST_REFC.
620
*/
621
622
RHO_HEST_REFC::~RHO_HEST_REFC(){
623
if(initialized){
624
finalize();
625
}
626
}
627
628
629
630
/**
631
* Initialize the estimator context, by allocating the aligned buffers
632
* internally needed.
633
*
634
* Currently there are 5 per-estimator buffers:
635
* - The buffer of m indexes representing a sample
636
* - The buffer of 16 floats representing m matches (x,y) -> (X,Y).
637
* - The buffer for the current homography
638
* - The buffer for the best-so-far homography
639
* - Optionally, the non-randomness criterion table
640
*
641
* Returns 0 if unsuccessful and non-0 otherwise.
642
*/
643
644
inline int RHO_HEST_REFC::initialize(void){
645
initialized = 0;
646
647
648
allocatePerObj();
649
650
curr.inl = NULL;
651
curr.numInl = 0;
652
653
best.inl = NULL;
654
best.numInl = 0;
655
656
nr.size = 0;
657
nr.beta = 0.0;
658
659
660
fastSeed((uint64_t)~0);
661
662
663
int areAllAllocsSuccessful = !mem.perObj.empty();
664
665
if(!areAllAllocsSuccessful){
666
finalize();
667
}else{
668
initialized = 1;
669
}
670
671
return areAllAllocsSuccessful;
672
}
673
674
/**
675
* Finalize.
676
*
677
* Finalize the estimator context, by freeing the aligned buffers used
678
* internally.
679
*/
680
681
inline void RHO_HEST_REFC::finalize(void){
682
if(initialized){
683
deallocatePerObj();
684
685
initialized = 0;
686
}
687
}
688
689
/**
690
* Ensure that the estimator context's internal table for non-randomness
691
* criterion is at least of the given size, and uses the given beta. The table
692
* should be larger than the maximum number of matches fed into the estimator.
693
*
694
* A value of N of 0 requests deallocation of the table.
695
*
696
* @param [in] N If 0, deallocate internal table. If > 0, ensure that the
697
* internal table is of at least this size, reallocating if
698
* necessary.
699
* @param [in] beta The beta-factor to use within the table.
700
* @return 0 if unsuccessful; non-zero otherwise.
701
*
702
* Reads: nr.*
703
* Writes: nr.*
704
*/
705
706
inline int RHO_HEST_REFC::ensureCapacity(unsigned N, double beta){
707
if(N == 0){
708
/* Clear. */
709
nr.tbl.clear();
710
nr.size = 0;
711
}else if(nr.beta != beta){
712
/* Beta changed. Redo all the work. */
713
nr.tbl.resize(N);
714
nr.beta = beta;
715
sacInitNonRand(nr.beta, 0, N, &nr.tbl[0]);
716
nr.size = N;
717
}else if(N > nr.size){
718
/* Work is partially done. Do rest of it. */
719
nr.tbl.resize(N);
720
sacInitNonRand(nr.beta, nr.size, N, &nr.tbl[nr.size]);
721
nr.size = N;
722
}else{
723
/* Work is already done. Do nothing. */
724
}
725
726
return 1;
727
}
728
729
730
/**
731
* Estimates the homography using the given context, matches and parameters to
732
* PROSAC.
733
*
734
* @param [in] src The pointer to the source points of the matches.
735
* Must be aligned to 4 bytes. Cannot be NULL.
736
* @param [in] dst The pointer to the destination points of the matches.
737
* Must be aligned to 4 bytes. Cannot be NULL.
738
* @param [out] inl The pointer to the output mask of inlier matches.
739
* Must be aligned to 4 bytes. May be NULL.
740
* @param [in] N The number of matches.
741
* @param [in] maxD The maximum distance.
742
* @param [in] maxI The maximum number of PROSAC iterations.
743
* @param [in] rConvg The RANSAC convergence parameter.
744
* @param [in] cfd The required confidence in the solution.
745
* @param [in] minInl The minimum required number of inliers.
746
* @param [in] beta The beta-parameter for the non-randomness criterion.
747
* @param [in] flags A union of flags to control the estimation.
748
* @param [in] guessH An extrinsic guess at the solution H, or NULL if
749
* none provided.
750
* @param [out] finalH The final estimation of H, or the zero matrix if
751
* the minimum number of inliers was not met.
752
* Cannot be NULL.
753
* @return The number of inliers if the minimum number of
754
* inliers for acceptance was reached; 0 otherwise.
755
*/
756
757
unsigned RHO_HEST_REFC::rhoHest(const float* src, /* Source points */
758
const float* dst, /* Destination points */
759
char* inl, /* Inlier mask */
760
unsigned N, /* = src.length = dst.length = inl.length */
761
float maxD, /* Works: 3.0 */
762
unsigned maxI, /* Works: 2000 */
763
unsigned rConvg, /* Works: 2000 */
764
double cfd, /* Works: 0.995 */
765
unsigned minInl, /* Minimum: 4 */
766
double beta, /* Works: 0.35 */
767
unsigned flags, /* Works: 0 */
768
const float* guessH, /* Extrinsic guess, NULL if none provided */
769
float* finalH){ /* Final result. */
770
771
/**
772
* Setup
773
*/
774
775
arg.src = src;
776
arg.dst = dst;
777
arg.inl = inl;
778
arg.N = N;
779
arg.maxD = maxD;
780
arg.maxI = maxI;
781
arg.rConvg = rConvg;
782
arg.cfd = cfd;
783
arg.minInl = minInl;
784
arg.beta = beta;
785
arg.flags = flags;
786
arg.guessH = guessH;
787
arg.finalH = finalH;
788
if(!initRun()){
789
outputZeroH();
790
finiRun();
791
return 0;
792
}
793
794
/**
795
* Extrinsic Guess
796
*/
797
798
if(haveExtrinsicGuess()){
799
verify();
800
}
801
802
803
/**
804
* PROSAC Loop
805
*/
806
807
for(ctrl.i=0; ctrl.i < arg.maxI || ctrl.i < 100; ctrl.i++){
808
hypothesize() && verify();
809
}
810
811
812
/**
813
* Teardown
814
*/
815
816
if(isFinalRefineEnabled() && canRefine()){
817
refine();
818
}
819
820
outputModel();
821
finiRun();
822
return isBestModelGoodEnough() ? best.numInl : 0;
823
}
824
825
826
/**
827
* Allocate per-object dynamic storage.
828
*
829
* This includes aligned, fixed-size internal buffers, but excludes any buffers
830
* whose size cannot be determined ahead-of-time (before the number of matches
831
* is known).
832
*
833
* All buffer memory is allocated in one single shot, and all pointers are
834
* initialized.
835
*/
836
837
inline void RHO_HEST_REFC::allocatePerObj(void){
838
/* We have known sizes */
839
size_t ctrl_smpl_sz = SMPL_SIZE*sizeof(*ctrl.smpl);
840
size_t curr_pkdPts_sz = SMPL_SIZE*2*2*sizeof(*curr.pkdPts);
841
size_t curr_H_sz = HSIZE;
842
size_t best_H_sz = HSIZE;
843
size_t lm_JtJ_sz = 8*8*sizeof(float);
844
size_t lm_tmp1_sz = 8*8*sizeof(float);
845
size_t lm_Jte_sz = 1*8*sizeof(float);
846
847
/* We compute offsets */
848
size_t total = 0;
849
#define MK_OFFSET(v) \
850
size_t v ## _of = total; \
851
total = alignSize(v ## _of + v ## _sz, MEM_ALIGN)
852
853
MK_OFFSET(ctrl_smpl);
854
MK_OFFSET(curr_pkdPts);
855
MK_OFFSET(curr_H);
856
MK_OFFSET(best_H);
857
MK_OFFSET(lm_JtJ);
858
MK_OFFSET(lm_tmp1);
859
MK_OFFSET(lm_Jte);
860
861
#undef MK_OFFSET
862
863
/* Allocate dynamic memory managed by cv::Mat */
864
mem.perObj.create(1, (int)(total + MEM_ALIGN), CV_8UC1);
865
866
/* Extract aligned pointer */
867
unsigned char* ptr = alignPtr(mem.perObj.data, MEM_ALIGN);
868
869
/* Assign pointers */
870
ctrl.smpl = (unsigned*) (ptr + ctrl_smpl_of);
871
curr.pkdPts = (float*) (ptr + curr_pkdPts_of);
872
curr.H = (float*) (ptr + curr_H_of);
873
best.H = (float*) (ptr + best_H_of);
874
lm.JtJ = (float(*)[8])(ptr + lm_JtJ_of);
875
lm.tmp1 = (float(*)[8])(ptr + lm_tmp1_of);
876
lm.Jte = (float*) (ptr + lm_Jte_of);
877
}
878
879
880
/**
881
* Allocate per-run dynamic storage.
882
*
883
* This includes storage that is proportional to the number of points, such as
884
* the inlier mask.
885
*/
886
887
inline void RHO_HEST_REFC::allocatePerRun(void){
888
/* We have known sizes */
889
size_t best_inl_sz = arg.N;
890
size_t curr_inl_sz = arg.N;
891
892
/* We compute offsets */
893
size_t total = 0;
894
#define MK_OFFSET(v) \
895
size_t v ## _of = total; \
896
total = alignSize(v ## _of + v ## _sz, MEM_ALIGN)
897
898
MK_OFFSET(best_inl);
899
MK_OFFSET(curr_inl);
900
901
#undef MK_OFFSET
902
903
/* Allocate dynamic memory managed by cv::Mat */
904
mem.perRun.create(1, (int)(total + MEM_ALIGN), CV_8UC1);
905
906
/* Extract aligned pointer */
907
unsigned char* ptr = alignPtr(mem.perRun.data, MEM_ALIGN);
908
909
/* Assign pointers */
910
best.inl = (char*)(ptr + best_inl_of);
911
curr.inl = (char*)(ptr + curr_inl_of);
912
}
913
914
915
/**
916
* Deallocate per-run dynamic storage.
917
*
918
* Undoes the work by allocatePerRun().
919
*/
920
921
inline void RHO_HEST_REFC::deallocatePerRun(void){
922
best.inl = NULL;
923
curr.inl = NULL;
924
925
mem.perRun.release();
926
}
927
928
929
/**
930
* Deallocate per-object dynamic storage.
931
*
932
* Undoes the work by allocatePerObj().
933
*/
934
935
inline void RHO_HEST_REFC::deallocatePerObj(void){
936
ctrl.smpl = NULL;
937
curr.pkdPts = NULL;
938
curr.H = NULL;
939
best.H = NULL;
940
lm.JtJ = NULL;
941
lm.tmp1 = NULL;
942
lm.Jte = NULL;
943
944
mem.perObj.release();
945
}
946
947
948
/**
949
* Initialize SAC for a run given its arguments.
950
*
951
* Performs sanity-checks and memory allocations. Also initializes the state.
952
*
953
* @returns 0 if per-run initialization failed at any point; non-zero
954
* otherwise.
955
*
956
* Reads: arg.*, nr.*
957
* Writes: curr.*, best.*, ctrl.*, eval.*
958
*/
959
960
inline int RHO_HEST_REFC::initRun(void){
961
/**
962
* Sanitize arguments.
963
*
964
* Runs zeroth because these are easy-to-check errors and unambiguously
965
* mean something or other.
966
*/
967
968
if(!arg.src || !arg.dst){
969
/* Arguments src or dst are insane, must be != NULL */
970
return 0;
971
}
972
if(arg.N < (unsigned)SMPL_SIZE){
973
/* Argument N is insane, must be >= 4. */
974
return 0;
975
}
976
if(arg.maxD < 0){
977
/* Argument maxD is insane, must be >= 0. */
978
return 0;
979
}
980
if(arg.cfd < 0 || arg.cfd > 1){
981
/* Argument cfd is insane, must be in [0, 1]. */
982
return 0;
983
}
984
/* Clamp minInl to 4 or higher. */
985
arg.minInl = arg.minInl < (unsigned)SMPL_SIZE ? SMPL_SIZE : arg.minInl;
986
if(isNREnabled() && (arg.beta <= 0 || arg.beta >= 1)){
987
/* Argument beta is insane, must be in (0, 1). */
988
return 0;
989
}
990
if(!arg.finalH){
991
/* Argument finalH is insane, must be != NULL */
992
return 0;
993
}
994
995
/**
996
* Optional NR setup.
997
*
998
* Runs first because it is decoupled from most other things (*) and if it
999
* fails, it is easy to recover from.
1000
*
1001
* (*) The only things this code depends on is the flags argument, the nr.*
1002
* substruct and the sanity-checked N and beta arguments from above.
1003
*/
1004
1005
if(isNREnabled() && !ensureCapacity(arg.N, arg.beta)){
1006
return 0;
1007
}
1008
1009
/**
1010
* Inlier mask alloc.
1011
*
1012
* Runs second because we want to quit as fast as possible if we can't even
1013
* allocate the two masks.
1014
*/
1015
1016
allocatePerRun();
1017
1018
memset(best.inl, 0, arg.N);
1019
memset(curr.inl, 0, arg.N);
1020
1021
/**
1022
* Reset scalar per-run state.
1023
*
1024
* Runs third because there's no point in resetting/calculating a large
1025
* number of fields if something in the above junk failed.
1026
*/
1027
1028
ctrl.i = 0;
1029
ctrl.phNum = SMPL_SIZE;
1030
ctrl.phEndI = 1;
1031
ctrl.phEndFpI = sacInitPEndFpI(arg.rConvg, arg.N, SMPL_SIZE);
1032
ctrl.phMax = arg.N;
1033
ctrl.phNumInl = 0;
1034
ctrl.numModels = 0;
1035
1036
if(haveExtrinsicGuess()){
1037
memcpy(curr.H, arg.guessH, HSIZE);
1038
}else{
1039
memset(curr.H, 0, HSIZE);
1040
}
1041
curr.numInl = 0;
1042
1043
memset(best.H, 0, HSIZE);
1044
best.numInl = 0;
1045
1046
eval.Ntested = 0;
1047
eval.Ntestedtotal = 0;
1048
eval.good = 1;
1049
eval.t_M = SPRT_T_M;
1050
eval.m_S = SPRT_M_S;
1051
eval.epsilon = SPRT_EPSILON;
1052
eval.delta = SPRT_DELTA;
1053
designSPRTTest();
1054
1055
return 1;
1056
}
1057
1058
/**
1059
* Finalize SAC run.
1060
*
1061
* Deallocates per-run allocatable resources. Currently this consists only of
1062
* the best and current inlier masks, which are equal in size to p->arg.N
1063
* bytes.
1064
*
1065
* Reads: arg.bestInl, curr.inl, best.inl
1066
* Writes: curr.inl, best.inl
1067
*/
1068
1069
inline void RHO_HEST_REFC::finiRun(void){
1070
deallocatePerRun();
1071
}
1072
1073
/**
1074
* Hypothesize a model.
1075
*
1076
* Selects randomly a sample (within the rules of PROSAC) and generates a
1077
* new current model, and applies degeneracy tests to it.
1078
*
1079
* @returns 0 if hypothesized model could be rejected early as degenerate, and
1080
* non-zero otherwise.
1081
*/
1082
1083
inline int RHO_HEST_REFC::hypothesize(void){
1084
if(PROSACPhaseEndReached()){
1085
PROSACGoToNextPhase();
1086
}
1087
1088
getPROSACSample();
1089
if(isSampleDegenerate()){
1090
return 0;
1091
}
1092
1093
generateModel();
1094
if(isModelDegenerate()){
1095
return 0;
1096
}
1097
1098
return 1;
1099
}
1100
1101
/**
1102
* Verify the hypothesized model.
1103
*
1104
* Given the current model, evaluate its quality. If it is better than
1105
* everything before, save as new best model (and possibly refine it).
1106
*
1107
* Returns 1.
1108
*/
1109
1110
inline int RHO_HEST_REFC::verify(void){
1111
evaluateModelSPRT();
1112
updateSPRT();
1113
1114
if(isBestModel()){
1115
saveBestModel();
1116
1117
if(isRefineEnabled() && canRefine()){
1118
refine();
1119
}
1120
1121
updateBounds();
1122
1123
if(isNREnabled()){
1124
nStarOptimize();
1125
}
1126
}
1127
1128
return 1;
1129
}
1130
1131
/**
1132
* Check whether extrinsic guess was provided or not.
1133
*
1134
* @return Zero if no extrinsic guess was provided; non-zero otherwiseEE.
1135
*/
1136
1137
inline int RHO_HEST_REFC::haveExtrinsicGuess(void){
1138
return !!arg.guessH;
1139
}
1140
1141
/**
1142
* Check whether non-randomness criterion is enabled.
1143
*
1144
* @return Zero if non-randomness criterion disabled; non-zero if not.
1145
*/
1146
1147
inline int RHO_HEST_REFC::isNREnabled(void){
1148
return arg.flags & RHO_FLAG_ENABLE_NR;
1149
}
1150
1151
/**
1152
* Check whether best-model-so-far refinement is enabled.
1153
*
1154
* @return Zero if best-model-so-far refinement disabled; non-zero if not.
1155
*/
1156
1157
inline int RHO_HEST_REFC::isRefineEnabled(void){
1158
return arg.flags & RHO_FLAG_ENABLE_REFINEMENT;
1159
}
1160
1161
/**
1162
* Check whether final-model refinement is enabled.
1163
*
1164
* @return Zero if final-model refinement disabled; non-zero if not.
1165
*/
1166
1167
inline int RHO_HEST_REFC::isFinalRefineEnabled(void){
1168
return arg.flags & RHO_FLAG_ENABLE_FINAL_REFINEMENT;
1169
}
1170
1171
/**
1172
* Computes whether the end of the current PROSAC phase has been reached. At
1173
* PROSAC phase phNum, only matches [0, phNum) are sampled from.
1174
*
1175
* Reads (direct): ctrl.i, ctrl.phEndI, ctrl.phNum, ctrl.phMax
1176
* Reads (callees): None.
1177
* Writes (direct): None.
1178
* Writes (callees): None.
1179
*/
1180
1181
inline int RHO_HEST_REFC::PROSACPhaseEndReached(void){
1182
return ctrl.i >= ctrl.phEndI && ctrl.phNum < ctrl.phMax;
1183
}
1184
1185
/**
1186
* Updates unconditionally the necessary fields to move to the next PROSAC
1187
* stage.
1188
*
1189
* Not idempotent.
1190
*
1191
* Reads (direct): ctrl.phNum, ctrl.phEndFpI, ctrl.phEndI
1192
* Reads (callees): None.
1193
* Writes (direct): ctrl.phNum, ctrl.phEndFpI, ctrl.phEndI
1194
* Writes (callees): None.
1195
*/
1196
1197
inline void RHO_HEST_REFC::PROSACGoToNextPhase(void){
1198
double next;
1199
1200
ctrl.phNum++;
1201
next = (ctrl.phEndFpI * ctrl.phNum)/(ctrl.phNum - SMPL_SIZE);
1202
ctrl.phEndI += (unsigned)ceil(next - ctrl.phEndFpI);
1203
ctrl.phEndFpI = next;
1204
}
1205
1206
/**
1207
* Get a sample according to PROSAC rules. Namely:
1208
* - If we're past the phase end interaction, select randomly 4 out of the first
1209
* phNum matches.
1210
* - Otherwise, select match phNum-1 and select randomly the 3 others out of
1211
* the first phNum-1 matches.
1212
*
1213
* Reads (direct): ctrl.i, ctrl.phEndI, ctrl.phNum
1214
* Reads (callees): prng.s
1215
* Writes (direct): ctrl.smpl
1216
* Writes (callees): prng.s
1217
*/
1218
1219
inline void RHO_HEST_REFC::getPROSACSample(void){
1220
if(ctrl.i > ctrl.phEndI){
1221
/* FIXME: Dubious. Review. */
1222
rndSmpl(4, ctrl.smpl, ctrl.phNum);/* Used to be phMax */
1223
}else{
1224
rndSmpl(3, ctrl.smpl, ctrl.phNum-1);
1225
ctrl.smpl[3] = ctrl.phNum-1;
1226
}
1227
}
1228
1229
/**
1230
* Choose, without repetition, sampleSize integers in the range [0, numDataPoints).
1231
*
1232
* Reads (direct): None.
1233
* Reads (callees): prng.s
1234
* Writes (direct): None.
1235
* Writes (callees): prng.s
1236
*/
1237
1238
inline void RHO_HEST_REFC::rndSmpl(unsigned sampleSize,
1239
unsigned* currentSample,
1240
unsigned dataSetSize){
1241
/**
1242
* If sampleSize is very close to dataSetSize, we use selection sampling.
1243
* Otherwise we use the naive sampling technique wherein we select random
1244
* indexes until sampleSize of them are distinct.
1245
*/
1246
1247
if(sampleSize*2>dataSetSize){
1248
/**
1249
* Selection Sampling:
1250
*
1251
* Algorithm S (Selection sampling technique). To select n records at random from a set of N, where 0 < n <= N.
1252
* S1. [Initialize.] Set t = 0, m = 0. (During this algorithm, m represents the number of records selected so far,
1253
* and t is the total number of input records that we have dealt with.)
1254
* S2. [Generate U.] Generate a random number U, uniformly distributed between zero and one.
1255
* S3. [Test.] If (N - t)U >= n - m, go to step S5.
1256
* S4. [Select.] Select the next record for the sample, and increase m and t by 1. If m < n, go to step S2;
1257
* otherwise the sample is complete and the algorithm terminates.
1258
* S5. [Skip.] Skip the next record (do not include it in the sample), increase t by 1, and go back to step S2.
1259
*
1260
* Replaced m with i and t with j in the below code.
1261
*/
1262
1263
unsigned i=0,j=0;
1264
1265
for(i=0;i<sampleSize;j++){
1266
double U=fastRandom();
1267
if((dataSetSize-j)*U < (sampleSize-i)){
1268
currentSample[i++]=j;
1269
}
1270
}
1271
}else{
1272
/**
1273
* Naive sampling technique. Generate indexes until sampleSize of them are distinct.
1274
*/
1275
1276
unsigned i, j;
1277
for(i=0;i<sampleSize;i++){
1278
int inList;
1279
1280
do{
1281
currentSample[i] = (unsigned)(dataSetSize*fastRandom());
1282
1283
inList=0;
1284
for(j=0;j<i;j++){
1285
if(currentSample[i] == currentSample[j]){
1286
inList=1;
1287
break;
1288
}
1289
}
1290
}while(inList);
1291
}
1292
}
1293
}
1294
1295
/**
1296
* Checks whether the *sample* is degenerate prior to model generation.
1297
* - First, the extremely cheap numerical degeneracy test is run, which weeds
1298
* out bad samples to the optimized GE implementation.
1299
* - Second, the geometrical degeneracy test is run, which weeds out most other
1300
* bad samples.
1301
*
1302
* Reads (direct): ctrl.smpl, arg.src, arg.dst
1303
* Reads (callees): None.
1304
* Writes (direct): curr.pkdPts
1305
* Writes (callees): None.
1306
*/
1307
1308
inline int RHO_HEST_REFC::isSampleDegenerate(void){
1309
unsigned i0 = ctrl.smpl[0], i1 = ctrl.smpl[1], i2 = ctrl.smpl[2], i3 = ctrl.smpl[3];
1310
typedef struct{float x,y;} MyPt2f;
1311
MyPt2f* pkdPts = (MyPt2f*)curr.pkdPts, *src = (MyPt2f*)arg.src, *dst = (MyPt2f*)arg.dst;
1312
1313
/**
1314
* Pack the matches selected by the SAC algorithm.
1315
* Must be packed points[0:7] = {srcx0, srcy0, srcx1, srcy1, srcx2, srcy2, srcx3, srcy3}
1316
* points[8:15] = {dstx0, dsty0, dstx1, dsty1, dstx2, dsty2, dstx3, dsty3}
1317
* Gather 4 points into the vector
1318
*/
1319
1320
pkdPts[0] = src[i0];
1321
pkdPts[1] = src[i1];
1322
pkdPts[2] = src[i2];
1323
pkdPts[3] = src[i3];
1324
pkdPts[4] = dst[i0];
1325
pkdPts[5] = dst[i1];
1326
pkdPts[6] = dst[i2];
1327
pkdPts[7] = dst[i3];
1328
1329
/**
1330
* If the matches' source points have common x and y coordinates, abort.
1331
*/
1332
1333
if(pkdPts[0].x == pkdPts[1].x || pkdPts[1].x == pkdPts[2].x ||
1334
pkdPts[2].x == pkdPts[3].x || pkdPts[0].x == pkdPts[2].x ||
1335
pkdPts[1].x == pkdPts[3].x || pkdPts[0].x == pkdPts[3].x ||
1336
pkdPts[0].y == pkdPts[1].y || pkdPts[1].y == pkdPts[2].y ||
1337
pkdPts[2].y == pkdPts[3].y || pkdPts[0].y == pkdPts[2].y ||
1338
pkdPts[1].y == pkdPts[3].y || pkdPts[0].y == pkdPts[3].y){
1339
return 1;
1340
}
1341
1342
/* If the matches do not satisfy the strong geometric constraint, abort. */
1343
/* (0 x 1) * 2 */
1344
float cross0s0 = pkdPts[0].y-pkdPts[1].y;
1345
float cross0s1 = pkdPts[1].x-pkdPts[0].x;
1346
float cross0s2 = pkdPts[0].x*pkdPts[1].y-pkdPts[0].y*pkdPts[1].x;
1347
float dots0 = cross0s0*pkdPts[2].x + cross0s1*pkdPts[2].y + cross0s2;
1348
float cross0d0 = pkdPts[4].y-pkdPts[5].y;
1349
float cross0d1 = pkdPts[5].x-pkdPts[4].x;
1350
float cross0d2 = pkdPts[4].x*pkdPts[5].y-pkdPts[4].y*pkdPts[5].x;
1351
float dotd0 = cross0d0*pkdPts[6].x + cross0d1*pkdPts[6].y + cross0d2;
1352
if(((int)dots0^(int)dotd0) < 0){
1353
return 1;
1354
}
1355
/* (0 x 1) * 3 */
1356
float cross1s0 = cross0s0;
1357
float cross1s1 = cross0s1;
1358
float cross1s2 = cross0s2;
1359
float dots1 = cross1s0*pkdPts[3].x + cross1s1*pkdPts[3].y + cross1s2;
1360
float cross1d0 = cross0d0;
1361
float cross1d1 = cross0d1;
1362
float cross1d2 = cross0d2;
1363
float dotd1 = cross1d0*pkdPts[7].x + cross1d1*pkdPts[7].y + cross1d2;
1364
if(((int)dots1^(int)dotd1) < 0){
1365
return 1;
1366
}
1367
/* (2 x 3) * 0 */
1368
float cross2s0 = pkdPts[2].y-pkdPts[3].y;
1369
float cross2s1 = pkdPts[3].x-pkdPts[2].x;
1370
float cross2s2 = pkdPts[2].x*pkdPts[3].y-pkdPts[2].y*pkdPts[3].x;
1371
float dots2 = cross2s0*pkdPts[0].x + cross2s1*pkdPts[0].y + cross2s2;
1372
float cross2d0 = pkdPts[6].y-pkdPts[7].y;
1373
float cross2d1 = pkdPts[7].x-pkdPts[6].x;
1374
float cross2d2 = pkdPts[6].x*pkdPts[7].y-pkdPts[6].y*pkdPts[7].x;
1375
float dotd2 = cross2d0*pkdPts[4].x + cross2d1*pkdPts[4].y + cross2d2;
1376
if(((int)dots2^(int)dotd2) < 0){
1377
return 1;
1378
}
1379
/* (2 x 3) * 1 */
1380
float cross3s0 = cross2s0;
1381
float cross3s1 = cross2s1;
1382
float cross3s2 = cross2s2;
1383
float dots3 = cross3s0*pkdPts[1].x + cross3s1*pkdPts[1].y + cross3s2;
1384
float cross3d0 = cross2d0;
1385
float cross3d1 = cross2d1;
1386
float cross3d2 = cross2d2;
1387
float dotd3 = cross3d0*pkdPts[5].x + cross3d1*pkdPts[5].y + cross3d2;
1388
if(((int)dots3^(int)dotd3) < 0){
1389
return 1;
1390
}
1391
1392
/* Otherwise, accept */
1393
return 0;
1394
}
1395
1396
/**
1397
* Compute homography of matches in gathered, packed sample and output the
1398
* current homography.
1399
*
1400
* Reads (direct): None.
1401
* Reads (callees): curr.pkdPts
1402
* Writes (direct): None.
1403
* Writes (callees): curr.H
1404
*/
1405
1406
inline void RHO_HEST_REFC::generateModel(void){
1407
hFuncRefC(curr.pkdPts, curr.H);
1408
}
1409
1410
/**
1411
* Checks whether the model is itself degenerate.
1412
* - One test: All elements of the homography are added, and if the result is
1413
* NaN the homography is rejected.
1414
*
1415
* Reads (direct): curr.H
1416
* Reads (callees): None.
1417
* Writes (direct): None.
1418
* Writes (callees): None.
1419
*/
1420
1421
inline int RHO_HEST_REFC::isModelDegenerate(void){
1422
int degenerate;
1423
float* H = curr.H;
1424
float f=H[0]+H[1]+H[2]+H[3]+H[4]+H[5]+H[6]+H[7];
1425
1426
/* degenerate = isnan(f); */
1427
/* degenerate = f!=f;// Only NaN is not equal to itself. */
1428
degenerate = cvIsNaN(f);
1429
/* degenerate = 0; */
1430
1431
1432
return degenerate;
1433
}
1434
1435
/**
1436
* Evaluates the current model using SPRT for early exiting.
1437
*
1438
* Reads (direct): arg.maxD, arg.src, arg.dst, arg.N, curr.inl, curr.H,
1439
* ctrl.numModels, eval.Ntestedtotal, eval.lambdaAccept,
1440
* eval.lambdaReject, eval.A
1441
* Reads (callees): None.
1442
* Writes (direct): ctrl.numModels, curr.numInl, eval.Ntested, eval.good,
1443
* eval.Ntestedtotal
1444
* Writes (callees): None.
1445
*/
1446
1447
inline void RHO_HEST_REFC::evaluateModelSPRT(void){
1448
unsigned i;
1449
unsigned isInlier;
1450
double lambda = 1.0;
1451
float distSq = arg.maxD*arg.maxD;
1452
const float* src = arg.src;
1453
const float* dst = arg.dst;
1454
char* inl = curr.inl;
1455
const float* H = curr.H;
1456
1457
1458
ctrl.numModels++;
1459
1460
curr.numInl = 0;
1461
eval.Ntested = 0;
1462
eval.good = 1;
1463
1464
1465
/* SCALAR */
1466
for(i=0;i<arg.N && eval.good;i++){
1467
/* Backproject */
1468
float x=src[i*2],y=src[i*2+1];
1469
float X=dst[i*2],Y=dst[i*2+1];
1470
1471
float reprojX=H[0]*x+H[1]*y+H[2]; /* ( X_1 ) ( H_11 H_12 H_13 ) (x_1) */
1472
float reprojY=H[3]*x+H[4]*y+H[5]; /* ( X_2 ) = ( H_21 H_22 H_23 ) (x_2) */
1473
float reprojZ=H[6]*x+H[7]*y+1.0f; /* ( X_3 ) ( H_31 H_32 H_33=1.0 ) (x_3 = 1.0) */
1474
1475
/* reproj is in homogeneous coordinates. To bring back to "regular" coordinates, divide by Z. */
1476
reprojX/=reprojZ;
1477
reprojY/=reprojZ;
1478
1479
/* Compute distance */
1480
reprojX-=X;
1481
reprojY-=Y;
1482
reprojX*=reprojX;
1483
reprojY*=reprojY;
1484
float reprojDist = reprojX+reprojY;
1485
1486
/* ... */
1487
isInlier = reprojDist <= distSq;
1488
curr.numInl += isInlier;
1489
*inl++ = (char)isInlier;
1490
1491
1492
/* SPRT */
1493
lambda *= isInlier ? eval.lambdaAccept : eval.lambdaReject;
1494
eval.good = lambda <= eval.A;
1495
/* If !good, the threshold A was exceeded, so we're rejecting */
1496
}
1497
1498
1499
eval.Ntested = i;
1500
eval.Ntestedtotal += i;
1501
}
1502
1503
/**
1504
* Update either the delta or epsilon SPRT parameters, depending on the events
1505
* that transpired in the previous evaluation.
1506
*
1507
* Reads (direct): eval.good, curr.numInl, arg.N, eval.Ntested, eval.delta
1508
* Reads (callees): eval.delta, eval.epsilon, eval.t_M, eval.m_S
1509
* Writes (direct): eval.epsilon, eval.delta
1510
* Writes (callees): eval.A, eval.lambdaReject, eval.lambdaAccept
1511
*/
1512
1513
inline void RHO_HEST_REFC::updateSPRT(void){
1514
if(eval.good){
1515
if(isBestModel()){
1516
eval.epsilon = (double)curr.numInl/arg.N;
1517
designSPRTTest();
1518
}
1519
}else{
1520
double newDelta = (double)curr.numInl/eval.Ntested;
1521
1522
if(newDelta > 0){
1523
double relChange = fabs(eval.delta - newDelta)/ eval.delta;
1524
if(relChange > MIN_DELTA_CHNG){
1525
eval.delta = newDelta;
1526
designSPRTTest();
1527
}
1528
}
1529
}
1530
}
1531
1532
/**
1533
* Numerically compute threshold A from the estimated delta, epsilon, t_M and
1534
* m_S values.
1535
*
1536
* Epsilon: Denotes the probability that a randomly chosen data point is
1537
* consistent with a good model.
1538
* Delta: Denotes the probability that a randomly chosen data point is
1539
* consistent with a bad model.
1540
* t_M: Time needed to instantiate a model hypotheses given a sample.
1541
* (Computing model parameters from a sample takes the same time
1542
* as verification of t_M data points)
1543
* m_S: The number of models that are verified per sample.
1544
*/
1545
1546
static inline double sacDesignSPRTTest(double delta, double epsilon, double t_M, double m_S){
1547
double An, C, K, prevAn;
1548
unsigned i;
1549
1550
/**
1551
* Randomized RANSAC with Sequential Probability Ratio Test, ICCV 2005
1552
* Eq (2)
1553
*/
1554
1555
C = (1-delta) * log((1-delta)/(1-epsilon)) +
1556
delta * log( delta / epsilon );
1557
1558
/**
1559
* Randomized RANSAC with Sequential Probability Ratio Test, ICCV 2005
1560
* Eq (6)
1561
* K = K_1/K_2 + 1 = (t_M*C)/m_S + 1
1562
*/
1563
1564
K = t_M*C/m_S + 1;
1565
1566
/**
1567
* Randomized RANSAC with Sequential Probability Ratio Test, ICCV 2005
1568
* Paragraph below Eq (6)
1569
*
1570
* A* = lim_{n -> infty} A_n, where
1571
* A_0 = K1/K2 + 1 and
1572
* A_{n+1} = K1/K2 + 1 + log(A_n)
1573
* The series converges fast, typically within four iterations.
1574
*/
1575
1576
An = K;
1577
i = 0;
1578
1579
do{
1580
prevAn = An;
1581
An = K + log(An);
1582
}while((An-prevAn > 1.5e-8) && (++i < 10));
1583
1584
/**
1585
* Return A = An_stopping, with n_stopping < 10
1586
*/
1587
1588
return An;
1589
}
1590
1591
/**
1592
* Design the SPRT test. Shorthand for
1593
* A = sprt(delta, epsilon, t_M, m_S);
1594
*
1595
* Idempotent.
1596
*
1597
* Reads (direct): eval.delta, eval.epsilon, eval.t_M, eval.m_S
1598
* Reads (callees): None.
1599
* Writes (direct): eval.A, eval.lambdaReject, eval.lambdaAccept.
1600
* Writes (callees): None.
1601
*/
1602
1603
inline void RHO_HEST_REFC::designSPRTTest(void){
1604
eval.A = sacDesignSPRTTest(eval.delta, eval.epsilon, eval.t_M, eval.m_S);
1605
eval.lambdaReject = ((1.0 - eval.delta) / (1.0 - eval.epsilon));
1606
eval.lambdaAccept = (( eval.delta ) / ( eval.epsilon ));
1607
}
1608
1609
/**
1610
* Return whether the current model is the best model so far.
1611
*
1612
* @return Non-zero if this is the model with the most inliers seen so far;
1613
* 0 otherwise.
1614
*
1615
* Reads (direct): curr.numInl, best.numInl
1616
* Reads (callees): None.
1617
* Writes (direct): None.
1618
* Writes (callees): None.
1619
*/
1620
1621
inline int RHO_HEST_REFC::isBestModel(void){
1622
return curr.numInl > best.numInl;
1623
}
1624
1625
/**
1626
* Returns whether the current-best model is good enough to be an
1627
* acceptable best model, by checking whether it meets the minimum
1628
* number of inliers.
1629
*
1630
* @return Non-zero if the current model is "good enough" to save;
1631
* 0 otherwise.
1632
*
1633
* Reads (direct): best.numInl, arg.minInl
1634
* Reads (callees): None.
1635
* Writes (direct): None.
1636
* Writes (callees): None.
1637
*/
1638
1639
inline int RHO_HEST_REFC::isBestModelGoodEnough(void){
1640
return best.numInl >= arg.minInl;
1641
}
1642
1643
/**
1644
* Make current model new best model by swapping the homography, inlier mask
1645
* and count of inliers between the current and best models.
1646
*
1647
* Reads (direct): curr.H, curr.inl, curr.numInl,
1648
* best.H, best.inl, best.numInl
1649
* Reads (callees): None.
1650
* Writes (direct): curr.H, curr.inl, curr.numInl,
1651
* best.H, best.inl, best.numInl
1652
* Writes (callees): None.
1653
*/
1654
1655
inline void RHO_HEST_REFC::saveBestModel(void){
1656
float* H = curr.H;
1657
char* inl = curr.inl;
1658
unsigned numInl = curr.numInl;
1659
1660
curr.H = best.H;
1661
curr.inl = best.inl;
1662
curr.numInl = best.numInl;
1663
1664
best.H = H;
1665
best.inl = inl;
1666
best.numInl = numInl;
1667
}
1668
1669
/**
1670
* Compute NR table entries [start, N) for given beta.
1671
*/
1672
1673
static inline void sacInitNonRand(double beta,
1674
unsigned start,
1675
unsigned N,
1676
unsigned* nonRandMinInl){
1677
unsigned n = SMPL_SIZE+1 > start ? SMPL_SIZE+1 : start;
1678
double beta_beta1_sq_chi = sqrt(beta*(1.0-beta)) * CHI_SQ;
1679
1680
for(; n < N; n++){
1681
double mu = n * beta;
1682
double sigma = sqrt((double)n)* beta_beta1_sq_chi;
1683
unsigned i_min = (unsigned)ceil(SMPL_SIZE + mu + sigma);
1684
1685
nonRandMinInl[n] = i_min;
1686
}
1687
}
1688
1689
/**
1690
* Optimize the stopping criterion to account for the non-randomness criterion
1691
* of PROSAC.
1692
*
1693
* Reads (direct): arg.N, best.numInl, nr.tbl, arg.inl, ctrl.phMax,
1694
* ctrl.phNumInl, arg.cfd, arg.maxI
1695
* Reads (callees): None.
1696
* Writes (direct): arg.maxI, ctrl.phMax, ctrl.phNumInl
1697
* Writes (callees): None.
1698
*/
1699
1700
inline void RHO_HEST_REFC::nStarOptimize(void){
1701
unsigned min_sample_length = 10*2; /*(N * INLIERS_RATIO) */
1702
unsigned best_n = arg.N;
1703
unsigned test_n = best_n;
1704
unsigned bestNumInl = best.numInl;
1705
unsigned testNumInl = bestNumInl;
1706
1707
for(;test_n > min_sample_length && testNumInl;test_n--){
1708
if(testNumInl*best_n > bestNumInl*test_n){
1709
if(testNumInl < nr.tbl[test_n]){
1710
break;
1711
}
1712
best_n = test_n;
1713
bestNumInl = testNumInl;
1714
}
1715
testNumInl -= !!best.inl[test_n-1];
1716
}
1717
1718
if(bestNumInl*ctrl.phMax > ctrl.phNumInl*best_n){
1719
ctrl.phMax = best_n;
1720
ctrl.phNumInl = bestNumInl;
1721
arg.maxI = sacCalcIterBound(arg.cfd,
1722
(double)ctrl.phNumInl/ctrl.phMax,
1723
SMPL_SIZE,
1724
arg.maxI);
1725
}
1726
}
1727
1728
/**
1729
* Classic RANSAC iteration bound based on largest # of inliers.
1730
*
1731
* Reads (direct): arg.maxI, arg.cfd, best.numInl, arg.N
1732
* Reads (callees): None.
1733
* Writes (direct): arg.maxI
1734
* Writes (callees): None.
1735
*/
1736
1737
inline void RHO_HEST_REFC::updateBounds(void){
1738
arg.maxI = sacCalcIterBound(arg.cfd,
1739
(double)best.numInl/arg.N,
1740
SMPL_SIZE,
1741
arg.maxI);
1742
}
1743
1744
/**
1745
* Output the best model so far to the output argument.
1746
*
1747
* Reads (direct): arg.finalH, best.H, arg.inl, best.inl, arg.N
1748
* Reads (callees): arg.finalH, arg.inl, arg.N
1749
* Writes (direct): arg.finalH, arg.inl
1750
* Writes (callees): arg.finalH, arg.inl
1751
*/
1752
1753
inline void RHO_HEST_REFC::outputModel(void){
1754
if(isBestModelGoodEnough()){
1755
memcpy(arg.finalH, best.H, HSIZE);
1756
if(arg.inl){
1757
memcpy(arg.inl, best.inl, arg.N);
1758
}
1759
}else{
1760
outputZeroH();
1761
}
1762
}
1763
1764
/**
1765
* Output a zeroed H to the output argument.
1766
*
1767
* Reads (direct): arg.finalH, arg.inl, arg.N
1768
* Reads (callees): None.
1769
* Writes (direct): arg.finalH, arg.inl
1770
* Writes (callees): None.
1771
*/
1772
1773
inline void RHO_HEST_REFC::outputZeroH(void){
1774
if(arg.finalH){
1775
memset(arg.finalH, 0, HSIZE);
1776
}
1777
if(arg.inl){
1778
memset(arg.inl, 0, arg.N);
1779
}
1780
}
1781
1782
/**
1783
* Compute the real-valued number of samples per phase, given the RANSAC convergence speed,
1784
* data set size and sample size.
1785
*/
1786
1787
static inline double sacInitPEndFpI(const unsigned ransacConvg,
1788
const unsigned n,
1789
const unsigned s){
1790
double numer=1, denom=1;
1791
1792
unsigned i;
1793
for(i=0;i<s;i++){
1794
numer *= s-i;
1795
denom *= n-i;
1796
}
1797
1798
return ransacConvg*numer/denom;
1799
}
1800
1801
/**
1802
* Estimate the number of iterations required based on the requested confidence,
1803
* proportion of inliers in the best model so far and sample size.
1804
*
1805
* Clamp return value at maxIterationBound.
1806
*/
1807
1808
static inline unsigned sacCalcIterBound(double confidence,
1809
double inlierRate,
1810
unsigned sampleSize,
1811
unsigned maxIterBound){
1812
unsigned retVal;
1813
1814
/**
1815
* Formula chosen from http://en.wikipedia.org/wiki/RANSAC#The_parameters :
1816
*
1817
* \[ k = \frac{\log{(1-confidence)}}{\log{(1-inlierRate**sampleSize)}} \]
1818
*/
1819
1820
double atLeastOneOutlierProbability = 1.-pow(inlierRate, (double)sampleSize);
1821
1822
/**
1823
* There are two special cases: When argument to log() is 0 and when it is 1.
1824
* Each has a special meaning.
1825
*/
1826
1827
if(atLeastOneOutlierProbability>=1.){
1828
/**
1829
* A certainty of picking at least one outlier means that we will need
1830
* an infinite amount of iterations in order to find a correct solution.
1831
*/
1832
1833
retVal = maxIterBound;
1834
}else if(atLeastOneOutlierProbability<=0.){
1835
/**
1836
* The certainty of NOT picking an outlier means that only 1 iteration
1837
* is needed to find a solution.
1838
*/
1839
1840
retVal = 1;
1841
}else{
1842
/**
1843
* Since 1-confidence (the probability of the model being based on at
1844
* least one outlier in the data) is equal to
1845
* (1-inlierRate**sampleSize)**numIterations (the probability of picking
1846
* at least one outlier in numIterations samples), we can isolate
1847
* numIterations (the return value) into
1848
*/
1849
1850
retVal = (unsigned)ceil(log(1.-confidence)/log(atLeastOneOutlierProbability));
1851
}
1852
1853
/**
1854
* Clamp to maxIterationBound.
1855
*/
1856
1857
return retVal <= maxIterBound ? retVal : maxIterBound;
1858
}
1859
1860
1861
/**
1862
* Given 4 matches, computes the homography that relates them using Gaussian
1863
* Elimination. The row operations are as given in the paper.
1864
*
1865
* TODO: Clean this up. The code is hideous, and might even conceal sign bugs
1866
* (specifically relating to whether the last column should be negated,
1867
* or not).
1868
*/
1869
1870
static void hFuncRefC(float* packedPoints,/* Source (four x,y float coordinates) points followed by
1871
destination (four x,y float coordinates) points, aligned by 32 bytes */
1872
float* H){ /* Homography (three 16-byte aligned rows of 3 floats) */
1873
float x0=*packedPoints++;
1874
float y0=*packedPoints++;
1875
float x1=*packedPoints++;
1876
float y1=*packedPoints++;
1877
float x2=*packedPoints++;
1878
float y2=*packedPoints++;
1879
float x3=*packedPoints++;
1880
float y3=*packedPoints++;
1881
float X0=*packedPoints++;
1882
float Y0=*packedPoints++;
1883
float X1=*packedPoints++;
1884
float Y1=*packedPoints++;
1885
float X2=*packedPoints++;
1886
float Y2=*packedPoints++;
1887
float X3=*packedPoints++;
1888
float Y3=*packedPoints++;
1889
1890
float x0X0=x0*X0, x1X1=x1*X1, x2X2=x2*X2, x3X3=x3*X3;
1891
float x0Y0=x0*Y0, x1Y1=x1*Y1, x2Y2=x2*Y2, x3Y3=x3*Y3;
1892
float y0X0=y0*X0, y1X1=y1*X1, y2X2=y2*X2, y3X3=y3*X3;
1893
float y0Y0=y0*Y0, y1Y1=y1*Y1, y2Y2=y2*Y2, y3Y3=y3*Y3;
1894
1895
1896
/**
1897
* [0] [1] Hidden Prec
1898
* x0 y0 1 x1
1899
* x1 y1 1 x1
1900
* x2 y2 1 x1
1901
* x3 y3 1 x1
1902
*
1903
* Eliminate ones in column 2 and 5.
1904
* R(0)-=R(2)
1905
* R(1)-=R(2)
1906
* R(3)-=R(2)
1907
*
1908
* [0] [1] Hidden Prec
1909
* x0-x2 y0-y2 0 x1+1
1910
* x1-x2 y1-y2 0 x1+1
1911
* x2 y2 1 x1
1912
* x3-x2 y3-y2 0 x1+1
1913
*
1914
* Eliminate column 0 of rows 1 and 3
1915
* R(1)=(x0-x2)*R(1)-(x1-x2)*R(0), y1'=(y1-y2)(x0-x2)-(x1-x2)(y0-y2)
1916
* R(3)=(x0-x2)*R(3)-(x3-x2)*R(0), y3'=(y3-y2)(x0-x2)-(x3-x2)(y0-y2)
1917
*
1918
* [0] [1] Hidden Prec
1919
* x0-x2 y0-y2 0 x1+1
1920
* 0 y1' 0 x2+3
1921
* x2 y2 1 x1
1922
* 0 y3' 0 x2+3
1923
*
1924
* Eliminate column 1 of rows 0 and 3
1925
* R(3)=y1'*R(3)-y3'*R(1)
1926
* R(0)=y1'*R(0)-(y0-y2)*R(1)
1927
*
1928
* [0] [1] Hidden Prec
1929
* x0' 0 0 x3+5
1930
* 0 y1' 0 x2+3
1931
* x2 y2 1 x1
1932
* 0 0 0 x4+7
1933
*
1934
* Eliminate columns 0 and 1 of row 2
1935
* R(0)/=x0'
1936
* R(1)/=y1'
1937
* R(2)-= (x2*R(0) + y2*R(1))
1938
*
1939
* [0] [1] Hidden Prec
1940
* 1 0 0 x6+10
1941
* 0 1 0 x4+6
1942
* 0 0 1 x4+7
1943
* 0 0 0 x4+7
1944
*/
1945
1946
/**
1947
* Eliminate ones in column 2 and 5.
1948
* R(0)-=R(2)
1949
* R(1)-=R(2)
1950
* R(3)-=R(2)
1951
*/
1952
1953
/*float minor[4][2] = {{x0-x2,y0-y2},
1954
{x1-x2,y1-y2},
1955
{x2 ,y2 },
1956
{x3-x2,y3-y2}};*/
1957
/*float major[8][3] = {{x2X2-x0X0,y2X2-y0X0,(X0-X2)},
1958
{x2X2-x1X1,y2X2-y1X1,(X1-X2)},
1959
{-x2X2 ,-y2X2 ,(X2 )},
1960
{x2X2-x3X3,y2X2-y3X3,(X3-X2)},
1961
{x2Y2-x0Y0,y2Y2-y0Y0,(Y0-Y2)},
1962
{x2Y2-x1Y1,y2Y2-y1Y1,(Y1-Y2)},
1963
{-x2Y2 ,-y2Y2 ,(Y2 )},
1964
{x2Y2-x3Y3,y2Y2-y3Y3,(Y3-Y2)}};*/
1965
float minor[2][4] = {{x0-x2,x1-x2,x2 ,x3-x2},
1966
{y0-y2,y1-y2,y2 ,y3-y2}};
1967
float major[3][8] = {{x2X2-x0X0,x2X2-x1X1,-x2X2 ,x2X2-x3X3,x2Y2-x0Y0,x2Y2-x1Y1,-x2Y2 ,x2Y2-x3Y3},
1968
{y2X2-y0X0,y2X2-y1X1,-y2X2 ,y2X2-y3X3,y2Y2-y0Y0,y2Y2-y1Y1,-y2Y2 ,y2Y2-y3Y3},
1969
{ (X0-X2) , (X1-X2) , (X2 ) , (X3-X2) , (Y0-Y2) , (Y1-Y2) , (Y2 ) , (Y3-Y2) }};
1970
1971
/**
1972
* int i;
1973
* for(i=0;i<8;i++) major[2][i]=-major[2][i];
1974
* Eliminate column 0 of rows 1 and 3
1975
* R(1)=(x0-x2)*R(1)-(x1-x2)*R(0), y1'=(y1-y2)(x0-x2)-(x1-x2)(y0-y2)
1976
* R(3)=(x0-x2)*R(3)-(x3-x2)*R(0), y3'=(y3-y2)(x0-x2)-(x3-x2)(y0-y2)
1977
*/
1978
1979
float scalar1=minor[0][0], scalar2=minor[0][1];
1980
minor[1][1]=minor[1][1]*scalar1-minor[1][0]*scalar2;
1981
1982
major[0][1]=major[0][1]*scalar1-major[0][0]*scalar2;
1983
major[1][1]=major[1][1]*scalar1-major[1][0]*scalar2;
1984
major[2][1]=major[2][1]*scalar1-major[2][0]*scalar2;
1985
1986
major[0][5]=major[0][5]*scalar1-major[0][4]*scalar2;
1987
major[1][5]=major[1][5]*scalar1-major[1][4]*scalar2;
1988
major[2][5]=major[2][5]*scalar1-major[2][4]*scalar2;
1989
1990
scalar2=minor[0][3];
1991
minor[1][3]=minor[1][3]*scalar1-minor[1][0]*scalar2;
1992
1993
major[0][3]=major[0][3]*scalar1-major[0][0]*scalar2;
1994
major[1][3]=major[1][3]*scalar1-major[1][0]*scalar2;
1995
major[2][3]=major[2][3]*scalar1-major[2][0]*scalar2;
1996
1997
major[0][7]=major[0][7]*scalar1-major[0][4]*scalar2;
1998
major[1][7]=major[1][7]*scalar1-major[1][4]*scalar2;
1999
major[2][7]=major[2][7]*scalar1-major[2][4]*scalar2;
2000
2001
/**
2002
* Eliminate column 1 of rows 0 and 3
2003
* R(3)=y1'*R(3)-y3'*R(1)
2004
* R(0)=y1'*R(0)-(y0-y2)*R(1)
2005
*/
2006
2007
scalar1=minor[1][1];scalar2=minor[1][3];
2008
major[0][3]=major[0][3]*scalar1-major[0][1]*scalar2;
2009
major[1][3]=major[1][3]*scalar1-major[1][1]*scalar2;
2010
major[2][3]=major[2][3]*scalar1-major[2][1]*scalar2;
2011
2012
major[0][7]=major[0][7]*scalar1-major[0][5]*scalar2;
2013
major[1][7]=major[1][7]*scalar1-major[1][5]*scalar2;
2014
major[2][7]=major[2][7]*scalar1-major[2][5]*scalar2;
2015
2016
scalar2=minor[1][0];
2017
minor[0][0]=minor[0][0]*scalar1-minor[0][1]*scalar2;
2018
2019
major[0][0]=major[0][0]*scalar1-major[0][1]*scalar2;
2020
major[1][0]=major[1][0]*scalar1-major[1][1]*scalar2;
2021
major[2][0]=major[2][0]*scalar1-major[2][1]*scalar2;
2022
2023
major[0][4]=major[0][4]*scalar1-major[0][5]*scalar2;
2024
major[1][4]=major[1][4]*scalar1-major[1][5]*scalar2;
2025
major[2][4]=major[2][4]*scalar1-major[2][5]*scalar2;
2026
2027
/**
2028
* Eliminate columns 0 and 1 of row 2
2029
* R(0)/=x0'
2030
* R(1)/=y1'
2031
* R(2)-= (x2*R(0) + y2*R(1))
2032
*/
2033
2034
scalar1=1.0f/minor[0][0];
2035
major[0][0]*=scalar1;
2036
major[1][0]*=scalar1;
2037
major[2][0]*=scalar1;
2038
major[0][4]*=scalar1;
2039
major[1][4]*=scalar1;
2040
major[2][4]*=scalar1;
2041
2042
scalar1=1.0f/minor[1][1];
2043
major[0][1]*=scalar1;
2044
major[1][1]*=scalar1;
2045
major[2][1]*=scalar1;
2046
major[0][5]*=scalar1;
2047
major[1][5]*=scalar1;
2048
major[2][5]*=scalar1;
2049
2050
2051
scalar1=minor[0][2];scalar2=minor[1][2];
2052
major[0][2]-=major[0][0]*scalar1+major[0][1]*scalar2;
2053
major[1][2]-=major[1][0]*scalar1+major[1][1]*scalar2;
2054
major[2][2]-=major[2][0]*scalar1+major[2][1]*scalar2;
2055
2056
major[0][6]-=major[0][4]*scalar1+major[0][5]*scalar2;
2057
major[1][6]-=major[1][4]*scalar1+major[1][5]*scalar2;
2058
major[2][6]-=major[2][4]*scalar1+major[2][5]*scalar2;
2059
2060
/* Only major matters now. R(3) and R(7) correspond to the hollowed-out rows. */
2061
scalar1=major[0][7];
2062
major[1][7]/=scalar1;
2063
major[2][7]/=scalar1;
2064
2065
scalar1=major[0][0];major[1][0]-=scalar1*major[1][7];major[2][0]-=scalar1*major[2][7];
2066
scalar1=major[0][1];major[1][1]-=scalar1*major[1][7];major[2][1]-=scalar1*major[2][7];
2067
scalar1=major[0][2];major[1][2]-=scalar1*major[1][7];major[2][2]-=scalar1*major[2][7];
2068
scalar1=major[0][3];major[1][3]-=scalar1*major[1][7];major[2][3]-=scalar1*major[2][7];
2069
scalar1=major[0][4];major[1][4]-=scalar1*major[1][7];major[2][4]-=scalar1*major[2][7];
2070
scalar1=major[0][5];major[1][5]-=scalar1*major[1][7];major[2][5]-=scalar1*major[2][7];
2071
scalar1=major[0][6];major[1][6]-=scalar1*major[1][7];major[2][6]-=scalar1*major[2][7];
2072
2073
2074
/* One column left (Two in fact, but the last one is the homography) */
2075
scalar1=major[1][3];
2076
2077
major[2][3]/=scalar1;
2078
scalar1=major[1][0];major[2][0]-=scalar1*major[2][3];
2079
scalar1=major[1][1];major[2][1]-=scalar1*major[2][3];
2080
scalar1=major[1][2];major[2][2]-=scalar1*major[2][3];
2081
scalar1=major[1][4];major[2][4]-=scalar1*major[2][3];
2082
scalar1=major[1][5];major[2][5]-=scalar1*major[2][3];
2083
scalar1=major[1][6];major[2][6]-=scalar1*major[2][3];
2084
scalar1=major[1][7];major[2][7]-=scalar1*major[2][3];
2085
2086
2087
/* Homography is done. */
2088
H[0]=major[2][0];
2089
H[1]=major[2][1];
2090
H[2]=major[2][2];
2091
2092
H[3]=major[2][4];
2093
H[4]=major[2][5];
2094
H[5]=major[2][6];
2095
2096
H[6]=major[2][7];
2097
H[7]=major[2][3];
2098
H[8]=1.0;
2099
}
2100
2101
2102
/**
2103
* Returns whether refinement is possible.
2104
*
2105
* NB This is separate from whether it is *enabled*.
2106
*
2107
* @return 0 if refinement isn't possible, non-zero otherwise.
2108
*
2109
* Reads (direct): best.numInl
2110
* Reads (callees): None.
2111
* Writes (direct): None.
2112
* Writes (callees): None.
2113
*/
2114
2115
inline int RHO_HEST_REFC::canRefine(void){
2116
/**
2117
* If we only have 4 matches, GE's result is already optimal and cannot
2118
* be refined any further.
2119
*/
2120
2121
return best.numInl > (unsigned)SMPL_SIZE;
2122
}
2123
2124
2125
/**
2126
* Refines the best-so-far homography (p->best.H).
2127
*
2128
* Reads (direct): best.H, arg.src, arg.dst, best.inl, arg.N, lm.JtJ,
2129
* lm.Jte, lm.tmp1
2130
* Reads (callees): None.
2131
* Writes (direct): best.H, lm.JtJ, lm.Jte, lm.tmp1
2132
* Writes (callees): None.
2133
*/
2134
2135
inline void RHO_HEST_REFC::refine(void){
2136
int i;
2137
float S, newS; /* Sum of squared errors */
2138
float gain; /* Gain-parameter. */
2139
float L = 100.0f;/* Lambda of LevMarq */
2140
float dH[8], newH[8];
2141
2142
/**
2143
* Iteratively refine the homography.
2144
*/
2145
/* Find initial conditions */
2146
sacCalcJacobianErrors(best.H, arg.src, arg.dst, best.inl, arg.N,
2147
lm.JtJ, lm.Jte, &S);
2148
2149
/*Levenberg-Marquardt Loop.*/
2150
for(i=0;i<MAXLEVMARQITERS;i++){
2151
/**
2152
* Attempt a step given current state
2153
* - Jacobian-x-Jacobian (JtJ)
2154
* - Jacobian-x-error (Jte)
2155
* - Sum of squared errors (S)
2156
* and current parameter
2157
* - Lambda (L)
2158
* .
2159
*
2160
* This is done by solving the system of equations
2161
* Ax = b
2162
* where A (JtJ) and b (Jte) are sourced from our current state, and
2163
* the solution x becomes a step (dH) that is applied to best.H in
2164
* order to compute a candidate homography (newH).
2165
*
2166
* The system above is solved by Cholesky decomposition of a
2167
* sufficently-damped JtJ into a lower-triangular matrix (and its
2168
* transpose), whose inverse is then computed. This inverse (and its
2169
* transpose) then multiply Jte in order to find dH.
2170
*/
2171
2172
while(!sacChol8x8Damped(lm.JtJ, L, lm.tmp1)){
2173
L *= 2.0f;
2174
}
2175
sacTRInv8x8 (lm.tmp1, lm.tmp1);
2176
sacTRISolve8x8(lm.tmp1, lm.Jte, dH);
2177
sacSub8x1 (newH, best.H, dH);
2178
sacCalcJacobianErrors(newH, arg.src, arg.dst, best.inl, arg.N,
2179
NULL, NULL, &newS);
2180
gain = sacLMGain(dH, lm.Jte, S, newS, L);
2181
/*printf("Lambda: %12.6f S: %12.6f newS: %12.6f Gain: %12.6f\n",
2182
L, S, newS, gain);*/
2183
2184
/**
2185
* If the gain is positive (i.e., the new Sum of Square Errors (newS)
2186
* corresponding to newH is lower than the previous one (S) ), save
2187
* the current state and accept the new step dH.
2188
*
2189
* If the gain is below LM_GAIN_LO, damp more (increase L), even if the
2190
* gain was positive. If the gain is above LM_GAIN_HI, damp less
2191
* (decrease L). Otherwise the gain is left unchanged.
2192
*/
2193
2194
if(gain < LM_GAIN_LO){
2195
L *= 8;
2196
if(L>1000.0f/FLT_EPSILON){
2197
break;/* FIXME: Most naive termination criterion imaginable. */
2198
}
2199
}else if(gain > LM_GAIN_HI){
2200
L *= 0.5;
2201
}
2202
2203
if(gain > 0){
2204
S = newS;
2205
memcpy(best.H, newH, sizeof(newH));
2206
sacCalcJacobianErrors(best.H, arg.src, arg.dst, best.inl, arg.N,
2207
lm.JtJ, lm.Jte, &S);
2208
}
2209
}
2210
}
2211
2212
2213
/**
2214
* Compute directly the JtJ, Jte and sum-of-squared-error for a given
2215
* homography and set of inliers.
2216
*
2217
* This is possible because the product of J and its transpose as well as with
2218
* the error and the sum-of-squared-error can all be computed additively
2219
* (match-by-match), as one would intuitively expect; All matches make
2220
* contributions to the error independently of each other.
2221
*
2222
* What this allows is a constant-space implementation of Lev-Marq that can
2223
* nevertheless be vectorized if need be.
2224
*/
2225
2226
static inline void sacCalcJacobianErrors(const float* H,
2227
const float* src,
2228
const float* dst,
2229
const char* inl,
2230
unsigned N,
2231
float (* JtJ)[8],
2232
float* Jte,
2233
float* Sp){
2234
unsigned i;
2235
float S;
2236
2237
/* Zero out JtJ, Jte and S */
2238
if(JtJ){memset(JtJ, 0, 8*8*sizeof(float));}
2239
if(Jte){memset(Jte, 0, 8*1*sizeof(float));}
2240
S = 0.0f;
2241
2242
/* Additively compute JtJ and Jte */
2243
for(i=0;i<N;i++){
2244
/* Skip outliers */
2245
if(!inl[i]){
2246
continue;
2247
}
2248
2249
/**
2250
* Otherwise, compute additively the upper triangular matrix JtJ and
2251
* the Jtd vector within the following formula:
2252
*
2253
* LaTeX:
2254
* (J^{T}J + \lambda \diag( J^{T}J )) \beta = J^{T}[ y - f(\Beta) ]
2255
* Simplified ASCII:
2256
* (JtJ + L*diag(JtJ)) beta = Jt e, where e (error) is y-f(Beta).
2257
*
2258
* For this we need to calculate
2259
* 1) The 2D error (e) of the homography on the current point i
2260
* using the current parameters Beta.
2261
* 2) The derivatives (J) of the error on the current point i under
2262
* perturbations of the current parameters Beta.
2263
* Accumulate products of the error times the derivative to Jte, and
2264
* products of the derivatives to JtJ.
2265
*/
2266
2267
/* Compute Squared Error */
2268
float x = src[2*i+0];
2269
float y = src[2*i+1];
2270
float X = dst[2*i+0];
2271
float Y = dst[2*i+1];
2272
float W = (H[6]*x + H[7]*y + 1.0f);
2273
float iW = fabs(W) > FLT_EPSILON ? 1.0f/W : 0;
2274
2275
float reprojX = (H[0]*x + H[1]*y + H[2]) * iW;
2276
float reprojY = (H[3]*x + H[4]*y + H[5]) * iW;
2277
2278
float eX = reprojX - X;
2279
float eY = reprojY - Y;
2280
float e = eX*eX + eY*eY;
2281
S += e;
2282
2283
/* Compute Jacobian */
2284
if(JtJ || Jte){
2285
float dxh11 = x * iW;
2286
float dxh12 = y * iW;
2287
float dxh13 = iW;
2288
/*float dxh21 = 0.0f;*/
2289
/*float dxh22 = 0.0f;*/
2290
/*float dxh23 = 0.0f;*/
2291
float dxh31 = -reprojX*x * iW;
2292
float dxh32 = -reprojX*y * iW;
2293
2294
/*float dyh11 = 0.0f;*/
2295
/*float dyh12 = 0.0f;*/
2296
/*float dyh13 = 0.0f;*/
2297
float dyh21 = x * iW;
2298
float dyh22 = y * iW;
2299
float dyh23 = iW;
2300
float dyh31 = -reprojY*x * iW;
2301
float dyh32 = -reprojY*y * iW;
2302
2303
/* Update Jte: X Y */
2304
if(Jte){
2305
Jte[0] += eX *dxh11 ;/* +0 */
2306
Jte[1] += eX *dxh12 ;/* +0 */
2307
Jte[2] += eX *dxh13 ;/* +0 */
2308
Jte[3] += eY *dyh21;/* 0+ */
2309
Jte[4] += eY *dyh22;/* 0+ */
2310
Jte[5] += eY *dyh23;/* 0+ */
2311
Jte[6] += eX *dxh31 + eY *dyh31;/* + */
2312
Jte[7] += eX *dxh32 + eY *dyh32;/* + */
2313
}
2314
2315
/* Update JtJ: X Y */
2316
if(JtJ){
2317
JtJ[0][0] += dxh11*dxh11 ;/* +0 */
2318
2319
JtJ[1][0] += dxh11*dxh12 ;/* +0 */
2320
JtJ[1][1] += dxh12*dxh12 ;/* +0 */
2321
2322
JtJ[2][0] += dxh11*dxh13 ;/* +0 */
2323
JtJ[2][1] += dxh12*dxh13 ;/* +0 */
2324
JtJ[2][2] += dxh13*dxh13 ;/* +0 */
2325
2326
/*JtJ[3][0] += ; 0+0 */
2327
/*JtJ[3][1] += ; 0+0 */
2328
/*JtJ[3][2] += ; 0+0 */
2329
JtJ[3][3] += dyh21*dyh21;/* 0+ */
2330
2331
/*JtJ[4][0] += ; 0+0 */
2332
/*JtJ[4][1] += ; 0+0 */
2333
/*JtJ[4][2] += ; 0+0 */
2334
JtJ[4][3] += dyh21*dyh22;/* 0+ */
2335
JtJ[4][4] += dyh22*dyh22;/* 0+ */
2336
2337
/*JtJ[5][0] += ; 0+0 */
2338
/*JtJ[5][1] += ; 0+0 */
2339
/*JtJ[5][2] += ; 0+0 */
2340
JtJ[5][3] += dyh21*dyh23;/* 0+ */
2341
JtJ[5][4] += dyh22*dyh23;/* 0+ */
2342
JtJ[5][5] += dyh23*dyh23;/* 0+ */
2343
2344
JtJ[6][0] += dxh11*dxh31 ;/* +0 */
2345
JtJ[6][1] += dxh12*dxh31 ;/* +0 */
2346
JtJ[6][2] += dxh13*dxh31 ;/* +0 */
2347
JtJ[6][3] += dyh21*dyh31;/* 0+ */
2348
JtJ[6][4] += dyh22*dyh31;/* 0+ */
2349
JtJ[6][5] += dyh23*dyh31;/* 0+ */
2350
JtJ[6][6] += dxh31*dxh31 + dyh31*dyh31;/* + */
2351
2352
JtJ[7][0] += dxh11*dxh32 ;/* +0 */
2353
JtJ[7][1] += dxh12*dxh32 ;/* +0 */
2354
JtJ[7][2] += dxh13*dxh32 ;/* +0 */
2355
JtJ[7][3] += dyh21*dyh32;/* 0+ */
2356
JtJ[7][4] += dyh22*dyh32;/* 0+ */
2357
JtJ[7][5] += dyh23*dyh32;/* 0+ */
2358
JtJ[7][6] += dxh31*dxh32 + dyh31*dyh32;/* + */
2359
JtJ[7][7] += dxh32*dxh32 + dyh32*dyh32;/* + */
2360
}
2361
}
2362
}
2363
2364
if(Sp){*Sp = S;}
2365
}
2366
2367
2368
/**
2369
* Compute the Levenberg-Marquardt "gain" obtained by the given step dH.
2370
*
2371
* Drawn from http://www2.imm.dtu.dk/documents/ftp/tr99/tr05_99.pdf.
2372
*/
2373
2374
static inline float sacLMGain(const float* dH,
2375
const float* Jte,
2376
const float S,
2377
const float newS,
2378
const float lambda){
2379
float dS = S-newS;
2380
float dL = 0;
2381
int i;
2382
2383
/* Compute h^t h... */
2384
for(i=0;i<8;i++){
2385
dL += dH[i]*dH[i];
2386
}
2387
/* Compute mu * h^t h... */
2388
dL *= lambda;
2389
/* Subtract h^t F'... */
2390
for(i=0;i<8;i++){
2391
dL += dH[i]*Jte[i];/* += as opposed to -=, since dH we compute is
2392
opposite sign. */
2393
}
2394
/* Multiply by 1/2... */
2395
dL *= 0.5;
2396
2397
/* Return gain as S-newS / L0 - LH. */
2398
return fabs(dL) < FLT_EPSILON ? dS : dS / dL;
2399
}
2400
2401
2402
/**
2403
* Cholesky decomposition on 8x8 real positive-definite matrix defined by its
2404
* lower-triangular half. Outputs L, the lower triangular part of the
2405
* decomposition.
2406
*
2407
* A and L can overlap fully (in-place) or not at all, but may not partially
2408
* overlap.
2409
*
2410
* For damping, the diagonal elements are scaled by 1.0 + lambda.
2411
*
2412
* Returns zero if decomposition unsuccessful, and non-zero otherwise.
2413
*
2414
* Source: http://en.wikipedia.org/wiki/Cholesky_decomposition#
2415
* The_Cholesky.E2.80.93Banachiewicz_and_Cholesky.E2.80.93Crout_algorithms
2416
*/
2417
2418
static inline int sacChol8x8Damped(const float (*A)[8],
2419
float lambda,
2420
float (*L)[8]){
2421
const int N = 8;
2422
int i, j, k;
2423
float lambdap1 = lambda + 1.0f;
2424
float x;
2425
2426
for(i=0;i<N;i++){/* Row */
2427
/* Pre-diagonal elements */
2428
for(j=0;j<i;j++){
2429
x = A[i][j]; /* Aij */
2430
for(k=0;k<j;k++){
2431
x -= L[i][k] * L[j][k];/* - Sum_{k=0..j-1} Lik*Ljk */
2432
}
2433
L[i][j] = x / L[j][j]; /* Lij = ... / Ljj */
2434
}
2435
2436
/* Diagonal element */
2437
{j = i;
2438
x = A[j][j] * lambdap1; /* Ajj */
2439
for(k=0;k<j;k++){
2440
x -= L[j][k] * L[j][k];/* - Sum_{k=0..j-1} Ljk^2 */
2441
}
2442
if(x<0){
2443
return 0;
2444
}
2445
L[j][j] = sqrtf(x); /* Ljj = sqrt( ... ) */
2446
}
2447
}
2448
2449
return 1;
2450
}
2451
2452
2453
/**
2454
* Invert lower-triangular 8x8 matrix L into lower-triangular matrix M.
2455
*
2456
* L and M can overlap fully (in-place) or not at all, but may not partially
2457
* overlap.
2458
*
2459
* Uses formulation from
2460
* http://www.cs.berkeley.edu/~knight/knight_math221_poster.pdf
2461
* , adjusted for the fact that A^T^-1 = A^-1^T. Thus:
2462
*
2463
* U11 U12 U11^-1 -U11^-1*U12*U22^-1
2464
* ->
2465
* 0 U22 0 U22^-1
2466
*
2467
* Becomes
2468
*
2469
* L11 0 L11^-1 0
2470
* ->
2471
* L21 L22 -L22^-1*L21*L11^-1 L22^-1
2472
*
2473
* Since
2474
*
2475
* ( -L11^T^-1*L21^T*L22^T^-1 )^T = -L22^T^-1^T*L21^T^T*L11^T^-1^T
2476
* = -L22^T^T^-1*L21^T^T*L11^T^T^-1
2477
* = -L22^-1*L21*L11^-1
2478
*/
2479
2480
static inline void sacTRInv8x8(const float (*L)[8],
2481
float (*M)[8]){
2482
float s[2][2], t[2][2];
2483
float u[4][4], v[4][4];
2484
2485
/*
2486
L00 0 0 0 0 0 0 0
2487
L10 L11 0 0 0 0 0 0
2488
L20 L21 L22 0 0 0 0 0
2489
L30 L31 L32 L33 0 0 0 0
2490
L40 L41 L42 L43 L44 0 0 0
2491
L50 L51 L52 L53 L54 L55 0 0
2492
L60 L61 L62 L63 L64 L65 L66 0
2493
L70 L71 L72 L73 L74 L75 L76 L77
2494
*/
2495
2496
/* Invert 4*2 1x1 matrices; Starts recursion. */
2497
M[0][0] = 1.0f/L[0][0];
2498
M[1][1] = 1.0f/L[1][1];
2499
M[2][2] = 1.0f/L[2][2];
2500
M[3][3] = 1.0f/L[3][3];
2501
M[4][4] = 1.0f/L[4][4];
2502
M[5][5] = 1.0f/L[5][5];
2503
M[6][6] = 1.0f/L[6][6];
2504
M[7][7] = 1.0f/L[7][7];
2505
2506
/*
2507
M00 0 0 0 0 0 0 0
2508
L10 M11 0 0 0 0 0 0
2509
L20 L21 M22 0 0 0 0 0
2510
L30 L31 L32 M33 0 0 0 0
2511
L40 L41 L42 L43 M44 0 0 0
2512
L50 L51 L52 L53 L54 M55 0 0
2513
L60 L61 L62 L63 L64 L65 M66 0
2514
L70 L71 L72 L73 L74 L75 L76 M77
2515
*/
2516
2517
/* 4*2 Matrix products of 1x1 matrices */
2518
M[1][0] = -M[1][1]*L[1][0]*M[0][0];
2519
M[3][2] = -M[3][3]*L[3][2]*M[2][2];
2520
M[5][4] = -M[5][5]*L[5][4]*M[4][4];
2521
M[7][6] = -M[7][7]*L[7][6]*M[6][6];
2522
2523
/*
2524
M00 0 0 0 0 0 0 0
2525
M10 M11 0 0 0 0 0 0
2526
L20 L21 M22 0 0 0 0 0
2527
L30 L31 M32 M33 0 0 0 0
2528
L40 L41 L42 L43 M44 0 0 0
2529
L50 L51 L52 L53 M54 M55 0 0
2530
L60 L61 L62 L63 L64 L65 M66 0
2531
L70 L71 L72 L73 L74 L75 M76 M77
2532
*/
2533
2534
/* 2*2 Matrix products of 2x2 matrices */
2535
2536
/*
2537
(M22 0 ) (L20 L21) (M00 0 )
2538
- (M32 M33) x (L30 L31) x (M10 M11)
2539
*/
2540
2541
s[0][0] = M[2][2]*L[2][0];
2542
s[0][1] = M[2][2]*L[2][1];
2543
s[1][0] = M[3][2]*L[2][0]+M[3][3]*L[3][0];
2544
s[1][1] = M[3][2]*L[2][1]+M[3][3]*L[3][1];
2545
2546
t[0][0] = s[0][0]*M[0][0]+s[0][1]*M[1][0];
2547
t[0][1] = s[0][1]*M[1][1];
2548
t[1][0] = s[1][0]*M[0][0]+s[1][1]*M[1][0];
2549
t[1][1] = s[1][1]*M[1][1];
2550
2551
M[2][0] = -t[0][0];
2552
M[2][1] = -t[0][1];
2553
M[3][0] = -t[1][0];
2554
M[3][1] = -t[1][1];
2555
2556
/*
2557
(M66 0 ) (L64 L65) (M44 0 )
2558
- (L76 M77) x (L74 L75) x (M54 M55)
2559
*/
2560
2561
s[0][0] = M[6][6]*L[6][4];
2562
s[0][1] = M[6][6]*L[6][5];
2563
s[1][0] = M[7][6]*L[6][4]+M[7][7]*L[7][4];
2564
s[1][1] = M[7][6]*L[6][5]+M[7][7]*L[7][5];
2565
2566
t[0][0] = s[0][0]*M[4][4]+s[0][1]*M[5][4];
2567
t[0][1] = s[0][1]*M[5][5];
2568
t[1][0] = s[1][0]*M[4][4]+s[1][1]*M[5][4];
2569
t[1][1] = s[1][1]*M[5][5];
2570
2571
M[6][4] = -t[0][0];
2572
M[6][5] = -t[0][1];
2573
M[7][4] = -t[1][0];
2574
M[7][5] = -t[1][1];
2575
2576
/*
2577
M00 0 0 0 0 0 0 0
2578
M10 M11 0 0 0 0 0 0
2579
M20 M21 M22 0 0 0 0 0
2580
M30 M31 M32 M33 0 0 0 0
2581
L40 L41 L42 L43 M44 0 0 0
2582
L50 L51 L52 L53 M54 M55 0 0
2583
L60 L61 L62 L63 M64 M65 M66 0
2584
L70 L71 L72 L73 M74 M75 M76 M77
2585
*/
2586
2587
/* 1*2 Matrix products of 4x4 matrices */
2588
2589
/*
2590
(M44 0 0 0 ) (L40 L41 L42 L43) (M00 0 0 0 )
2591
(M54 M55 0 0 ) (L50 L51 L52 L53) (M10 M11 0 0 )
2592
(M64 M65 M66 0 ) (L60 L61 L62 L63) (M20 M21 M22 0 )
2593
- (M74 M75 M76 M77) x (L70 L71 L72 L73) x (M30 M31 M32 M33)
2594
*/
2595
2596
u[0][0] = M[4][4]*L[4][0];
2597
u[0][1] = M[4][4]*L[4][1];
2598
u[0][2] = M[4][4]*L[4][2];
2599
u[0][3] = M[4][4]*L[4][3];
2600
u[1][0] = M[5][4]*L[4][0]+M[5][5]*L[5][0];
2601
u[1][1] = M[5][4]*L[4][1]+M[5][5]*L[5][1];
2602
u[1][2] = M[5][4]*L[4][2]+M[5][5]*L[5][2];
2603
u[1][3] = M[5][4]*L[4][3]+M[5][5]*L[5][3];
2604
u[2][0] = M[6][4]*L[4][0]+M[6][5]*L[5][0]+M[6][6]*L[6][0];
2605
u[2][1] = M[6][4]*L[4][1]+M[6][5]*L[5][1]+M[6][6]*L[6][1];
2606
u[2][2] = M[6][4]*L[4][2]+M[6][5]*L[5][2]+M[6][6]*L[6][2];
2607
u[2][3] = M[6][4]*L[4][3]+M[6][5]*L[5][3]+M[6][6]*L[6][3];
2608
u[3][0] = M[7][4]*L[4][0]+M[7][5]*L[5][0]+M[7][6]*L[6][0]+M[7][7]*L[7][0];
2609
u[3][1] = M[7][4]*L[4][1]+M[7][5]*L[5][1]+M[7][6]*L[6][1]+M[7][7]*L[7][1];
2610
u[3][2] = M[7][4]*L[4][2]+M[7][5]*L[5][2]+M[7][6]*L[6][2]+M[7][7]*L[7][2];
2611
u[3][3] = M[7][4]*L[4][3]+M[7][5]*L[5][3]+M[7][6]*L[6][3]+M[7][7]*L[7][3];
2612
2613
v[0][0] = u[0][0]*M[0][0]+u[0][1]*M[1][0]+u[0][2]*M[2][0]+u[0][3]*M[3][0];
2614
v[0][1] = u[0][1]*M[1][1]+u[0][2]*M[2][1]+u[0][3]*M[3][1];
2615
v[0][2] = u[0][2]*M[2][2]+u[0][3]*M[3][2];
2616
v[0][3] = u[0][3]*M[3][3];
2617
v[1][0] = u[1][0]*M[0][0]+u[1][1]*M[1][0]+u[1][2]*M[2][0]+u[1][3]*M[3][0];
2618
v[1][1] = u[1][1]*M[1][1]+u[1][2]*M[2][1]+u[1][3]*M[3][1];
2619
v[1][2] = u[1][2]*M[2][2]+u[1][3]*M[3][2];
2620
v[1][3] = u[1][3]*M[3][3];
2621
v[2][0] = u[2][0]*M[0][0]+u[2][1]*M[1][0]+u[2][2]*M[2][0]+u[2][3]*M[3][0];
2622
v[2][1] = u[2][1]*M[1][1]+u[2][2]*M[2][1]+u[2][3]*M[3][1];
2623
v[2][2] = u[2][2]*M[2][2]+u[2][3]*M[3][2];
2624
v[2][3] = u[2][3]*M[3][3];
2625
v[3][0] = u[3][0]*M[0][0]+u[3][1]*M[1][0]+u[3][2]*M[2][0]+u[3][3]*M[3][0];
2626
v[3][1] = u[3][1]*M[1][1]+u[3][2]*M[2][1]+u[3][3]*M[3][1];
2627
v[3][2] = u[3][2]*M[2][2]+u[3][3]*M[3][2];
2628
v[3][3] = u[3][3]*M[3][3];
2629
2630
M[4][0] = -v[0][0];
2631
M[4][1] = -v[0][1];
2632
M[4][2] = -v[0][2];
2633
M[4][3] = -v[0][3];
2634
M[5][0] = -v[1][0];
2635
M[5][1] = -v[1][1];
2636
M[5][2] = -v[1][2];
2637
M[5][3] = -v[1][3];
2638
M[6][0] = -v[2][0];
2639
M[6][1] = -v[2][1];
2640
M[6][2] = -v[2][2];
2641
M[6][3] = -v[2][3];
2642
M[7][0] = -v[3][0];
2643
M[7][1] = -v[3][1];
2644
M[7][2] = -v[3][2];
2645
M[7][3] = -v[3][3];
2646
2647
/*
2648
M00 0 0 0 0 0 0 0
2649
M10 M11 0 0 0 0 0 0
2650
M20 M21 M22 0 0 0 0 0
2651
M30 M31 M32 M33 0 0 0 0
2652
M40 M41 M42 M43 M44 0 0 0
2653
M50 M51 M52 M53 M54 M55 0 0
2654
M60 M61 M62 M63 M64 M65 M66 0
2655
M70 M71 M72 M73 M74 M75 M76 M77
2656
*/
2657
}
2658
2659
2660
/**
2661
* Solves dH = inv(JtJ) Jte. The argument lower-triangular matrix is the
2662
* inverse of L as produced by the Cholesky decomposition LL^T of the matrix
2663
* JtJ; Thus the operation performed here is a left-multiplication of a vector
2664
* by two triangular matrices. The math is below:
2665
*
2666
* JtJ = LL^T
2667
* Linv = L^-1
2668
* (JtJ)^-1 = (LL^T)^-1
2669
* = (L^T^-1)(Linv)
2670
* = (Linv^T)(Linv)
2671
* dH = ((JtJ)^-1) (Jte)
2672
* = (Linv^T)(Linv) (Jte)
2673
*
2674
* where J is nx8, Jt is 8xn, JtJ is 8x8 PD, e is nx1, Jte is 8x1, L is lower
2675
* triangular 8x8 and dH is 8x1.
2676
*/
2677
2678
static inline void sacTRISolve8x8(const float (*L)[8],
2679
const float* Jte,
2680
float* dH){
2681
float t[8];
2682
2683
t[0] = L[0][0]*Jte[0];
2684
t[1] = L[1][0]*Jte[0]+L[1][1]*Jte[1];
2685
t[2] = L[2][0]*Jte[0]+L[2][1]*Jte[1]+L[2][2]*Jte[2];
2686
t[3] = L[3][0]*Jte[0]+L[3][1]*Jte[1]+L[3][2]*Jte[2]+L[3][3]*Jte[3];
2687
t[4] = L[4][0]*Jte[0]+L[4][1]*Jte[1]+L[4][2]*Jte[2]+L[4][3]*Jte[3]+L[4][4]*Jte[4];
2688
t[5] = L[5][0]*Jte[0]+L[5][1]*Jte[1]+L[5][2]*Jte[2]+L[5][3]*Jte[3]+L[5][4]*Jte[4]+L[5][5]*Jte[5];
2689
t[6] = L[6][0]*Jte[0]+L[6][1]*Jte[1]+L[6][2]*Jte[2]+L[6][3]*Jte[3]+L[6][4]*Jte[4]+L[6][5]*Jte[5]+L[6][6]*Jte[6];
2690
t[7] = L[7][0]*Jte[0]+L[7][1]*Jte[1]+L[7][2]*Jte[2]+L[7][3]*Jte[3]+L[7][4]*Jte[4]+L[7][5]*Jte[5]+L[7][6]*Jte[6]+L[7][7]*Jte[7];
2691
2692
2693
dH[0] = L[0][0]*t[0]+L[1][0]*t[1]+L[2][0]*t[2]+L[3][0]*t[3]+L[4][0]*t[4]+L[5][0]*t[5]+L[6][0]*t[6]+L[7][0]*t[7];
2694
dH[1] = L[1][1]*t[1]+L[2][1]*t[2]+L[3][1]*t[3]+L[4][1]*t[4]+L[5][1]*t[5]+L[6][1]*t[6]+L[7][1]*t[7];
2695
dH[2] = L[2][2]*t[2]+L[3][2]*t[3]+L[4][2]*t[4]+L[5][2]*t[5]+L[6][2]*t[6]+L[7][2]*t[7];
2696
dH[3] = L[3][3]*t[3]+L[4][3]*t[4]+L[5][3]*t[5]+L[6][3]*t[6]+L[7][3]*t[7];
2697
dH[4] = L[4][4]*t[4]+L[5][4]*t[5]+L[6][4]*t[6]+L[7][4]*t[7];
2698
dH[5] = L[5][5]*t[5]+L[6][5]*t[6]+L[7][5]*t[7];
2699
dH[6] = L[6][6]*t[6]+L[7][6]*t[7];
2700
dH[7] = L[7][7]*t[7];
2701
}
2702
2703
2704
/**
2705
* Subtract dH from H.
2706
*/
2707
2708
static inline void sacSub8x1(float* Hout, const float* H, const float* dH){
2709
Hout[0] = H[0] - dH[0];
2710
Hout[1] = H[1] - dH[1];
2711
Hout[2] = H[2] - dH[2];
2712
Hout[3] = H[3] - dH[3];
2713
Hout[4] = H[4] - dH[4];
2714
Hout[5] = H[5] - dH[5];
2715
Hout[6] = H[6] - dH[6];
2716
Hout[7] = H[7] - dH[7];
2717
}
2718
2719
2720
/* End namespace cv */
2721
}
2722
2723