Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

more improvements #45

Merged
merged 7 commits into from
Oct 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 34 additions & 39 deletions src/AdaBoost.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ function learn(
votes::Matrix{Int8},
num_classifiers::Integer=-one(Int32)
)

# get number of positive and negative images (and create a global variable of the total number of images——global for the @everywhere scope)
num_pos = length(filtered_ls(positive_path))
num_neg = length(filtered_ls(negative_path))
Expand All @@ -118,35 +117,52 @@ function learn(
# select classifiers
classifiers = HaarLikeObject[]
p = Progress(num_classifiers, 1) # minimum update interval: 1 second
classification_errors = Vector{Float64}(undef, length(feature_indices))

for t in 1:num_classifiers
classification_errors = Matrix{Float64}(undef, length(feature_indices), 1)
# classification_errors = zeros(length(feature_indices))
#classification_errors = Matrix{Float64}(undef, length(feature_indices), 1)

# normalize the weights $w_{t,i}\gets \frac{w_{t,i}}{\sum_{j=1}^n w_{t,j}}$
weights = float(weights) / sum(weights)
inv_sumweights = inv(sum(weights))
weights .*= inv_sumweights
# For each feature j, train a classifier $h_j$ which is restricted to using a single feature. The error is evaluated with respect to $w_j,\varepsilon_j = \sum_i w_i\left|h_j\left(x_i\right)-y_i\right|$
classification_errors[:] .= [sum([labels[img_idx] !== votes[feature_indices[j], img_idx] ? weights[img_idx] : zero(Float64) for img_idx in 1:num_imgs]) for j in 1:length(feature_indices)]
# map!(view(classification_errors, :), 1:length(feature_indices)) do j
# sum(1:num_imgs) do img_idx
# labels[img_idx] !== votes[feature_indices[j], img_idx] ? weights[img_idx] : zero(Float64)
# end
# end


for j in 1:length(feature_indices)
_sum = sum(1:num_imgs) do img_idx
_bool = (labels[img_idx] !== votes[feature_indices[j], img_idx])
_bool*weights[img_idx]
end
classification_errors[j] = _sum
end

# choose the classifier $h_t$ with the lowest error $\varepsilon_t$
best_error, min_error_idx = findmin(classification_errors)
best_feature_idx = feature_indices[min_error_idx]
best_feature = features[best_feature_idx]

# set feature weight
feature_weight = 0.5 * log((1 - best_error) / best_error) # β
best_feature = features[best_feature_idx]
feature_weight = β(best_error) # β
best_feature.weight = feature_weight

classifiers = push!(classifiers, best_feature)

sqrt_best_error = @fastmath(sqrt(best_error / (one(best_error) - best_error)))
inv_sqrt_best_error = @fastmath(sqrt((one(best_error) - best_error)/best_error))
# update image weights $w_{t+1,i}=w_{t,i}\beta_{t}^{1-e_i}$
weights .= [labels[i] !== votes[best_feature_idx, i] ? weights[i] * sqrt((1 - best_error) / best_error) : weights[i] * sqrt(best_error / (1 - best_error)) for i in 1:num_imgs]

@inbounds for i in 1:num_imgs
if labels[i] !== votes[best_feature_idx, i]
weights[i] *= inv_sqrt_best_error
else
weights[i] *= sqrt_best_error
end
end

# remove feature (a feature can't be selected twice)
filter!(e -> e ∉ best_feature_idx, feature_indices) # note: without unicode operators, `e ∉ [a, b]` is `!(e in [a, b])`

resize!(classification_errors,length(feature_indices))
next!(p) # increment progress bar
end

Expand All @@ -156,33 +172,12 @@ function learn(

end

"""
learn(
positive_iis::AbstractArray,
negative_iis::AbstractArray,
num_classifiers::Int64=-1,
min_feature_width::Int64=1,
max_feature_width::Int64=-1,
min_feature_height::Int64=1,
max_feature_height::Int64=-1
) ->::Array{HaarLikeObject,1}

The boosting algorithm for learning a query online. T hypotheses are constructed, each using a single feature.
The final hypothesis is a weighted linear combination of the T hypotheses, where the weights are inversely proportional to the training errors.
This function selects a set of classifiers. Iteratively takes the best classifiers based on a weighted error.

# Arguments

- `positive_iis::AbstractArray`: List of positive integral image examples
- `negative_iis::AbstractArray`: List of negative integral image examples
- `num_classifiers::Integer`: Number of classifiers to select. -1 will use all classifiers
- `min_feature_width::Integer`: the minimum width of the feature
- `max_feature_width::Integer`: the maximum width of the feature
- `min_feature_height::Integer`: the minimum height of the feature
- `max_feature_width::Integer`: the maximum height of the feature
function β(err::T)::T where T
_1=one(err)
_half = T(0.5)
@fastmath(_half*log((_1 - err) / err))
end

# Returns `classifiers::Array{HaarLikeObject, 1}`: List of selected features
"""
function learn(
positive_path::AbstractString,
negative_path::AbstractString,
Expand Down
5 changes: 4 additions & 1 deletion src/HaarLikeFeature.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ Get score for given integral image array.
function get_score(feature::HaarLikeObject{I,F}, int_img::Array) where {I, F}
score = zero(I)
faceness = zero(I)

_2f = F(2)
_half = F(0.5)
_third = F(1.0/3.0)
_3f = F(3)
if feature.feature_type == feature_types.two_vertical
_first = sum_region(int_img, feature.top_left, (first(feature.top_left) + feature.width, I(round(last(feature.top_left) + feature.height / 2))))
_second = sum_region(int_img, (first(feature.top_left), I(round(last(feature.top_left) + feature.height / 2))), feature.bottom_right)
Expand Down