@@ -443,34 +443,10 @@ fn intersection<S: Source + ?Sized>(f: &S, p: usize, q: usize) -> f64 {
443
443
mod tests {
444
444
use super :: * ;
445
445
use crate :: definitions:: Image ;
446
- use crate :: property_testing:: GrayTestImage ;
447
- use crate :: utils:: pixel_diff_summary;
448
446
use image:: { GrayImage , Luma } ;
449
- use quickcheck:: { quickcheck, Arbitrary , Gen , TestResult } ;
450
447
use std:: cmp:: max;
451
448
use std:: f64;
452
449
453
- /// Avoid generating garbage floats during certain calculations below.
454
- #[ derive( Debug , Clone ) ]
455
- struct BoundedFloat ( f64 ) ;
456
-
457
- impl Arbitrary for BoundedFloat {
458
- fn arbitrary ( g : & mut Gen ) -> Self {
459
- let mut f;
460
-
461
- loop {
462
- f = f64:: arbitrary ( g) ;
463
-
464
- if f. is_normal ( ) {
465
- f = f. clamp ( -1_000_000.0 , 1_000_000.0 ) ;
466
- break ;
467
- }
468
- }
469
-
470
- BoundedFloat ( f)
471
- }
472
- }
473
-
474
450
#[ test]
475
451
fn test_distance_transform_saturation ( ) {
476
452
// A single foreground pixel in the top-left
@@ -486,54 +462,10 @@ mod tests {
486
462
assert_pixels_eq ! ( distances, expected) ;
487
463
}
488
464
489
- impl Sink for Vec < f64 > {
490
- fn put ( & mut self , idx : usize , value : f64 ) {
491
- self [ idx] = value;
492
- }
493
- fn len ( & self ) -> usize {
494
- self . len ( )
495
- }
496
- }
497
-
498
- fn distance_transform_1d ( f : & Vec < f64 > ) -> Vec < f64 > {
499
- let mut r = vec ! [ 0.0 ; f. len( ) ] ;
500
- let mut e = LowerEnvelope :: new ( f. len ( ) ) ;
501
- distance_transform_1d_mut ( f, & mut r, & mut e) ;
502
- r
503
- }
504
-
505
- #[ test]
506
- fn test_distance_transform_1d_constant ( ) {
507
- let f = vec ! [ 0.0 , 0.0 , 0.0 ] ;
508
- let dists = distance_transform_1d ( & f) ;
509
- assert_eq ! ( dists, & [ 0.0 , 0.0 , 0.0 ] ) ;
510
- }
511
-
512
- #[ test]
513
- fn test_distance_transform_1d_descending_gradient ( ) {
514
- let f = vec ! [ 7.0 , 5.0 , 3.0 , 1.0 ] ;
515
- let dists = distance_transform_1d ( & f) ;
516
- assert_eq ! ( dists, & [ 6.0 , 4.0 , 2.0 , 1.0 ] ) ;
517
- }
518
-
519
- #[ test]
520
- fn test_distance_transform_1d_ascending_gradient ( ) {
521
- let f = vec ! [ 1.0 , 3.0 , 5.0 , 7.0 ] ;
522
- let dists = distance_transform_1d ( & f) ;
523
- assert_eq ! ( dists, & [ 1.0 , 2.0 , 4.0 , 6.0 ] ) ;
524
- }
525
-
526
- #[ test]
527
- fn test_distance_transform_1d_with_infinities ( ) {
528
- let f = vec ! [ f64 :: INFINITY , f64 :: INFINITY , 5.0 , f64 :: INFINITY ] ;
529
- let dists = distance_transform_1d ( & f) ;
530
- assert_eq ! ( dists, & [ 9.0 , 6.0 , 5.0 , 6.0 ] ) ;
531
- }
532
-
533
465
// Simple implementation of 1d distance transform which performs an
534
466
// exhaustive search. Used to valid the more complicated lower-envelope
535
467
// implementation against.
536
- fn distance_transform_1d_reference ( f : & [ f64 ] ) -> Vec < f64 > {
468
+ pub fn distance_transform_1d_reference ( f : & [ f64 ] ) -> Vec < f64 > {
537
469
let mut ret = vec ! [ 0.0 ; f. len( ) ] ;
538
470
for q in 0 ..f. len ( ) {
539
471
ret[ q] = ( 0 ..f. len ( ) )
@@ -546,20 +478,16 @@ mod tests {
546
478
ret
547
479
}
548
480
549
- #[ cfg_attr( miri, ignore = "slow" ) ]
550
- #[ test]
551
- fn test_distance_transform_1d_matches_reference_implementation ( ) {
552
- fn prop ( f : Vec < BoundedFloat > ) -> bool {
553
- let v: Vec < f64 > = f. into_iter ( ) . map ( |n| n. 0 ) . collect ( ) ;
554
- let expected = distance_transform_1d_reference ( & v) ;
555
- let actual = distance_transform_1d ( & v) ;
556
- expected == actual
557
- }
558
-
559
- quickcheck ( prop as fn ( Vec < BoundedFloat > ) -> bool ) ;
481
+ pub fn distance_transform_1d ( f : & Vec < f64 > ) -> Vec < f64 > {
482
+ let mut r = vec ! [ 0.0 ; f. len( ) ] ;
483
+ let mut e = LowerEnvelope :: new ( f. len ( ) ) ;
484
+ distance_transform_1d_mut ( f, & mut r, & mut e) ;
485
+ r
560
486
}
561
487
562
- fn euclidean_squared_distance_transform_reference ( image : & Image < Luma < u8 > > ) -> Image < Luma < f64 > > {
488
+ pub fn euclidean_squared_distance_transform_reference (
489
+ image : & Image < Luma < u8 > > ,
490
+ ) -> Image < Luma < f64 > > {
563
491
let ( width, height) = image. dimensions ( ) ;
564
492
565
493
let mut dists = Image :: new ( width, height) ;
@@ -586,18 +514,41 @@ mod tests {
586
514
dists
587
515
}
588
516
589
- #[ cfg_attr( miri, ignore = "slow" ) ]
590
- #[ test]
591
- fn test_euclidean_squared_distance_transform_matches_reference_implementation ( ) {
592
- fn prop ( image : GrayTestImage ) -> TestResult {
593
- let expected = euclidean_squared_distance_transform_reference ( & image. 0 ) ;
594
- let actual = euclidean_squared_distance_transform ( & image. 0 ) ;
595
- match pixel_diff_summary ( & actual, & expected) {
596
- None => TestResult :: passed ( ) ,
597
- Some ( err) => TestResult :: error ( err) ,
598
- }
517
+ impl Sink for Vec < f64 > {
518
+ fn put ( & mut self , idx : usize , value : f64 ) {
519
+ self [ idx] = value;
599
520
}
600
- quickcheck ( prop as fn ( GrayTestImage ) -> TestResult ) ;
521
+ fn len ( & self ) -> usize {
522
+ self . len ( )
523
+ }
524
+ }
525
+
526
+ #[ test]
527
+ fn test_distance_transform_1d_constant ( ) {
528
+ let f = vec ! [ 0.0 , 0.0 , 0.0 ] ;
529
+ let dists = distance_transform_1d ( & f) ;
530
+ assert_eq ! ( dists, & [ 0.0 , 0.0 , 0.0 ] ) ;
531
+ }
532
+
533
+ #[ test]
534
+ fn test_distance_transform_1d_descending_gradient ( ) {
535
+ let f = vec ! [ 7.0 , 5.0 , 3.0 , 1.0 ] ;
536
+ let dists = distance_transform_1d ( & f) ;
537
+ assert_eq ! ( dists, & [ 6.0 , 4.0 , 2.0 , 1.0 ] ) ;
538
+ }
539
+
540
+ #[ test]
541
+ fn test_distance_transform_1d_ascending_gradient ( ) {
542
+ let f = vec ! [ 1.0 , 3.0 , 5.0 , 7.0 ] ;
543
+ let dists = distance_transform_1d ( & f) ;
544
+ assert_eq ! ( dists, & [ 1.0 , 2.0 , 4.0 , 6.0 ] ) ;
545
+ }
546
+
547
+ #[ test]
548
+ fn test_distance_transform_1d_with_infinities ( ) {
549
+ let f = vec ! [ f64 :: INFINITY , f64 :: INFINITY , 5.0 , f64 :: INFINITY ] ;
550
+ let dists = distance_transform_1d ( & f) ;
551
+ assert_eq ! ( dists, & [ 9.0 , 6.0 , 5.0 , 6.0 ] ) ;
601
552
}
602
553
603
554
#[ test]
@@ -623,6 +574,34 @@ mod tests {
623
574
}
624
575
}
625
576
577
+ #[ cfg( not( miri) ) ]
578
+ #[ cfg( test) ]
579
+ mod proptests {
580
+ use super :: tests:: euclidean_squared_distance_transform_reference;
581
+ use super :: tests:: { distance_transform_1d, distance_transform_1d_reference} ;
582
+ use super :: * ;
583
+ use crate :: proptest_utils:: arbitrary_image;
584
+ use proptest:: prelude:: * ;
585
+
586
+ proptest ! {
587
+ #[ test]
588
+ fn test_distance_transform_1d_matches_reference_implementation( f in proptest:: collection:: vec( -10_000_000.0 ..10_000_000.0 , 0 ..50 ) ) {
589
+ let actual = distance_transform_1d( & f) ;
590
+ let expected = distance_transform_1d_reference( & f) ;
591
+
592
+ assert_eq!( actual, expected) ;
593
+ }
594
+
595
+ #[ test]
596
+ fn test_euclidean_squared_distance_transform_matches_reference_implementation( image in arbitrary_image:: <Luma <u8 >>( 0 ..10 , 0 ..10 ) ) {
597
+ let expected = euclidean_squared_distance_transform_reference( & image) ;
598
+ let actual = euclidean_squared_distance_transform( & image) ;
599
+
600
+ assert_eq!( actual, expected)
601
+ }
602
+ }
603
+ }
604
+
626
605
#[ cfg( not( miri) ) ]
627
606
#[ cfg( test) ]
628
607
mod benches {
0 commit comments