Skip to content

Commit 7d36e0d

Browse files
annimesh2809mronian
authored andcommitted
Patching ImageFeatures.jl (#25)
Updates ImageFeatures.jl to conform to the new Images. Includes the following changes (with many minor ones also) - - Removed all warnings, some failing test cases - Added grade_matches function - Minor change in tests of orb.jl - Fixed lbp.jl and added test cases for it
1 parent d11f4a0 commit 7d36e0d

File tree

15 files changed

+121
-58
lines changed

15 files changed

+121
-58
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ script:
1414
- julia -e 'Pkg.add("Images")' # Needed for Docs
1515
- julia -e 'Pkg.clone("https://github.com/JuliaImages/ImageDraw.jl")' # Needed for Docs
1616
- julia -e 'Pkg.clone(pwd()); Pkg.build("ImageFeatures")'
17-
- julia -e 'Pkg.test("ImageFeatures", coverage=true)'
17+
- julia -e 'Pkg.test("ImageFeatures",coverage=true)'
1818
after_success:
1919
- if [ $TRAVIS_OS_NAME = "linux" ]; then
2020
julia -e 'cd(Pkg.dir("ImageFeatures")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())';

docs/src/function_reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ random_uniform
2828
random_coarse
2929
gaussian
3030
gaussian_local
31-
centered
31+
center_sample
3232
```
3333

3434
## Feature Extraction

docs/src/tutorials/brief.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ In ImageFeatures.jl we have five methods to determine the vectors `X` and `Y` :
88
- [`gaussian`](@ref) : `X` and `Y` are randomly sampled using a Gaussian distribution, meaning that locations that are closer to the center of the patch are preferred
99
- [`gaussian_local`](@ref) : `X` and `Y` are randomly sampled using a Gaussian distribution where first `X` is sampled with a standard deviation of `0.04*S^2` and then the `Yi’s` are sampled using a Gaussian distribution – Each `Yi` is sampled with mean `Xi` and standard deviation of `0.01 * S^2`
1010
- [`random_coarse`](@ref) : `X` and `Y` are randomly sampled from discrete location of a coarse polar grid
11-
- [`centered`](@ref) : For each `i`, `Xi` is `(0, 0)` and `Yi` takes all possible values on a coarse polar grid
11+
- [`center_sample`](@ref) : For each `i`, `Xi` is `(0, 0)` and `Yi` takes all possible values on a coarse polar grid
1212

1313
As with all the binary descriptors, BRIEF’s distance measure is the number of different bits between two binary strings which can also be computed as the sum of the XOR operation between the strings.
1414

src/ImageFeatures.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export
2020
create_descriptor,
2121
hamming_distance,
2222
match_keypoints,
23+
grade_matches,
2324

2425
#Local Binary Patterns
2526
lbp,
@@ -56,5 +57,5 @@ export
5657
random_coarse,
5758
gaussian,
5859
gaussian_local,
59-
centered
60+
center_sample
6061
end

src/brief.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,12 @@ end
127127

128128
"""
129129
```
130-
sample_one, sample_two = centered(size, window, seed)
130+
sample_one, sample_two = center_sample(size, window, seed)
131131
```
132132
133133
Builds sampling pairs `(Xi, Yi)` where `Xi` is `(0, 0)` and `Yi` is sampled uniformly from the window.
134134
"""
135-
function centered(size::Int, window::Int, seed::Int)
135+
function center_sample(size::Int, window::Int, seed::Int)
136136
srand(seed)
137137
count = 0
138138
sample = CartesianIndex{2}[]
@@ -148,7 +148,8 @@ function centered(size::Int, window::Int, seed::Int)
148148
end
149149

150150
function create_descriptor{T<:Gray}(img::AbstractArray{T, 2}, keypoints::Keypoints, params::BRIEF)
151-
img_smoothed = imfilter_gaussian(img, [params.sigma, params.sigma])
151+
factkernel = KernelFactors.IIRGaussian([params.sigma, params.sigma])
152+
img_smoothed = imfilter(Float64, img, factkernel, NA())
152153
sample_one, sample_two = params.sampling_type(params.size, params.window, params.seed)
153154
descriptors = BitArray{1}[]
154155
h, w = size(img_smoothed)

src/core.jl

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,18 @@ function match_keypoints(keypoints_1::Keypoints, keypoints_2::Keypoints, desc_1,
104104
end
105105
end
106106
matches
107-
end
107+
end
108+
109+
"""
110+
```
111+
grade = grade_matches(keypoints_1, keypoints_2, limit, difference_method)
112+
```
113+
Returns the fraction of keypoint pairs which have
114+
`difference_method(keypoint_1,keypoint_2)` less than `limit`.
115+
"""
116+
117+
function grade_matches(keypoints_1::Keypoints, keypoints_2::Keypoints, limit::Real, diff::Function = (i,j) -> (sqrt( (i[1]-j[1])^2 + (i[2]-j[2])^2 )))
118+
@assert length(keypoints_1)==length(keypoints_2) "Keypoint lists are of different lengths."
119+
@assert length(keypoints_1)!=0 "Keypoint list is of size zero."
120+
mean(map((keypoint_1,keypoint_2)->((diff(keypoint_1,keypoint_2) < limit) ? 1.0 : 0.0), keypoints_1, keypoints_2))
121+
end

src/corner.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ function corner_orientations{T<:Gray, K<:Real}(img::AbstractArray{T, 2}, corners
1818
pre_y = ceil(Int, (h - 1) / 2)
1919
pre_x = ceil(Int, (w - 1) / 2)
2020
post_y = floor(Int, (h - 1) / 2)
21-
post_x = floor(Int, (w - 1) / 2)
22-
img_padded = padarray(img, [pre_y, pre_x], [post_y, post_x], "value", 0)
21+
post_x = floor(Int, (w - 1) / 2)
22+
img_padded = parent(padarray(img, Fill(0, (pre_y, pre_x), (post_y, post_x))))
2323
orientations = Float64[]
2424
for c in corners
2525
m10 = zero(T)
@@ -49,13 +49,13 @@ end
4949
function corner_orientations(img::AbstractArray)
5050
corners = imcorner(img)
5151
corner_indexes = Keypoints(corners)
52-
kernel = gaussian2d(2, [5, 5])
52+
kernel = Kernel.gaussian((2,2), (5, 5))
5353
kernel /= maxfinite(kernel)
54-
corner_orientations(img, corner_indexes, kernel)
54+
corner_orientations(img, corner_indexes, parent(kernel))
5555
end
5656

5757
function corner_orientations(img::AbstractArray, corners::Keypoints)
58-
kernel = gaussian2d(2, [5, 5])
58+
kernel = Kernel.gaussian((2,2), (5, 5))
5959
kernel /= maxfinite(kernel)
60-
corner_orientations(img, corners, kernel)
60+
corner_orientations(img, corners, parent(kernel))
6161
end

src/glcm.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ function glcm{T<:Real, A<:Real}(img::AbstractArray{T, 2}, distances::Array{Int,
1212
end
1313

1414
function glcm{T<:Colorant}(img::AbstractArray{T, 2}, distance::Integer, angle::Real, mat_size::Integer = 16)
15-
img_rescaled = map(i -> max(1, Int(ceil((convert(Gray{U8}, i).val.i) * mat_size / 256))), img)
15+
img_rescaled = map(i -> max(1, Int(ceil((reinterpret(gray(convert(Gray{N0f8}, i)))) * mat_size / 256))), img)
1616
_glcm(img_rescaled, distance, angle, mat_size)
1717
end
1818

1919
function glcm{T<:Colorant, A<:Real}(img::AbstractArray{T, 2}, distances::Array{Int, 1}, angles::Array{A, 1}, mat_size::Integer = 16)
20-
img_rescaled = map(i -> max(1, Int(ceil((convert(Gray{U8}, i).val.i) * mat_size / 256))), img)
20+
img_rescaled = map(i -> max(1, Int(ceil((reinterpret(gray(convert(Gray{N0f8}, i)))) * mat_size / 256))), img)
2121
glcm_matrices = [_glcm(img_rescaled, d, a, mat_size) for d in distances, a in angles]
2222
glcm_matrices
2323
end

src/lbp.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function _direction_coded_lbp{T}(img::AbstractArray{T, 2}, offsets::Array)
8080
lbp_image = zeros(UInt, size(img))
8181
R = CartesianRange(size(img))
8282
p = Int(length(offsets) / 2)
83-
raw_img = convert(Array{Int}, raw(img))
83+
raw_img = convert(Array{Int}, rawview(channelview(img)))
8484
neighbours = zeros(Int, length(offsets))
8585
for I in R
8686
for (i, o) in enumerate(offsets) neighbours[i] = Int(bilinear_interpolation(img, I[1] + o[1], I[2] + o[2]).val.i) end
@@ -116,16 +116,16 @@ function multi_block_lbp{T<:Gray}(img::AbstractArray{T, 2}, tl_y::Integer, tl_x:
116116
lbp_code
117117
end
118118

119-
function _create_descriptor{T<:FixedPointNumbers.UFixed}(img::AbstractArray{Gray{T}, 2}, yblocks::Integer = 4, xblocks = 4, lbp_type::Function = lbp, args...)
119+
function _create_descriptor{T<:Normed}(img::AbstractArray{Gray{T}, 2}, yblocks::Integer = 4, xblocks = 4, lbp_type::Function = lbp, args...)
120120
h, w = size(img)
121121
blockh = ceil(Int, h / (yblocks))
122122
blockw = ceil(Int, w / (xblocks))
123123
el_max = typemax(FixedPointNumbers.rawtype(eltype(img[1])))
124124
edges = 0:Int((el_max+1)^0.5):el_max+1
125-
descriptor = Int64[]
125+
descriptor = Int[]
126126
for i in 1:xblocks
127127
for j in 1:yblocks
128-
lbp_image = lbp_type(img[j : j + blockh - 1, i : i + blockw - 1], args...)
128+
lbp_image = lbp_type(img[(j-1)*blockh+1 : j*blockh, (i-1)*blockw+1 : i*blockw], args...)
129129
lbp_norm = lbp_image
130130
_, hist = imhist(lbp_image, edges)
131131
append!(descriptor, hist[2 : end - 1])
@@ -134,7 +134,7 @@ function _create_descriptor{T<:FixedPointNumbers.UFixed}(img::AbstractArray{Gray
134134
descriptor
135135
end
136136

137-
function create_descriptor{T<:FixedPointNumbers.UFixed}(img::AbstractArray{Gray{T}, 2}, yblocks::Integer = 4, xblocks = 4; lbp_type::Function = lbp, args...)
137+
function create_descriptor{T<:Normed}(img::AbstractArray{Gray{T}, 2}, yblocks::Integer = 4, xblocks = 4; lbp_type::Function = lbp, args...)
138138
h, w = size(img)
139139
y_padded = ceil(Int, h / (yblocks)) * yblocks
140140
x_padded = ceil(Int, w / (xblocks)) * xblocks

test/brief.jl

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using FactCheck, Images, ImageFeatures, TestImages, Distributions, ColorTypes, TestImages
1+
using FactCheck, Images, ImageFeatures, TestImages, Distributions
22

33
facts("BRIEF") do
44

@@ -12,7 +12,7 @@ facts("BRIEF") do
1212
context("Sampling Patterns") do
1313
# Check Bounds
1414
for si in [32, 128, 256], wi in [5, 15, 25, 49], se in [123, 546, 178]
15-
s1, s2 = centered(si, wi, se)
15+
s1, s2 = ImageFeatures.center_sample(si, wi, se)
1616
@fact check_samples(s1, s2, si, wi) --> true
1717
@fact s1 == zeros(CartesianIndex{2}, si) --> true
1818
s1, s2 = random_coarse(si, wi, se)
@@ -27,31 +27,48 @@ facts("BRIEF") do
2727
end
2828

2929
context("Descriptor Calculation") do
30-
img_1 = Gray{Float64}[ 0 0 0 0 0 0
31-
0 0 1 1 0 0
32-
0 0 1 1 0 0
33-
0 0 1 1 0 0
34-
0 0 1 1 0 0
35-
0 0 0 0 0 0 ]
30+
img_1 = Gray{Float64}[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
31+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
32+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
33+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
34+
0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
35+
0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
36+
0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
37+
0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
38+
0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0
39+
0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0
40+
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
41+
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
42+
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
43+
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
44+
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
45+
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
46+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
47+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
48+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
49+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
3650
keypoints_1 = Keypoints(imcorner(img_1))
3751

38-
img_2 = Gray{Float64}[ 0 0 0 0 0 0
39-
0 0 1 1 0 0
40-
0 0 1 1 0 0
41-
0 0 1 1 0 0
42-
0 0 1 1 0 0
43-
0 0 1 1 0 0
44-
0 0 1 1 0 0
45-
0 0 0 0 0 0 ]
52+
img_2 = Gray{Float64}[ 0 0 0 0 0 0 0 0 0 0
53+
0 0 0 0 0 0 0 0 0 0
54+
0 0 1 1 1 0 0 0 0 0
55+
0 0 1 1 1 1 0 0 0 0
56+
0 0 1 1 1 1 1 0 0 0
57+
0 0 1 1 1 1 1 1 0 0
58+
0 0 1 1 1 1 1 1 0 0
59+
0 0 1 1 1 1 1 1 0 0
60+
0 0 0 0 0 0 0 0 0 0
61+
0 0 0 0 0 0 0 0 0 0 ]
4662
keypoints_2 = Keypoints(imcorner(img_2))
4763

4864
brief_params = BRIEF(size = 8, window = 3, seed = 123)
4965

5066
desc_1, ret_keypoints_1 = create_descriptor(img_1, keypoints_1, brief_params)
5167
desc_2, ret_keypoints_2 = create_descriptor(img_2, keypoints_2, brief_params)
5268
matches = match_keypoints(ret_keypoints_1, ret_keypoints_2, desc_1, desc_2)
53-
expected_matches = [[CartesianIndex((2,3)),CartesianIndex((2,3))],
54-
[CartesianIndex((5,3)),CartesianIndex((7,3))]]
69+
expected_matches = [[CartesianIndex((5,4)),CartesianIndex((3,3))],
70+
[CartesianIndex((16,4)),CartesianIndex((8,3))],
71+
[CartesianIndex((16,15)),CartesianIndex((8,8))]]
5572
@fact all(matches .== expected_matches) --> true
5673

5774
img_1 = Gray{Float64}[ 0 0 0 0 0 0 0 0 0

0 commit comments

Comments
 (0)