mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-17 15:26:00 +08:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -55,6 +55,8 @@
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "opencv2/core/utility.hpp"
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include "opencv2/core.hpp"
|
||||
@@ -628,6 +630,208 @@ class CV_EXPORTS_W BinaryDescriptor : public Algorithm
|
||||
|
||||
cv::Mat_<float> tempVecLineFit; //the vector used in line fit function;
|
||||
|
||||
/** Compare doubles by relative error.
|
||||
The resulting rounding error after floating point computations
|
||||
depend on the specific operations done. The same number computed by
|
||||
different algorithms could present different rounding errors. For a
|
||||
useful comparison, an estimation of the relative rounding error
|
||||
should be considered and compared to a factor times EPS. The factor
|
||||
should be related to the accumulated rounding error in the chain of
|
||||
computation. Here, as a simplification, a fixed factor is used.
|
||||
*/
|
||||
static int double_equal( double a, double b )
|
||||
{
|
||||
double abs_diff, aa, bb, abs_max;
|
||||
/* trivial case */
|
||||
if( a == b )
|
||||
return true;
|
||||
abs_diff = fabs( a - b );
|
||||
aa = fabs( a );
|
||||
bb = fabs( b );
|
||||
abs_max = aa > bb ? aa : bb;
|
||||
|
||||
/* DBL_MIN is the smallest normalized number, thus, the smallest
|
||||
number whose relative error is bounded by DBL_EPSILON. For
|
||||
smaller numbers, the same quantization steps as for DBL_MIN
|
||||
are used. Then, for smaller numbers, a meaningful "relative"
|
||||
error should be computed by dividing the difference by DBL_MIN. */
|
||||
if( abs_max < DBL_MIN )
|
||||
abs_max = DBL_MIN;
|
||||
|
||||
/* equal if relative error <= factor x eps */
|
||||
return ( abs_diff / abs_max ) <= ( RELATIVE_ERROR_FACTOR * DBL_EPSILON );
|
||||
}
|
||||
|
||||
/** Computes the natural logarithm of the absolute value of
|
||||
the gamma function of x using the Lanczos approximation.
|
||||
See http://www.rskey.org/gamma.htm
|
||||
The formula used is
|
||||
@f[
|
||||
\Gamma(x) = \frac{ \sum_{n=0}^{N} q_n x^n }{ \Pi_{n=0}^{N} (x+n) }
|
||||
(x+5.5)^{x+0.5} e^{-(x+5.5)}
|
||||
@f]
|
||||
so
|
||||
@f[
|
||||
\log\Gamma(x) = \log\left( \sum_{n=0}^{N} q_n x^n \right)
|
||||
+ (x+0.5) \log(x+5.5) - (x+5.5) - \sum_{n=0}^{N} \log(x+n)
|
||||
@f]
|
||||
and
|
||||
q0 = 75122.6331530,
|
||||
q1 = 80916.6278952,
|
||||
q2 = 36308.2951477,
|
||||
q3 = 8687.24529705,
|
||||
q4 = 1168.92649479,
|
||||
q5 = 83.8676043424,
|
||||
q6 = 2.50662827511.
|
||||
*/
|
||||
static double log_gamma_lanczos( double x )
|
||||
{
|
||||
static double q[7] =
|
||||
{ 75122.6331530, 80916.6278952, 36308.2951477, 8687.24529705, 1168.92649479, 83.8676043424, 2.50662827511 };
|
||||
double a = ( x + 0.5 ) * log( x + 5.5 ) - ( x + 5.5 );
|
||||
double b = 0.0;
|
||||
int n;
|
||||
for ( n = 0; n < 7; n++ )
|
||||
{
|
||||
a -= log( x + (double) n );
|
||||
b += q[n] * pow( x, (double) n );
|
||||
}
|
||||
return a + log( b );
|
||||
}
|
||||
|
||||
/** Computes the natural logarithm of the absolute value of
|
||||
the gamma function of x using Windschitl method.
|
||||
See http://www.rskey.org/gamma.htm
|
||||
The formula used is
|
||||
@f[
|
||||
\Gamma(x) = \sqrt{\frac{2\pi}{x}} \left( \frac{x}{e}
|
||||
\sqrt{ x\sinh(1/x) + \frac{1}{810x^6} } \right)^x
|
||||
@f]
|
||||
so
|
||||
@f[
|
||||
\log\Gamma(x) = 0.5\log(2\pi) + (x-0.5)\log(x) - x
|
||||
+ 0.5x\log\left( x\sinh(1/x) + \frac{1}{810x^6} \right).
|
||||
@f]
|
||||
This formula is a good approximation when x > 15.
|
||||
*/
|
||||
static double log_gamma_windschitl( double x )
|
||||
{
|
||||
return 0.918938533204673 + ( x - 0.5 ) * log( x ) - x + 0.5 * x * log( x * std::sinh( 1 / x ) + 1 / ( 810.0 * pow( x, 6.0 ) ) );
|
||||
}
|
||||
|
||||
/** Computes -log10(NFA).
|
||||
NFA stands for Number of False Alarms:
|
||||
@f[
|
||||
\mathrm{NFA} = NT \cdot B(n,k,p)
|
||||
@f]
|
||||
- NT - number of tests
|
||||
- B(n,k,p) - tail of binomial distribution with parameters n,k and p:
|
||||
@f[
|
||||
B(n,k,p) = \sum_{j=k}^n
|
||||
\left(\begin{array}{c}n\\j\end{array}\right)
|
||||
p^{j} (1-p)^{n-j}
|
||||
@f]
|
||||
The value -log10(NFA) is equivalent but more intuitive than NFA:
|
||||
- -1 corresponds to 10 mean false alarms
|
||||
- 0 corresponds to 1 mean false alarm
|
||||
- 1 corresponds to 0.1 mean false alarms
|
||||
- 2 corresponds to 0.01 mean false alarms
|
||||
- ...
|
||||
Used this way, the bigger the value, better the detection,
|
||||
and a logarithmic scale is used.
|
||||
@param n,k,p binomial parameters.
|
||||
@param logNT logarithm of Number of Tests
|
||||
The computation is based in the gamma function by the following
|
||||
relation:
|
||||
@f[
|
||||
\left(\begin{array}{c}n\\k\end{array}\right)
|
||||
= \frac{ \Gamma(n+1) }{ \Gamma(k+1) \cdot \Gamma(n-k+1) }.
|
||||
@f]
|
||||
We use efficient algorithms to compute the logarithm of
|
||||
the gamma function.
|
||||
To make the computation faster, not all the sum is computed, part
|
||||
of the terms are neglected based on a bound to the error obtained
|
||||
(an error of 10% in the result is accepted).
|
||||
*/
|
||||
static double nfa( int n, int k, double p, double logNT )
|
||||
{
|
||||
double tolerance = 0.1; /* an error of 10% in the result is accepted */
|
||||
double log1term, term, bin_term, mult_term, bin_tail, err, p_term;
|
||||
int i;
|
||||
|
||||
/* check parameters */
|
||||
if( n < 0 || k < 0 || k > n || p <= 0.0 || p >= 1.0 )
|
||||
CV_Error(Error::StsBadArg, "nfa: wrong n, k or p values.\n");
|
||||
/* trivial cases */
|
||||
if( n == 0 || k == 0 )
|
||||
return -logNT;
|
||||
if( n == k )
|
||||
return -logNT - (double) n * log10( p );
|
||||
|
||||
/* probability term */
|
||||
p_term = p / ( 1.0 - p );
|
||||
|
||||
/* compute the first term of the series */
|
||||
/*
|
||||
binomial_tail(n,k,p) = sum_{i=k}^n bincoef(n,i) * p^i * (1-p)^{n-i}
|
||||
where bincoef(n,i) are the binomial coefficients.
|
||||
But
|
||||
bincoef(n,k) = gamma(n+1) / ( gamma(k+1) * gamma(n-k+1) ).
|
||||
We use this to compute the first term. Actually the log of it.
|
||||
*/
|
||||
log1term = log_gamma( (double) n + 1.0 )- log_gamma( (double ) k + 1.0 )- log_gamma( (double ) ( n - k ) + 1.0 )
|
||||
+ (double) k * log( p )
|
||||
+ (double) ( n - k ) * log( 1.0 - p );
|
||||
term = exp( log1term );
|
||||
|
||||
/* in some cases no more computations are needed */
|
||||
if( double_equal( term, 0.0 ) )
|
||||
{ /* the first term is almost zero */
|
||||
if( (double) k > (double) n * p ) /* at begin or end of the tail? */
|
||||
return -log1term / MLN10 - logNT; /* end: use just the first term */
|
||||
else
|
||||
return -logNT; /* begin: the tail is roughly 1 */
|
||||
}
|
||||
|
||||
/* compute more terms if needed */
|
||||
bin_tail = term;
|
||||
for ( i = k + 1; i <= n; i++ )
|
||||
{
|
||||
/* As
|
||||
term_i = bincoef(n,i) * p^i * (1-p)^(n-i)
|
||||
and
|
||||
bincoef(n,i)/bincoef(n,i-1) = n-i+1 / i,
|
||||
then,
|
||||
term_i / term_i-1 = (n-i+1)/i * p/(1-p)
|
||||
and
|
||||
term_i = term_i-1 * (n-i+1)/i * p/(1-p).
|
||||
p/(1-p) is computed only once and stored in 'p_term'.
|
||||
*/
|
||||
bin_term = (double) ( n - i + 1 ) / (double) i;
|
||||
mult_term = bin_term * p_term;
|
||||
term *= mult_term;
|
||||
bin_tail += term;
|
||||
if( bin_term < 1.0 )
|
||||
{
|
||||
/* When bin_term<1 then mult_term_j<mult_term_i for j>i.
|
||||
Then, the error on the binomial tail when truncated at
|
||||
the i term can be bounded by a geometric series of form
|
||||
term_i * sum mult_term_i^j. */
|
||||
err = term * ( ( 1.0 - pow( mult_term, (double) ( n - i + 1 ) ) ) / ( 1.0 - mult_term ) - 1.0 );
|
||||
/* One wants an error at most of tolerance*final_result, or:
|
||||
tolerance * abs(-log10(bin_tail)-logNT).
|
||||
Now, the error that can be accepted on bin_tail is
|
||||
given by tolerance*final_result divided by the derivative
|
||||
of -log10(x) when x=bin_tail. that is:
|
||||
tolerance * abs(-log10(bin_tail)-logNT) / (1/bin_tail)
|
||||
Finally, we truncate the tail if the error is less than:
|
||||
tolerance * abs(-log10(bin_tail)-logNT) * bin_tail */
|
||||
if( err < tolerance * fabs( -log10( bin_tail ) - logNT ) * bin_tail )
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -log10( bin_tail ) - logNT;
|
||||
}
|
||||
};
|
||||
|
||||
// Specifies a vector of lines.
|
||||
|
Reference in New Issue
Block a user