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