00001
00007
00008
00009
00010
00011
00012
00013
00184 #include "mser.h"
00185
00186 #include<stdlib.h>
00187 #include<string.h>
00188 #include<assert.h>
00189
00201 VL_INLINE void
00202 adv(int ndims, int const *dims, int *subs)
00203 {
00204 int d = 0 ;
00205 while(d < ndims) {
00206 if( ++subs[d] < dims[d] ) return ;
00207 subs[d++] = 0 ;
00208 }
00209 }
00210
00226 VL_INLINE vl_uint
00227 climb (VlMserReg* r, vl_uint idx)
00228 {
00229
00230 vl_uint prev_idx = idx ;
00231 vl_uint next_idx ;
00232 vl_uint root_idx ;
00233
00234
00235 while (1) {
00236
00237
00238 next_idx = r [idx] .shortcut ;
00239
00240
00241 r [idx] .shortcut = prev_idx ;
00242
00243
00244 if( next_idx == idx ) break ;
00245
00246
00247 prev_idx = idx ;
00248 idx = next_idx ;
00249 }
00250
00251 root_idx = idx ;
00252
00253
00254 while (1) {
00255
00256
00257 prev_idx = r [idx] .shortcut ;
00258
00259
00260 r [idx] .shortcut = root_idx ;
00261
00262
00263 if( prev_idx == idx ) break ;
00264
00265
00266 idx = prev_idx ;
00267 }
00268
00269 return root_idx ;
00270 }
00271
00282 VL_EXPORT
00283 VlMserFilt*
00284 vl_mser_new (int ndims, int const* dims)
00285 {
00286 VlMserFilt* f ;
00287 int *strides, k ;
00288
00289 f = vl_calloc (sizeof(VlMserFilt), 1) ;
00290
00291 f-> ndims = ndims ;
00292 f-> dims = vl_malloc (sizeof(int) * ndims) ;
00293 f-> subs = vl_malloc (sizeof(int) * ndims) ;
00294 f-> dsubs = vl_malloc (sizeof(int) * ndims) ;
00295 f-> strides = vl_malloc (sizeof(int) * ndims) ;
00296
00297
00298 strides = f-> strides ;
00299
00300
00301 for(k = 0 ; k < ndims ; ++k) {
00302 f-> dims [k] = dims [k] ;
00303 }
00304
00305
00306 strides [0] = 1 ;
00307 for(k = 1 ; k < ndims ; ++k) {
00308 strides [k] = strides [k-1] * dims [k-1] ;
00309 }
00310
00311
00312 f-> nel = strides [ndims-1] * dims [ndims-1] ;
00313
00314
00315 f-> dof = ndims * (ndims + 1) / 2 + ndims ;
00316
00317
00318 f-> perm = vl_malloc (sizeof(vl_uint) * f-> nel) ;
00319 f-> joins = vl_malloc (sizeof(vl_uint) * f-> nel) ;
00320 f-> r = vl_malloc (sizeof(VlMserReg) * f-> nel) ;
00321
00322 f-> er = 0 ;
00323 f-> rer = 0 ;
00324 f-> mer = 0 ;
00325 f-> rmer = 0 ;
00326 f-> ell = 0 ;
00327 f-> rell = 0 ;
00328
00329
00330 f-> delta = 5 ;
00331 f-> max_area = 0.75 ;
00332 f-> min_area = 3.0 / f-> nel ;
00333 f-> max_variation = 0.25 ;
00334 f-> min_diversity = 0.2 ;
00335
00336 return f ;
00337 }
00338
00346 VL_EXPORT
00347 void
00348 vl_mser_delete (VlMserFilt* f)
00349 {
00350 if(f) {
00351 if(f-> acc ) vl_free( f-> acc ) ;
00352 if(f-> ell ) vl_free( f-> ell ) ;
00353
00354 if(f-> er ) vl_free( f-> er ) ;
00355 if(f-> r ) vl_free( f-> r ) ;
00356 if(f-> joins ) vl_free( f-> joins ) ;
00357 if(f-> perm ) vl_free( f-> perm ) ;
00358
00359 if(f-> strides) vl_free( f-> strides) ;
00360 if(f-> dsubs ) vl_free( f-> dsubs ) ;
00361 if(f-> subs ) vl_free( f-> subs ) ;
00362 if(f-> dims ) vl_free( f-> dims ) ;
00363
00364 if(f-> mer ) vl_free( f-> mer ) ;
00365 vl_free (f) ;
00366 }
00367 }
00368
00369
00382 VL_EXPORT
00383 void
00384 vl_mser_process (VlMserFilt* f, vl_mser_pix const* im)
00385 {
00386
00387 vl_uint nel = f-> nel ;
00388 vl_uint *perm = f-> perm ;
00389 vl_uint *joins = f-> joins ;
00390 int ndims = f-> ndims ;
00391 int *dims = f-> dims ;
00392 int *subs = f-> subs ;
00393 int *dsubs = f-> dsubs ;
00394 int *strides = f-> strides ;
00395 VlMserReg *r = f-> r ;
00396 VlMserExtrReg *er = f-> er ;
00397 vl_uint *mer = f-> mer ;
00398 int delta = f-> delta ;
00399
00400 int njoins = 0 ;
00401 int ner = 0 ;
00402 int nmer = 0 ;
00403 int nbig = 0 ;
00404 int nsmall = 0 ;
00405 int nbad = 0 ;
00406 int ndup = 0 ;
00407
00408 int i, j, k ;
00409
00410
00411 f-> nell = 0 ;
00412
00413
00414
00415
00416
00417 {
00418 vl_uint buckets [ VL_MSER_PIX_MAXVAL ] ;
00419
00420
00421 memset (buckets, 0, sizeof(vl_uint) * VL_MSER_PIX_MAXVAL ) ;
00422
00423
00424
00425 for(i = 0 ; i < nel ; ++i) {
00426 vl_mser_pix v = im [i] ;
00427 ++ buckets [v] ;
00428 }
00429
00430
00431 for(i = 1 ; i < VL_MSER_PIX_MAXVAL ; ++i) {
00432 buckets [i] += buckets [i-1] ;
00433 }
00434
00435
00436 for(i = nel ; i >= 1 ; ) {
00437 vl_mser_pix v = im [ --i ] ;
00438 vl_uint j = -- buckets [v] ;
00439 perm [j] = i ;
00440 }
00441 }
00442
00443
00444 for(i = 0 ; i < nel ; ++i) {
00445 r [i] .parent = VL_MSER_VOID_NODE ;
00446 }
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 for(i = 0 ; i < nel ; ++i) {
00464
00465
00466 vl_uint idx = perm [i] ;
00467 vl_mser_pix val = im [idx] ;
00468 vl_uint r_idx ;
00469
00470
00471 r [idx] .parent = idx ;
00472 r [idx] .shortcut = idx ;
00473 r [idx] .area = 1 ;
00474 r [idx] .height = 1 ;
00475
00476 r_idx = idx ;
00477
00478
00479
00480 {
00481 vl_uint temp = idx ;
00482 for(k = ndims - 1 ; k >= 0 ; --k) {
00483 dsubs [k] = -1 ;
00484 subs [k] = temp / strides [k] ;
00485 temp = temp % strides [k] ;
00486 }
00487 }
00488
00489
00490 while (1) {
00491 vl_uint n_idx = 0 ;
00492 vl_bool good = 1 ;
00493
00494
00495
00496
00497
00498
00499 for(k = 0 ; k < ndims && good ; ++k) {
00500 int temp = dsubs [k] + subs [k] ;
00501 good &= (0 <= temp) && (temp < dims [k]) ;
00502 n_idx += temp * strides [k] ;
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 if (good &&
00518 n_idx != idx &&
00519 r [n_idx] .parent != VL_MSER_VOID_NODE ) {
00520
00521 vl_mser_pix nr_val = 0 ;
00522 vl_uint nr_idx = 0 ;
00523 int hgt = r [ r_idx] .height ;
00524 int n_hgt = r [nr_idx] .height ;
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 r_idx = climb(r, idx) ;
00537 nr_idx = climb(r, n_idx) ;
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 if( r_idx != nr_idx ) {
00561
00562 nr_val = im [nr_idx] ;
00563
00564 if( nr_val == val && hgt < n_hgt ) {
00565
00566
00567 r [r_idx] .parent = nr_idx ;
00568 r [r_idx] .shortcut = nr_idx ;
00569 r [nr_idx] .area += r [r_idx] .area ;
00570 r [nr_idx] .height = VL_MAX(n_hgt, hgt+1) ;
00571
00572 joins [njoins++] = r_idx ;
00573
00574 } else {
00575
00576
00577 r [nr_idx] .parent = r_idx ;
00578 r [nr_idx] .shortcut = r_idx ;
00579 r [r_idx] .area += r [nr_idx] .area ;
00580 r [r_idx] .height = VL_MAX(hgt, n_hgt + 1) ;
00581
00582 joins [njoins++] = nr_idx ;
00583
00584
00585 if (nr_val != val) ++ ner ;
00586
00587 }
00588 }
00589 }
00590
00591
00592 k = 0 ;
00593 while(++ dsubs [k] > 1) {
00594 dsubs [k++] = -1 ;
00595 if(k == ndims) goto done_all_neighbors ;
00596 }
00597 }
00598 done_all_neighbors : ;
00599 }
00600
00601
00602 ++ ner ;
00603
00604
00605 f-> njoins = njoins ;
00606
00607 f-> stats. num_extremal = ner ;
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 if (f-> rer < ner) {
00622 if (er) vl_free (er) ;
00623 f->er = er = vl_malloc (sizeof(VlMserExtrReg) * ner) ;
00624 f->rer = ner ;
00625 } ;
00626
00627
00628 f-> nmer = ner ;
00629
00630
00631 ner = 0 ;
00632
00633
00634 for(i = 0 ; i < nel ; ++i) {
00635
00636
00637 vl_uint idx = perm [i] ;
00638
00639 vl_mser_pix val = im [idx] ;
00640 vl_uint p_idx = r [idx] .parent ;
00641 vl_mser_pix p_val = im [p_idx] ;
00642
00643
00644 vl_bool is_extr = (p_val > val) || idx == p_idx ;
00645
00646 if( is_extr ) {
00647
00648
00649 er [ner] .index = idx ;
00650 er [ner] .parent = ner ;
00651 er [ner] .value = im [idx] ;
00652 er [ner] .area = r [idx] .area ;
00653
00654
00655 r [idx] .shortcut = ner ;
00656
00657
00658 ++ ner ;
00659 } else {
00660
00661 r [idx] .shortcut = VL_MSER_VOID_NODE ;
00662 }
00663 }
00664
00665
00666
00667
00668
00669 for(i = 0 ; i < ner ; ++i) {
00670
00671 vl_uint idx = er [i] .index ;
00672
00673 do {
00674 idx = r[idx] .parent ;
00675 } while (r[idx] .shortcut == VL_MSER_VOID_NODE) ;
00676
00677 er[i] .parent = r[idx] .shortcut ;
00678 er[i] .shortcut = i ;
00679 }
00680
00681
00682
00683
00684
00685
00686
00687
00688 for(i = 0 ; i < ner ; ++i) {
00689
00690
00691 int top_val = er [i] .value + delta ;
00692 int top = er [i] .shortcut ;
00693
00694
00695 while (1) {
00696 int next = er [top] .parent ;
00697 int next_val = er [next] .value ;
00698
00699
00700
00701
00702
00703 if (next == top || next_val > top_val) break ;
00704
00705
00706 top = next ;
00707 }
00708
00709
00710 {
00711 int area = er [i ] .area ;
00712 int area_top = er [top] .area ;
00713 er [i] .variation = (float) (area_top - area) / area ;
00714 er [i] .max_stable = 1 ;
00715 }
00716
00717
00718
00719
00720
00721
00722
00723 {
00724 int parent = er [i] .parent ;
00725 int curr = er [parent] .shortcut ;
00726 er [parent] .shortcut = VL_MAX (top, curr) ;
00727 }
00728 }
00729
00730
00731
00732
00733
00734 nmer = ner ;
00735 for(i = 0 ; i < ner ; ++i) {
00736 vl_uint parent = er [i ] .parent ;
00737 vl_mser_pix val = er [i ] .value ;
00738 float var = er [i ] .variation ;
00739 vl_mser_pix p_val = er [parent] .value ;
00740 float p_var = er [parent] .variation ;
00741 vl_uint loser ;
00742
00743
00744
00745
00746
00747 if(p_val > val + 1) continue ;
00748
00749
00750 if(var < p_var) loser = parent ; else loser = i ;
00751
00752
00753 if(er [loser] .max_stable) {
00754 -- nmer ;
00755 er [loser] .max_stable = 0 ;
00756 }
00757 }
00758
00759 f-> stats. num_unstable = ner - nmer ;
00760
00761
00762
00763
00764
00765
00766 {
00767 float max_area = (float) f-> max_area * nel ;
00768 float min_area = (float) f-> min_area * nel ;
00769 float max_var = (float) f-> max_variation ;
00770 float min_div = (float) f-> min_diversity ;
00771
00772
00773 for(i = ner-1 ; i >= 0L ; --i) {
00774
00775
00776 if (! er [i] .max_stable) continue ;
00777
00778 if (er [i] .variation >= max_var ) { ++ nbad ; goto remove ; }
00779 if (er [i] .area > max_area) { ++ nbig ; goto remove ; }
00780 if (er [i] .area < min_area) { ++ nsmall ; goto remove ; }
00781
00782
00783
00784
00785 if (min_div < 1.0) {
00786 vl_uint parent = er [i] .parent ;
00787 int area, p_area ;
00788 float div ;
00789
00790
00791 if(parent != i) {
00792
00793
00794 while(! er [parent] .max_stable) {
00795 vl_uint next = er [parent] .parent ;
00796 if(next == parent) break ;
00797 parent = next ;
00798 }
00799
00800
00801
00802 area = er [i] .area ;
00803 p_area = er [parent] .area ;
00804 div = (float) (p_area - area) / (float) p_area ;
00805
00806 if (div < min_div) { ++ ndup ; goto remove ; }
00807 }
00808
00809 }
00810 continue ;
00811 remove :
00812 er [i] .max_stable = 0 ;
00813 -- nmer ;
00814 }
00815
00816 f-> stats .num_abs_unstable = nbad ;
00817 f-> stats .num_too_big = nbig ;
00818 f-> stats .num_too_small = nsmall ;
00819 f-> stats .num_duplicates = ndup ;
00820 }
00821
00822
00823
00824
00825
00826 if (f-> rmer < nmer) {
00827 if (mer) vl_free (mer) ;
00828 f->mer = mer = vl_malloc( sizeof(vl_uint) * nmer) ;
00829 f->rmer = nmer ;
00830 }
00831
00832
00833 f-> nmer = nmer ;
00834
00835 j = 0 ;
00836 for (i = 0 ; i < ner ; ++i) {
00837 if (er [i] .max_stable) mer [j++] = er [i] .index ;
00838 }
00839 }
00840
00849 VL_EXPORT
00850 void
00851 vl_mser_ell_fit (VlMserFilt* f)
00852 {
00853
00854 int nel = f-> nel ;
00855 int dof = f-> dof ;
00856 int *dims = f-> dims ;
00857 int ndims = f-> ndims ;
00858 int *subs = f-> subs ;
00859 int njoins = f-> njoins ;
00860 vl_uint *joins = f-> joins ;
00861 VlMserReg *r = f-> r ;
00862 vl_uint *mer = f-> mer ;
00863 int nmer = f-> nmer ;
00864 vl_mser_acc *acc = f-> acc ;
00865 vl_mser_acc *ell = f-> ell ;
00866
00867 int d, index, i, j ;
00868
00869
00870 if (f->nell == f->nmer) return ;
00871
00872
00873 if (f->rell < f->nmer) {
00874 if (f->ell) vl_free (f->ell) ;
00875 f->ell = vl_malloc (sizeof(float) * f->nmer * f->dof) ;
00876 f->rell = f-> nmer ;
00877 }
00878
00879 if (f->acc == 0) {
00880 f->acc = vl_malloc (sizeof(float) * f->nel) ;
00881 }
00882
00883 acc = f-> acc ;
00884 ell = f-> ell ;
00885
00886
00887
00888
00889
00890
00891 for(d = 0 ; d < f->dof ; ++d) {
00892
00893
00894 memset (subs, 0, sizeof(int) * ndims) ;
00895
00896
00897 if(d < ndims) {
00898
00899
00900 for(index = 0 ; index < nel ; ++ index) {
00901 acc [index] = subs [d] ;
00902 adv(ndims, dims, subs) ;
00903 }
00904 }
00905 else {
00906
00907
00908
00909 i = d - ndims ;
00910 j = 0 ;
00911 while(i > j) {
00912 i -= j + 1 ;
00913 j ++ ;
00914 }
00915
00916 for(index = 0 ; index < nel ; ++ index){
00917 acc [index] = subs [i] * subs [j] ;
00918 adv(ndims, dims, subs) ;
00919 }
00920 }
00921
00922
00923 for(i = 0 ; i < njoins ; ++i) {
00924 vl_uint index = joins [i] ;
00925 vl_uint parent = r [index] .parent ;
00926 acc [parent] += acc [index] ;
00927 }
00928
00929
00930 for(i = 0 ; i < nmer ; ++i) {
00931 vl_uint idx = mer [i] ;
00932 ell [d + dof*i] = acc [idx] ;
00933 }
00934
00935 }
00936
00937
00938
00939
00940
00941 for(index = 0 ; index < nmer ; ++index) {
00942 float *pt = ell + index * dof ;
00943 vl_uint idx = mer [index] ;
00944 float area = r [idx] .area ;
00945
00946 for(d = 0 ; d < dof ; ++d) {
00947
00948 pt [d] /= area ;
00949
00950 if(d >= ndims) {
00951
00952 i = d - ndims ;
00953 j = 0 ;
00954 while(i > j) {
00955 i -= j + 1 ;
00956 j ++ ;
00957 }
00958 pt [d] -= pt [i] * pt [j] ;
00959 }
00960
00961 }
00962 }
00963
00964
00965 f-> nell = nmer ;
00966 }
00967