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 vl_free (f) ;
00364 }
00365 }
00366
00367
00380 VL_EXPORT
00381 void
00382 vl_mser_process (VlMserFilt* f, vl_mser_pix const* im)
00383 {
00384
00385 vl_uint nel = f-> nel ;
00386 vl_uint *perm = f-> perm ;
00387 vl_uint *joins = f-> joins ;
00388 int ndims = f-> ndims ;
00389 int *dims = f-> dims ;
00390 int *subs = f-> subs ;
00391 int *dsubs = f-> dsubs ;
00392 int *strides = f-> strides ;
00393 VlMserReg *r = f-> r ;
00394 VlMserExtrReg *er = f-> er ;
00395 vl_uint *mer = f-> mer ;
00396 int delta = f-> delta ;
00397
00398 int njoins = 0 ;
00399 int ner = 0 ;
00400 int nmer = 0 ;
00401 int nbig = 0 ;
00402 int nsmall = 0 ;
00403 int nbad = 0 ;
00404 int ndup = 0 ;
00405
00406 int i, j, k ;
00407
00408
00409 f-> nell = 0 ;
00410
00411
00412
00413
00414
00415 {
00416 vl_uint buckets [ VL_MSER_PIX_MAXVAL ] ;
00417
00418
00419 memset (buckets, 0, sizeof(vl_uint) * VL_MSER_PIX_MAXVAL ) ;
00420
00421
00422
00423 for(i = 0 ; i < nel ; ++i) {
00424 vl_mser_pix v = im [i] ;
00425 ++ buckets [v] ;
00426 }
00427
00428
00429 for(i = 1 ; i < VL_MSER_PIX_MAXVAL ; ++i) {
00430 buckets [i] += buckets [i-1] ;
00431 }
00432
00433
00434 for(i = nel ; i >= 1 ; ) {
00435 vl_mser_pix v = im [ --i ] ;
00436 vl_uint j = -- buckets [v] ;
00437 perm [j] = i ;
00438 }
00439 }
00440
00441
00442 for(i = 0 ; i < nel ; ++i) {
00443 r [i] .parent = VL_MSER_VOID_NODE ;
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 for(i = 0 ; i < nel ; ++i) {
00462
00463
00464 vl_uint idx = perm [i] ;
00465 vl_mser_pix val = im [idx] ;
00466 vl_uint r_idx ;
00467
00468
00469 r [idx] .parent = idx ;
00470 r [idx] .shortcut = idx ;
00471 r [idx] .area = 1 ;
00472 r [idx] .height = 1 ;
00473
00474 r_idx = idx ;
00475
00476
00477
00478 {
00479 vl_uint temp = idx ;
00480 for(k = ndims - 1 ; k >= 0 ; --k) {
00481 dsubs [k] = -1 ;
00482 subs [k] = temp / strides [k] ;
00483 temp = temp % strides [k] ;
00484 }
00485 }
00486
00487
00488 while (1) {
00489 vl_uint n_idx = 0 ;
00490 vl_bool good = 1 ;
00491
00492
00493
00494
00495
00496
00497 for(k = 0 ; k < ndims && good ; ++k) {
00498 int temp = dsubs [k] + subs [k] ;
00499 good &= (0 <= temp) && (temp < dims [k]) ;
00500 n_idx += temp * strides [k] ;
00501 }
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 if (good &&
00516 n_idx != idx &&
00517 r [n_idx] .parent != VL_MSER_VOID_NODE ) {
00518
00519 vl_mser_pix nr_val = 0 ;
00520 vl_uint nr_idx = 0 ;
00521 int hgt = r [ r_idx] .height ;
00522 int n_hgt = r [nr_idx] .height ;
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 r_idx = climb(r, idx) ;
00535 nr_idx = climb(r, n_idx) ;
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 if( r_idx != nr_idx ) {
00559
00560 nr_val = im [nr_idx] ;
00561
00562 if( nr_val == val && hgt < n_hgt ) {
00563
00564
00565 r [r_idx] .parent = nr_idx ;
00566 r [r_idx] .shortcut = nr_idx ;
00567 r [nr_idx] .area += r [r_idx] .area ;
00568 r [nr_idx] .height = VL_MAX(n_hgt, hgt+1) ;
00569
00570 joins [njoins++] = r_idx ;
00571
00572 } else {
00573
00574
00575 r [nr_idx] .parent = r_idx ;
00576 r [nr_idx] .shortcut = r_idx ;
00577 r [r_idx] .area += r [nr_idx] .area ;
00578 r [r_idx] .height = VL_MAX(hgt, n_hgt + 1) ;
00579
00580 joins [njoins++] = nr_idx ;
00581
00582
00583 if (nr_val != val) ++ ner ;
00584
00585 }
00586 }
00587 }
00588
00589
00590 k = 0 ;
00591 while(++ dsubs [k] > 1) {
00592 dsubs [k++] = -1 ;
00593 if(k == ndims) goto done_all_neighbors ;
00594 }
00595 }
00596 done_all_neighbors : ;
00597 }
00598
00599
00600 ++ ner ;
00601
00602
00603 f-> njoins = njoins ;
00604
00605 f-> stats. num_extremal = ner ;
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 if (f-> rer < ner) {
00620 if (er) vl_free (er) ;
00621 f->er = er = vl_malloc (sizeof(VlMserExtrReg) * ner) ;
00622 f->rer = ner ;
00623 } ;
00624
00625
00626 f-> nmer = ner ;
00627
00628
00629 ner = 0 ;
00630
00631
00632 for(i = 0 ; i < nel ; ++i) {
00633
00634
00635 vl_uint idx = perm [i] ;
00636
00637 vl_mser_pix val = im [idx] ;
00638 vl_uint p_idx = r [idx] .parent ;
00639 vl_mser_pix p_val = im [p_idx] ;
00640
00641
00642 vl_bool is_extr = (p_val > val) || idx == p_idx ;
00643
00644 if( is_extr ) {
00645
00646
00647 er [ner] .index = idx ;
00648 er [ner] .parent = ner ;
00649 er [ner] .value = im [idx] ;
00650 er [ner] .area = r [idx] .area ;
00651
00652
00653 r [idx] .shortcut = ner ;
00654
00655
00656 ++ ner ;
00657 } else {
00658
00659 r [idx] .shortcut = VL_MSER_VOID_NODE ;
00660 }
00661 }
00662
00663
00664
00665
00666
00667 for(i = 0 ; i < ner ; ++i) {
00668
00669 vl_uint idx = er [i] .index ;
00670
00671 do {
00672 idx = r[idx] .parent ;
00673 } while (r[idx] .shortcut == VL_MSER_VOID_NODE) ;
00674
00675 er[i] .parent = r[idx] .shortcut ;
00676 er[i] .shortcut = i ;
00677 }
00678
00679
00680
00681
00682
00683
00684
00685
00686 for(i = 0 ; i < ner ; ++i) {
00687
00688
00689 int top_val = er [i] .value + delta ;
00690 int top = er [i] .shortcut ;
00691
00692
00693 while (1) {
00694 int next = er [top] .parent ;
00695 int next_val = er [next] .value ;
00696
00697
00698
00699
00700
00701 if (next == top || next_val > top_val) break ;
00702
00703
00704 top = next ;
00705 }
00706
00707
00708 {
00709 int area = er [i ] .area ;
00710 int area_top = er [top] .area ;
00711 er [i] .variation = (float) (area_top - area) / area ;
00712 er [i] .max_stable = 1 ;
00713 }
00714
00715
00716
00717
00718
00719
00720
00721 {
00722 int parent = er [i] .parent ;
00723 int curr = er [parent] .shortcut ;
00724 er [parent] .shortcut = VL_MAX (top, curr) ;
00725 }
00726 }
00727
00728
00729
00730
00731
00732 nmer = ner ;
00733 for(i = 0 ; i < ner ; ++i) {
00734 vl_uint parent = er [i ] .parent ;
00735 vl_mser_pix val = er [i ] .value ;
00736 float var = er [i ] .variation ;
00737 vl_mser_pix p_val = er [parent] .value ;
00738 float p_var = er [parent] .variation ;
00739 vl_uint loser ;
00740
00741
00742
00743
00744
00745 if(p_val > val + 1) continue ;
00746
00747
00748 if(var < p_var) loser = parent ; else loser = i ;
00749
00750
00751 if(er [loser] .max_stable) {
00752 -- nmer ;
00753 er [loser] .max_stable = 0 ;
00754 }
00755 }
00756
00757 f-> stats. num_unstable = ner - nmer ;
00758
00759
00760
00761
00762
00763
00764 {
00765 float max_area = (float) f-> max_area * nel ;
00766 float min_area = (float) f-> min_area * nel ;
00767 float max_var = (float) f-> max_variation ;
00768 float min_div = (float) f-> min_diversity ;
00769
00770
00771 for(i = ner-1 ; i >= 0L ; --i) {
00772
00773
00774 if (! er [i] .max_stable) continue ;
00775
00776 if (er [i] .variation >= max_var ) { ++ nbad ; goto remove ; }
00777 if (er [i] .area > max_area) { ++ nbig ; goto remove ; }
00778 if (er [i] .area < min_area) { ++ nsmall ; goto remove ; }
00779
00780
00781
00782
00783 if (min_div < 1.0) {
00784 vl_uint parent = er [i] .parent ;
00785 int area, p_area ;
00786 float div ;
00787
00788
00789 if(parent != i) {
00790
00791
00792 while(! er [parent] .max_stable) {
00793 vl_uint next = er [parent] .parent ;
00794 if(next == parent) break ;
00795 parent = next ;
00796 }
00797
00798
00799
00800 area = er [i] .area ;
00801 p_area = er [parent] .area ;
00802 div = (float) (p_area - area) / (float) p_area ;
00803
00804 if (div < min_div) { ++ ndup ; goto remove ; }
00805 }
00806
00807 }
00808 continue ;
00809 remove :
00810 er [i] .max_stable = 0 ;
00811 -- nmer ;
00812 }
00813
00814 f-> stats .num_abs_unstable = nbad ;
00815 f-> stats .num_too_big = nbig ;
00816 f-> stats .num_too_small = nsmall ;
00817 f-> stats .num_duplicates = ndup ;
00818 }
00819
00820
00821
00822
00823
00824 if (f-> rmer < nmer) {
00825 if (mer) vl_free (mer) ;
00826 f->mer = mer = vl_malloc( sizeof(vl_uint) * nmer) ;
00827 f->rmer = nmer ;
00828 }
00829
00830
00831 f-> nmer = nmer ;
00832
00833 j = 0 ;
00834 for (i = 0 ; i < ner ; ++i) {
00835 if (er [i] .max_stable) mer [j++] = er [i] .index ;
00836 }
00837 }
00838
00847 VL_EXPORT
00848 void
00849 vl_mser_ell_fit (VlMserFilt* f)
00850 {
00851
00852 int nel = f-> nel ;
00853 int dof = f-> dof ;
00854 int *dims = f-> dims ;
00855 int ndims = f-> ndims ;
00856 int *subs = f-> subs ;
00857 int njoins = f-> njoins ;
00858 vl_uint *joins = f-> joins ;
00859 VlMserReg *r = f-> r ;
00860 vl_uint *mer = f-> mer ;
00861 int nmer = f-> nmer ;
00862 vl_mser_acc *acc = f-> acc ;
00863 vl_mser_acc *ell = f-> ell ;
00864
00865 int d, index, i, j ;
00866
00867
00868 if (f->nell == f->nmer) return ;
00869
00870
00871 if (f->rell < f->nmer) {
00872 if (f->ell) vl_free (f->ell) ;
00873 f->ell = vl_malloc (sizeof(float) * f->nmer * f->dof) ;
00874 f->rell = f-> nmer ;
00875 }
00876
00877 if (f->acc == 0) {
00878 f->acc = vl_malloc (sizeof(float) * f->nel) ;
00879 }
00880
00881 acc = f-> acc ;
00882 ell = f-> ell ;
00883
00884
00885
00886
00887
00888
00889 for(d = 0 ; d < f->dof ; ++d) {
00890
00891
00892 memset (subs, 0, sizeof(int) * ndims) ;
00893
00894
00895 if(d < ndims) {
00896
00897
00898 for(index = 0 ; index < nel ; ++ index) {
00899 acc [index] = subs [d] ;
00900 adv(ndims, dims, subs) ;
00901 }
00902 }
00903 else {
00904
00905
00906
00907 i = d - ndims ;
00908 j = 0 ;
00909 while(i > j) {
00910 i -= j + 1 ;
00911 j ++ ;
00912 }
00913
00914 for(index = 0 ; index < nel ; ++ index){
00915 acc [index] = subs [i] * subs [j] ;
00916 adv(ndims, dims, subs) ;
00917 }
00918 }
00919
00920
00921 for(i = 0 ; i < njoins ; ++i) {
00922 vl_uint index = joins [i] ;
00923 vl_uint parent = r [index] .parent ;
00924 acc [parent] += acc [index] ;
00925 }
00926
00927
00928 for(i = 0 ; i < nmer ; ++i) {
00929 vl_uint idx = mer [i] ;
00930 ell [d + dof*i] = acc [idx] ;
00931 }
00932
00933 }
00934
00935
00936
00937
00938
00939 for(index = 0 ; index < nmer ; ++index) {
00940 float *pt = ell + index * dof ;
00941 vl_uint idx = mer [index] ;
00942 float area = r [idx] .area ;
00943
00944 for(d = 0 ; d < dof ; ++d) {
00945
00946 pt [d] /= area ;
00947
00948 if(d >= ndims) {
00949
00950 i = d - ndims ;
00951 j = 0 ;
00952 while(i > j) {
00953 i -= j + 1 ;
00954 j ++ ;
00955 }
00956 pt [d] -= pt [i] * pt [j] ;
00957 }
00958
00959 }
00960 }
00961
00962
00963 f-> nell = nmer ;
00964 }
00965