Skip to content

Commit

Permalink
Rectify faceness measure (addresses #56)
Browse files Browse the repository at this point in the history
This was previously incorrectly calculated.  The results for this are looking much more promising now.  The method of calculation is more in-line with what was originally proposed:
> As for your question about adapting the Viola-Jones face detector to return a measure of face-likeness - I think one simple thing you could use is the number of features computed before terminating from the cascade.  Face patches always make it to the end of the cascade, i.e. all Haar-like features are computed.  Non-faces usually result in early termination from the cascade, and the earlier, the less face-like the patch is (roughly speaking).  This certainly would not be a perfect measure, but I'm confident that there is a positive correlation between the total number of features computed in the cascade and the "face-likeness".
  • Loading branch information
jakewilliami committed Nov 9, 2021
1 parent 7e2475c commit 64e686f
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 6 deletions.
5 changes: 1 addition & 4 deletions src/HaarLikeFeature.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ Get vote of this feature for given integral image.
# Arguments
- `feature::HaarLikeObject`: given Haar-like feature (parameterised replacement of Python's `self`)
- `feature::HaarLikeObject`: given Haar-like feature
- `int_img::IntegralArray`: Integral image array
# Returns
Expand All @@ -142,8 +142,5 @@ Get vote of this feature for given integral image.
"""
function get_vote(feature::HaarLikeObject{I, F}, int_img::IntegralArray{T, N}) where {I, F, T, N}
score = get_score(feature, int_img)
# return (feature.weight * score) < (feature.polarity * feature.threshold) ? one(Int8) : -one(Int8)
# return feature.weight * (score < feature.polarity * feature.threshold ? one(Int8) : -one(Int8))
return score < feature.polarity * feature.threshold ? feature.weight : -feature.weight
# self.weight * (1 if score < self.polarity * self.threshold else -1)
end
26 changes: 24 additions & 2 deletions src/Utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,26 @@ function determine_feature_size(

end

function _ensemble_vote(int_img::IntegralArray{T, N}, classifiers::Vector{HaarLikeObject}) where {T, N}
classifiers = sort(classifiers, by = c -> c.weight, rev = true)
vote = 0
summed_vote = sum(get_vote(c, int_img) for c in classifiers) zero(Int8) ? one(Int8) : zero(Int8)
faceness = 0
for c in classifiers
vote = get_vote(c, int_img)
if vote < 0
# then no face is found using this classifier
# we reject this face
return summed_vote, faceness
return zero(Int8), faceness
end
# otherwise, keep looking
faceness += 1
end
return summed_vote, faceness
return one(Int8), faceness
end

@doc raw"""
ensemble_vote(int_img::IntegralArray, classifiers::AbstractArray) -> Integer
Expand All @@ -149,8 +169,8 @@ h(x) = \begin{cases}
1 ⟺ sum of classifier votes > 0
0 otherwise
"""
ensemble_vote(int_img::IntegralArray{T, N}, classifiers::Vector{HaarLikeObject}) where {T, N} =
sum(get_vote(c, int_img) for c in classifiers) zero(Int8) ? one(Int8) : zero(Int8)
ensemble_vote(int_img::IntegralArray{T, N}, classifiers::Vector{HaarLikeObject}) where {T, N} =
first(_ensemble_vote(int_img, classifiers))

"""
ensemble_vote_all(images::Vector{String}, classifiers::Vector{HaarLikeObject}) -> Vector{Int8}
Expand Down Expand Up @@ -204,6 +224,8 @@ function get_faceness(feature::HaarLikeObject{I, F}, int_img::IntegralArray{T, N
score, faceness = get_score(feature, int_img)
return (feature.weight * score) < (feature.polarity * feature.threshold) ? faceness : zero(T)
end
get_faceness(classifiers::Vector{HaarLikeObject}, int_img::IntegralArray{T, N}) where {T, N} =
last(_ensemble_vote(int_img, classifiers))

#=
reconstruct(classifiers::Vector, img_size::Tuple) -> AbstractArray
Expand Down

0 comments on commit 64e686f

Please sign in to comment.