unsigned int Sampler::inverseCumulativeSampling( const VectorXd &cdf ) { int i=0; double m=cdf.size(); double u = unifRand(); while ( i<m && cdf.coeff(i)<=u ) ++i; return i; }
VectorXd Sampler::discreteCumulativeDistribution( const VectorXd &pdf) { unsigned int m=pdf.size(); VectorXd cdf(m); cdf.setZero(m); cdf(0)=pdf(0); for (unsigned int i=1; i<m; i++) cdf.coeffRef(i)=cdf.coeff(i-1)+pdf.coeff(i); return cdf; }
MatrixXd SolveRobustMatting( const Mat& src, const Mat& trimap, const double sigma=0.1, const double gamma=0.1 ) { const Size sz( src.size() ); const Mat fg( trimap == eFG ), bg( trimap != eBG ); const Mat Known( trimap != eUnknown ), Unknown( trimap == eUnknown ) ; const vector<Point> ctf( GetMaskPoints ( erode(fg)!=fg ) ), ctb( GetMaskPoints ( dilate(bg)!=bg ) ); typedef Triplet<double> Trip; typedef deque< Trip > Trips; Trips triplets; BuildProblem<3>( triplets, src, Known ); double SumWF(0), SumWB(0) ; const int N( sz.area( ) ); MatrixXd Alpha(sz.height,sz.width); # define Push(r,c,v) if(v!=0) triplets.push_back(Trip(r,c,v)) for (int I(0), x(0); x < sz.width; ++x) for( int y(0); y < sz.height; ++y, ++I ) { double &alpha( Alpha.coeffRef(y,x) ), conf(0); if( Unknown.at<uchar>( y, x ) ){ const double sigma( 0.1 ), sigma2( sigma * sigma ); const Point p(x,y); const Vec3i ucolor( src.at<Vec3b>( p ) ) ; const Vec3d dcolor( ucolor ); const vector< Point > fg_samp ( CollectSampleSet(p,ctf) ); const SampleColorWeights_t fg_scw( GetSampleColorWeights( src, p, fg_samp ) ); const vector< Point > bg_samp( CollectSampleSet(p,ctb) ); const SampleColorWeights_t bg_scw( GetSampleColorWeights( src, p, bg_samp ) ); typedef std::pair< double, double > AE; std::vector< AE > ae; ae.reserve( fg_scw.size( ) * bg_scw.size( ) ); for( SampleColorWeights_t::const_iterator f(fg_scw.begin()); f != fg_scw.end( ); ++f ){ for( SampleColorWeights_t::const_iterator b(bg_scw.begin()); b != bg_scw.end( ); ++b ){ const Vec3i usubb( ucolor - b->first ); const Vec3i fsubb( f->first - b->first ); const double ff( fsubb.dot(fsubb) ), ffx( max(ff,1.) ), uf( usubb.dot(fsubb) ), alpha( uf/ffx ); // alpha = (usubb*fsubb')/max(fsubb*fsubb',DMin); const Vec3d difference( dcolor - alpha*Vec3d(f->first) - (1-alpha)*Vec3d(b->first) ); //difference = ucolor - (alpha*fgsampcolors(i,:) + (1-alpha)*bgsampcolors(j,:)); const double distanceratio2( difference.ddot(difference)/ffx ); //(difference*difference')/max(fsubb*fsubb', DMin); const double Exp( exp( -distanceratio2 * f->second * b->second / sigma2 ) ); const double Alpha( max(min( alpha, 1. ), 0. ) ); ae.push_back( std::make_pair( Exp, Alpha ) ); } } enum{ M=3 }; struct LT{ bool operator()( const AE& a, const AE& b ){ return b<a; } }; nth_element( ae.begin( ), ae.begin( )+M, ae.end( ), LT() ); std::accumulate( ae.begin( ), ae.begin( )+M, AE(0,0) ); const AE v( std::accumulate( ae.begin( ), ae.begin( )+M, AE(0,0) ) ); conf=v.first/M; alpha=v.second/M; } else { alpha = fg.at<uchar>(y,x)? 1:0; } const double wf ( conf*alpha + (1-conf)*(alpha>0.5?1:0) ), WF(gamma*wf), WB(gamma*(1-wf)) ; SumWF += WF; SumWB += WB; Push( I, I , gamma ); Push( I, N , -WF ); Push( N, I , -WF ); Push( I, N+1 , -WB ); Push( N+1, I , -WB ); } Push( N, N , SumWF ); Push( N+1, N+1 , SumWB ); # undef Push // const int Total(N+2); typedef std::pair< int, bool > UIF; typedef deque<UIF> UIFS; UIFS unknowns, knowns, * const uk[]={ &unknowns, &knowns }; for( int i=0; i<Total; ++i ){ const uchar t( i<N? trimap.at<uchar>( i%sz.height, i/sz.height ):0 ); const UIF uif( std::make_pair( i, ( i<N? t == eFG : i==N) ) ); uk[ ( i<N && t == eUnknown ) ? 0 : 1 ] -> push_back( uif ); } const int last_unknown( unknowns.size( ) ); VectorXi Ak( knowns.size( ) ), indmap(Total), Indeces(Total) ; transform( knowns.begin( ), knowns.end( ), Ak.data( ), Second( ) ); for( int k(0), j(0); k<2; ++k ){ const UIFS &uifs( *uk[k] ); for( UIFS::const_iterator i( uifs.begin( ) ); i != uifs.end( ); ++i, ++j ){ const UIF uif( *i ); const int index( uif.first ); Indeces.coeffRef(j) = index ; indmap.coeffRef(index) = j ; } } Trips lu, rt; for( Trips::const_iterator i( triplets.begin( ) ); i != triplets.end( ); ++i ){ const int row( indmap[i->row()] ), col( indmap[i->col()] ); const Trip t( indmap[i->row()], indmap[i->col()], i->value() ); if( row < last_unknown ){ if( col<last_unknown ){ lu.push_back( Trip( row, col,i->value( ) ) ); } else { rt.push_back( Trip( row, col-last_unknown,i->value( ) ) ); } } } typedef SparseMatrix<double> SpMat; SpMat Lu(last_unknown,last_unknown); Lu.setFromTriplets( lu.begin( ), lu.end( ) ); SpMat Rt(last_unknown,Total-last_unknown); Rt.setFromTriplets( rt.begin( ), rt.end( ) ); const VectorXd Au( SimplicialCholesky<SpMat>(Lu).solve( -Rt*Ak.cast<double>() ) ); for( int i(0); i< last_unknown; ++i ){ const int ind( Indeces.coeff(i) ); const double auki( Au.coeff( i ) ), alpha( min( 1., max(0., auki) ) ); Alpha.coeffRef( ind % sz.height, ind / sz.height ) = alpha; } return Alpha; }