-
Notifications
You must be signed in to change notification settings - Fork 9
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
[WIP]Add boosting tracker #20
base: master
Are you sure you want to change the base?
Changes from 5 commits
1f23e78
252c01e
ed3dc2c
dca7da3
3ffa15e
fcddb94
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,30 @@ | ||
name = "ImageTracking" | ||
uuid = "5cb2747a-620a-11e9-38cd-3dc946e3e5f7" | ||
version = "0.1.0" | ||
|
||
[deps] | ||
AxisAlgorithms = "13072b0f-2c55-5437-9ae7-d433b7a33950" | ||
CoordinateTransformations = "150eb455-5306-5404-9cee-2592286d6298" | ||
ImageFiltering = "6a3955dd-da59-5b1f-98d4-e7296123deb5" | ||
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" | ||
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" | ||
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" | ||
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" | ||
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" | ||
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" | ||
|
||
[compat] | ||
AxisAlgorithms = ">= 0.2" | ||
ImageFiltering = ">= 0.3" | ||
Images = ">= 0.17" | ||
Interpolations = ">= 0.7" | ||
julia = ">= 0.7" | ||
|
||
[extras] | ||
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" | ||
QuartzImageIO = "dca85d43-d64c-5e67-8c65-017450d5d020" | ||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" | ||
TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990" | ||
|
||
[targets] | ||
test = ["Test", "TestImages", "ImageMagick", "QuartzImageIO"] |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,3 +30,23 @@ function pinv2x2(M::AbstractArray) | |
D = SMatrix{2,2,Float64}( S[1,1] > tol ? 1/S[1,1] : 0.0 , 0.0, 0.0, S[2,2] > tol ? 1/S[2,2] : 0.0 ) | ||
U*D*V' | ||
end | ||
|
||
abstract type AbstractTrackerTargetState end | ||
mutable struct BoostingTrackerTargetState <: AbstractTrackerTargetState | ||
#Initialized | ||
position::SVector{2, Float64} | ||
height::Integer | ||
width::Integer | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this stands for tracking region position::SVector{2, Float64}
height::Integer
width::Integer you can use |
||
is_target::Bool | ||
|
||
#Uninitialized | ||
responses::Array{T, 2} where T | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the purpose of |
||
BoostingTrackerTargetState(position::SVector{2, Float64}, height::Integer, width::Integer, is_target::Bool) = | ||
new(position, height, width, is_target) | ||
end | ||
|
||
|
||
mutable struct ConfidenceMap{T <: AbstractTrackerTargetState, F <: AbstractFloat} | ||
states::Vector{T} | ||
confidence::Vector{F} | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#----------------------------------- | ||
# Implementation of boosting tracker | ||
#----------------------------------- | ||
|
||
function initialize!(tracker::TrackerBoosting) | ||
int_image = integral_image(tracker.box.img) | ||
|
||
# sampling | ||
int_box = BoxROI(int_image, tracker.box.bound) | ||
|
||
tracker.sampler.mode = :positive | ||
positive_samples = sample_roi(tracker.sampler, int_box) | ||
|
||
tracker.sampler.mode = :negative | ||
negative_samples = sample_roi(tracker.sampler, int_box) | ||
|
||
if isempty(positive_samples) || isempty(negative_samples) | ||
error("Couldn't get initial samples") | ||
end | ||
# compute harr haar_features | ||
|
||
# model | ||
|
||
# Run model estimation and update for initial iterations | ||
end | ||
|
||
function update!(tracker::TrackerBoosting, image::AbstractArray) | ||
|
||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#--------------------- | ||
# TRACKER COMPONENTS | ||
#--------------------- | ||
|
||
include("../core.jl") | ||
include("tracker_sampler.jl") | ||
# include("tracker_state_estimator.jl") | ||
# include("tracker_model.jl") | ||
# include("tracker_features.jl") | ||
|
||
abstract type AbstractTracker end | ||
mutable struct TrackerBoosting{I <: Integer, B <: BoxROI, CS <: CurrentSampler} <: AbstractTracker | ||
# initialized | ||
box::B | ||
sampler::CS | ||
num_of_classifiers::I | ||
initial_iterations::I | ||
num_of_features::I | ||
|
||
# constructor | ||
function TrackerBoosting{I, B, CS}(box::B, sampler::CS, num_of_classifiers::I = 100, initial_iterations::I = 20, | ||
num_of_features::I = 1050)where {I <: Integer, B <: BoxROI, CS <: CurrentSampler} | ||
if size(box.bound, 1) != 4 | ||
error("Invalid bounding box size") | ||
end | ||
|
||
if box.bound[1] < 1 && box.bound[1] > size(box.img)[1] | ||
Deepank308 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
error("Invalid bounding box") | ||
end | ||
if box.bound[2] < 1 && box.bound[2] > size(box.img)[2] | ||
error("Invalid bounding box") | ||
end | ||
if box.bound[3] < 1 && box.bound[3] > size(box.img)[1] | ||
error("Invalid bounding box") | ||
end | ||
if box.bound[4] < 1 && box.bound[4] > size(box.img)[2] | ||
error("Invalid bounding box") | ||
end | ||
|
||
if box.bound[1] > box.bound[3] | ||
error("Invalid bounding box") | ||
end | ||
if box.bound[2] > box.bound[4] | ||
error("Invalid bounding box") | ||
end | ||
new(box, sampler, num_of_classifiers, initial_iterations, num_of_features) | ||
end | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that in general you can write inequalities like this in Julia: if 0 < x < 1
do something
end rather than if x > 0 && x < 1
do something
end The former is much more readable. |
||
|
||
TrackerBoosting(box::B, sampler::CS, num_of_classifiers::I, initial_iterations::I, num_of_features::I) | ||
where{I <: Integer, B <: BoxROI, CS <: CurrentSampler} = | ||
TrackerBoosting{I, B, CS}(box, sampler, num_of_classifiers, initial_iterations, num_of_features) | ||
|
||
|
||
#------------------ | ||
# IMPLEMENTATIONS | ||
#------------------ | ||
|
||
include("boosting_tracker.jl") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
abstract type AbstractROI end | ||
mutable struct BoxROI{T <: AbstractArray, S <: AbstractArray} <: AbstractROI | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should be storing the entire image as a field in struct BoxROI{R₁ <: AbstractRange, R₂} <: AbstractROI
span₁::R₁
span₂::R₂
end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is |
||
img::T | ||
bound::S | ||
end | ||
|
||
abstract type AbstractTrackerSampler end | ||
mutable struct CurrentSampler{F <: AbstractFloat} <: AbstractTrackerSampler | ||
overlap::F | ||
search_factor::F | ||
mode::S where S <: Symbol | ||
Deepank308 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
sampling_region::SVector{4, Integer} | ||
valid_region::SVector{4, Integer} | ||
tracked_patch::SVector{4, Integer} | ||
CurrentSampler{F}(overlap, search_factor) where{F <: AbstractFloat} = new(overlap, search_factor) | ||
Deepank308 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
|
||
CurrentSampler(overlap::F = 0.99, search_factor::F = 1.8) where{F <: AbstractFloat} = CurrentSampler{F}(overlap, search_factor) | ||
|
||
function sample_roi(sampler::CurrentSampler, box::BoxROI) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You would then pass the image as a parameter (instead of retrieving it from BoxROI). |
||
sampler.tracked_patch = box.bound | ||
sampler.valid_region = SVector{4, Integer}([1, 1, size(box.img, 1), size(box.img, 2)]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could just be a tuple taken from |
||
|
||
height = box.bound[3] - box.bound[1] + 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can write a custom |
||
width = box.bound[4] - box.bound[2] + 1 | ||
|
||
sampling_region_min_y = max(0, floor(Integer, box.bound[1] - height*((sampler.search_factor - 1) / 2) + 1)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of all of the search_factor = get_search_factor(sampler)
sampling_region_min_y = ... So that you don't keep writing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I'll take care of this. |
||
sampling_region_min_x = max(0, floor(Integer, box.bound[2] - width*((sampler.search_factor - 1) / 2) + 1)) | ||
|
||
sampling_region_height = min(floor(Integer, height*sampler.search_factor), size(box.img, 1) - sampling_region_min_y + 1) | ||
sampling_region_width = min(floor(Integer, width*sampler.search_factor), size(box.img, 2) - sampling_region_min_x + 1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please clarify the role of the |
||
|
||
sampling_region_max_y = sampling_region_min_y + sampling_region_height - 1 | ||
sampling_region_max_x = sampling_region_min_x + sampling_region_width - 1 | ||
|
||
sampling_region = SVector{4, Integer}([sampling_region_min_y, sampling_region_min_x, sampling_region_max_y, sampling_region_max_x]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not a good idea. You are allocating an array by invoking the square brackets |
||
|
||
sample_mode_roi(sampler, box, sampling_region) | ||
end | ||
|
||
function sample_mode_roi(sampler::CurrentSampler, box::BoxROI, sampling_region::SVector{4, Integer}) | ||
if sampler.valid_region == sampling_region | ||
sampler.sampling_region = sampling_region | ||
else | ||
sampler.sampling_region = SVector{4, Integer}(max(sampler.valid_region[1], sampling_region[1]), max(sampler.valid_region[2],sampling_region[2]), | ||
min(sampler.valid_region[3], sampling_region[3]), min(sampler.valid_region[4], sampling_region[4])) | ||
end | ||
|
||
if sampler.mode == :positive | ||
positive_sample = box.img[sampler.tracked_patch[1]:sampler.tracked_patch[3], | ||
sampler.tracked_patch[2]:sampler.tracked_patch[4]] | ||
positive_sample_pos = SVector{2, Integer}(sampler.tracked_patch[1], sampler.tracked_patch[2]) | ||
samples = fill((positive_sample, positive_sample_pos), (1, 4)) | ||
|
||
return samples | ||
end | ||
|
||
height = sampler.tracked_patch[3] - sampler.tracked_patch[1] + 1 | ||
width = sampler.tracked_patch[4] - sampler.tracked_patch[2] + 1 | ||
|
||
tl_block = SVector{4, Integer}(sampler.sampling_region[1], sampler.sampling_region[2], sampler.sampling_region[1] + height - 1, | ||
sampler.sampling_region[2] + width - 1) | ||
tr_block = SVector{4, Integer}(sampler.sampling_region[1], sampler.sampling_region[4] - width + 1, sampler.sampling_region[1] + height - 1, | ||
sampler.sampling_region[4]) | ||
bl_block = SVector{4, Integer}(sampler.sampling_region[3] - height + 1, sampler.sampling_region[2], sampler.sampling_region[3], | ||
sampler.sampling_region[2] + width - 1) | ||
br_block = SVector{4, Integer}(sampler.sampling_region[3] - height + 1, sampler.sampling_region[4] - width + 1, sampler.sampling_region[3], | ||
sampler.sampling_region[4]) | ||
|
||
if sampler.mode == :negative | ||
tl_sample = box.img[tl_block[1]:tl_block[3], tl_block[2]:tl_block[4]] | ||
tr_sample = box.img[tr_block[1]:tr_block[3], tr_block[2]:tr_block[4]] | ||
bl_sample = box.img[bl_block[1]:bl_block[3], bl_block[2]:bl_block[4]] | ||
br_sample = box.img[br_block[1]:br_block[3], br_block[2]:br_block[4]] | ||
samples = [(tl_sample, SVector{2, Integer}(tl_block[1:2])), (tr_sample, SVector{2, Integer}(tr_block[1:2])), | ||
(bl_sample, SVector{2, Integer}(bl_block[1:2])), (br_sample, SVector{2, Integer}(br_block[1:2]))] | ||
|
||
return samples | ||
end | ||
|
||
if sampler.mode == :classify | ||
step_row = max(1, floor(Int, (1 - sampler.overlap)*height + 0.5)) | ||
step_col = max(1, floor(Int, (1 - sampler.overlap)*width + 0.5)) | ||
max_row = sampler.sampling_region[3] - sampler.sampling_region[1] - height + 1 | ||
max_col = sampler.sampling_region[4] - sampler.sampling_region[2] - width + 1 | ||
|
||
samples = Array{Tuple{Array{T, 2}, SVector{2, Integer}}} where T <: Integer | ||
for i = 1:step_col:max_col | ||
for j = 1:step_row:max_row | ||
push!(samples, (box.img[j + sampler.sampling_region[1] - 1:j + sampler.sampling_region[1] + height - 2, | ||
i + sampler.sampling_region[2] - 1:i + sampler.sampling_region[2] + width - 2], | ||
SVector{2, Integer}(j + sampler.sampling_region[1]-1, i + sampler.sampling_region[2]-1))) | ||
end | ||
end | ||
|
||
return samples | ||
else | ||
Deepank308 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
error("Incorrect mode.") | ||
end | ||
|
||
end |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be kept in a separate file as well.