@@ -12,6 +12,48 @@ using LocalFilters:
12
12
top_hat!, bottom_hat!,
13
13
Returns, reverse, reverse!
14
14
15
+ zerofill! (A:: AbstractArray ) = fill! (A, zero (eltype (A)))
16
+
17
+ function unsafe_erode_filter! (dst:: AbstractArray{<:Any,N} ,
18
+ A:: AbstractArray{<:Any,N} ,
19
+ ord:: FilterOrdering ,
20
+ B:: AbstractArray{<:Any,N} ,
21
+ i, J) where {N}
22
+ v = typemax (eltype (B) <: Bool ? eltype (A) : promote_type (eltype (A), eltype (B)))
23
+ @inbounds begin
24
+ if eltype (B) <: Bool
25
+ @simd for j in J
26
+ v = ifelse (B[ord (i,j)], min (v, A[j]), v)
27
+ end
28
+ else
29
+ @simd for j in J
30
+ v = min (v, A[j] - B[ord (i,j)])
31
+ end
32
+ end
33
+ dst[i] = v
34
+ end
35
+ end
36
+
37
+ function unsafe_dilate_filter! (dst:: AbstractArray{<:Any,N} ,
38
+ A:: AbstractArray{<:Any,N} ,
39
+ ord:: FilterOrdering ,
40
+ B:: AbstractArray{<:Any,N} ,
41
+ i, J) where {N}
42
+ v = typemin (eltype (B) <: Bool ? eltype (A) : promote_type (eltype (A), eltype (B)))
43
+ @inbounds begin
44
+ if eltype (B) <: Bool
45
+ @simd for j in J
46
+ v = ifelse (B[ord (i,j)], max (v, A[j]), v)
47
+ end
48
+ else
49
+ @simd for j in J
50
+ v = max (v, A[j] + B[ord (i,j)])
51
+ end
52
+ end
53
+ dst[i] = v
54
+ end
55
+ end
56
+
15
57
#=
16
58
# Selector for reference methods.
17
59
const REF = Val(:Base)
@@ -589,14 +631,17 @@ f2(x) = x > 0.5
589
631
wrk = similar (A); # workspace
590
632
B2 = similar (A); # for in-place operation
591
633
C = copy (A); # to check that the source is left unchanged
592
- @testset " $name " for (name, func, func!) in ((" Erosion" , erode, erode!),
593
- (" Dilation" , dilate, dilate!))
634
+ @testset " $name " for (name, func, func!, filter! ) in ((" Erosion" , erode, erode!, unsafe_erode_filter !),
635
+ (" Dilation" , dilate, dilate!, unsafe_dilate_filter !))
594
636
# ... with a simple rectangular structuring element
595
637
B1 = @inferred func (A, R; slow= true );
596
638
@test C == A # check that A is left unchanged
597
639
@test B2 === @inferred func! (B2, A, R; slow= true )
598
640
@test C == A # check that A is left unchanged
599
641
@test B2 == B1 # check if in-place and out-of-place yield the same result
642
+ @test B2 === @inferred localfilter! (zerofill! (B2), A, R, filter!)
643
+ @test C == A # check that A is left unchanged
644
+ @test B2 == B1 # check result
600
645
@test B1 == @inferred func (A, R; slow= false );
601
646
@test C == A # check that A is left unchanged
602
647
@test B2 === @inferred func! (B2, A, R; slow= false )
@@ -611,20 +656,29 @@ f2(x) = x > 0.5
611
656
@test B2 === @inferred func! (B2, A, F)
612
657
@test C == A # check that A is left unchanged
613
658
@test B2 == B1 # check if in-place and out-of-place yield the same result
659
+ @test B2 === @inferred localfilter! (zerofill! (B2), A, F, filter!)
660
+ @test C == A # check that A is left unchanged
661
+ @test B2 == B1 # check result
614
662
end
615
663
# ... with a shaped structuring element
616
664
B1 = @inferred func (A, S);
617
665
@test C == A # check that A is left unchanged
618
666
@test B2 === @inferred func! (B2, A, S)
619
667
@test C == A # check that A is left unchanged
620
668
@test B2 == B1 # check if in-place and out-of-place yield the same result
669
+ @test B2 === @inferred localfilter! (zerofill! (B2), A, S, filter!)
670
+ @test C == A # check that A is left unchanged
671
+ @test B2 == B1 # check result
621
672
if T <: AbstractFloat
622
673
F = @inferred strel (T, S) # flat structuring element like S
623
674
@test B1 == @inferred func (A, F)
624
675
@test C == A # check that A is left unchanged
625
676
@test B2 === @inferred func! (B2, A, F)
626
677
@test C == A # check that A is left unchanged
627
678
@test B2 == B1 # check if in-place and out-of-place yield the same result
679
+ @test B2 === @inferred localfilter! (zerofill! (B2), A, F, filter!)
680
+ @test C == A # check that A is left unchanged
681
+ @test B2 == B1 # check result
628
682
end
629
683
end
630
684
@testset " Local min. and max." begin
0 commit comments