├── .gitignore
├── 3rd_party
├── TLD
│ ├── bbox
│ │ ├── bb_burn.m
│ │ ├── bb_center.m
│ │ ├── bb_click.m
│ │ ├── bb_click_move.m
│ │ ├── bb_cluster.m
│ │ ├── bb_cluster_confidence.m
│ │ ├── bb_correct.m
│ │ ├── bb_distance.m
│ │ ├── bb_draw.m
│ │ ├── bb_get_similar.m
│ │ ├── bb_height.m
│ │ ├── bb_hull.m
│ │ ├── bb_isdef.m
│ │ ├── bb_isin.m
│ │ ├── bb_isout.m
│ │ ├── bb_normalize.m
│ │ ├── bb_points.m
│ │ ├── bb_predict.m
│ │ ├── bb_rescale_absolute.m
│ │ ├── bb_rescale_relative.m
│ │ ├── bb_scale.m
│ │ ├── bb_scan.m
│ │ ├── bb_shift_absolute.m
│ │ ├── bb_shift_relative.m
│ │ ├── bb_size.m
│ │ ├── bb_square.m
│ │ └── bb_width.m
│ ├── lk.cpp
│ ├── lkcompile.m
│ ├── tldTracking.m
│ └── utils
│ │ ├── idx2id.m
│ │ ├── mat2img.m
│ │ ├── maximize.m
│ │ ├── median2.m
│ │ ├── n2s.m
│ │ ├── ntuples.m
│ │ ├── pseudorandom_indexes.m
│ │ ├── randvalues.m
│ │ ├── repcel.m
│ │ ├── uniquecount.m
│ │ └── vnormp.m
├── addpath
│ ├── addpath_recurse.m
│ └── license.txt
├── sfigure.m
└── uninit
│ ├── license.txt
│ ├── uninit.c
│ ├── uninit.m
│ └── uninit.mexa64
├── README
├── README.md
├── compile.m
├── config
├── cfg.m
├── cluster_ctl.m
├── datapath.m
├── matlab_init.m
└── setpath.m
├── detection
├── Detector.m
├── cost_lcl_tsvm.m
├── feat_code.m
├── featpyramid.m
├── feature_get_for_svm.m
├── features.m
├── features_c.cc
├── gt_filter_detections.m
├── mex_resize.cc
├── nms.m
├── nms_c.cc
├── reduce.cc
└── scoreBox.m
├── evalOnVids.sh
├── hashMat_mat.m
├── learning
├── compute_tsvm_deltas.m
├── getDetsEst.m
└── learn_tsvm_score.m
├── mex
└── compat.h
├── model
├── Model.m
├── SVM_trainer.m
└── genModel.m
├── qp
├── QP.m
├── qp_assert.m
├── qp_clear.m
├── qp_init.m
├── qp_one.m
├── qp_one_c.cc
├── qp_opt.m
├── qp_prune.m
└── qp_write.m
├── rect
├── check_rect_size.m
├── csvBtoK.m
├── rectBtoK.m
├── rectKtoB.m
├── rect_area.m
├── rect_aspect.m
├── rect_center.m
├── rect_contains.m
├── rect_correct_aspect.m
├── rect_equal.m
├── rect_from_center.m
├── rect_image.m
├── rect_overlap.m
├── rect_scale.m
├── rect_size.m
├── rect_trans.m
├── rect_zero_orig.m
└── rects_overlap.m
├── show
├── hasDisplay.m
├── linWidth.m
├── plot_resp.m
├── showBox.m
├── showBoxVia.m
├── showBoxes.m
├── showGhostBoxes.m
└── showModel.m
├── track_dp
├── DPTracker.m
├── dynprog_chain.cc
├── track_dp.m
├── track_dp_backward.m
├── track_dp_forward.m
├── track_dp_forward_augment_states.m
├── track_dp_forward_one.m
├── track_dp_gen_occlusions.m
├── track_dp_init.m
└── track_dp_lcl.m
├── trackers
├── track_offline.m
├── track_online.m
└── track_tbd.m
└── video
├── clamp.m
├── f1score.m
├── get_frame.m
├── get_vid_range.m
├── gt_load.m
├── gt_occluded.m
├── gt_valid.m
├── hashMat.cc
├── imcropr.m
├── imgray.m
├── imrgb.m
├── score_track_file.m
├── score_track_one.m
├── track_scorer.m
└── vidLen.m
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | *.mexa64
3 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_burn.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function img = bb_burn(img, bb_in, width)
20 |
21 | if ~exist('width','var')
22 | width = 0;
23 | end
24 |
25 | if isempty(bb_in)
26 | return;
27 | end
28 |
29 | for i = 1:size(bb_in,2)
30 |
31 | bb = bb_in(:,i);
32 | bb(1) = max([1 bb(1)]);
33 | bb(2) = max([1 bb(2)]);
34 | bb(3) = min([size(img,2), bb(3)]);
35 | bb(4) = min([size(img,1), bb(4)]);
36 |
37 |
38 | img(bb(2):bb(2)+width,bb(1):bb(3)) = 255;
39 | img(bb(4)-width:bb(4),bb(1):bb(3)) = 255;
40 | img(bb(2):bb(4),bb(1):bb(1)+width) = 255;
41 | img(bb(2):bb(4),bb(3)-width:bb(3)) = 255;
42 |
43 | end
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_center.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function center = bb_center(bb)
20 | % Info
21 |
22 | if isempty(bb)
23 | center = [];
24 | return;
25 | end
26 |
27 | center = 0.5 * [bb(1,:)+bb(3,:); bb(2,:)+bb(4,:)];
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_click.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bb = bb_click(tld,img)
20 | % Create
21 |
22 | if isfield(tld,'handle')
23 | h = get(gca,'Children'); delete(h(1:end-1));
24 | set(tld.handle,'cdata',img);
25 | else
26 | imshow(img);
27 | end
28 | text(10,10,'Define bounding box and double click inside.','color','white');
29 | h = imrect;
30 | p = wait(h);
31 | bb = [p(1); p(2);p(1)+p(3); p(2)+p(4)];
32 | % [c,r,p] = impixel(img);
33 | % if length(c) ~= 2,
34 | % bb = [];
35 | % return;
36 | % end
37 | % bb = [c(1); r(1); c(2); r(2)];
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_click_move.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bb = bb_click_move(img,bb)
20 | % Change
21 |
22 | [c,r,p] = impixel(bb_burn(img,bb));
23 |
24 | bbW = bb_width(bb);
25 | bbH = bb_height(bb);
26 |
27 | bb = [c(1) - bbW/2; r(1) - bbH/2; c(1) + bbW/2; r(1) + bbH/2];
28 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_cluster.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function [bb,cSz] = bb_cluster(bb2, SPACE_THR, MIN_NUM_BB)
19 | % Clusters bboxes.
20 |
21 | if isempty(bb2)
22 | bb = [];
23 | cSz = [];
24 | return;
25 | end
26 |
27 | switch size(bb2,2)
28 | case 0, T = [];
29 | case 1, T = 1;
30 | case 2
31 | T = ones(2,1);
32 | if bb_distance(bb2) > SPACE_THR, T(2) = 2; end
33 | otherwise
34 | bbd = bb_distance(bb2);
35 | Z = linkagemex(bbd,'si');
36 | T = cluster(Z,'cutoff', SPACE_THR,'criterion','distance');
37 | end
38 | uT = unique(T);
39 |
40 | % Merge clusters
41 | bb = [];
42 | cSz = [];
43 | for i = 1:length(uT)
44 | num_bb = sum(T == uT(i));
45 | if num_bb >= MIN_NUM_BB
46 | bb = [bb mean(bb2(:,T == uT(i)),2)];
47 | cSz = [cSz num_bb];
48 | end
49 | end
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_cluster_confidence.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function [oBB,oConf,oSize] = bb_cluster_confidence(iBB, iConf)
20 | % Clusterering of tracker and detector responses
21 | % First cluster returned corresponds to the tracker
22 |
23 | SPACE_THR = 0.5;
24 |
25 | oBB = [];
26 | oConf = [];
27 | oSize = [];
28 |
29 | if isempty(iBB)
30 | return;
31 | end
32 |
33 | switch size(iBB,2)
34 | case 0, T = [];
35 | case 1, T = 1;
36 | case 2
37 | T = ones(2,1);
38 | if bb_distance(iBB) > SPACE_THR, T(2) = 2; end
39 | otherwise
40 | bbd = bb_distance(iBB);
41 | Z = linkagemex(bbd,'si');
42 | T = cluster(Z,'cutoff', SPACE_THR,'criterion','distance');
43 | end
44 |
45 | idx_cluster = unique(T);
46 | num_clusters = length(idx_cluster);
47 |
48 | oBB = nan(4,num_clusters);
49 | oConf = nan(1,num_clusters);
50 | oSize = nan(1,num_clusters);
51 |
52 | for i = 1:num_clusters
53 |
54 | idx = T == idx_cluster(i);
55 |
56 | oBB(:,i) = mean(iBB(1:4,idx),2);
57 | oConf(i) = mean(iConf(idx));
58 | oSize(i) = sum(idx);
59 |
60 | end
61 |
62 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_correct.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bb = bb_correct(img,bb)
20 | % Change
21 |
22 | K = 2;
23 | K2 = 1;
24 | while 1
25 |
26 | clf; imshow(img); bb_rectangle(bb,'EdgeColor','y');
27 | %maximize();
28 | [x,y,ch] = ginput(1);
29 | if isempty(ch), break; end
30 | switch ch
31 | case 29
32 | bb = [bb(1)+K; bb(2); bb(3)+K; bb(4)];
33 | case 28
34 | bb = [bb(1)-K; bb(2); bb(3)-K; bb(4)];
35 | case 30
36 | bb = [bb(1); bb(2)-K; bb(3); bb(4)-K];
37 | case 31
38 | bb = [bb(1); bb(2)+K; bb(3); bb(4)+K];
39 | case 46 % bigger
40 | bb = [bb(1)-K2; bb(2)-K2; bb(3)+K2; bb(4)+K2];
41 | case 44 % smaller
42 | bb = [bb(1)+K2; bb(2)+K2; bb(3)-K2; bb(4)-K2];
43 |
44 | end
45 |
46 | end
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_distance.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function d = bb_distance(bb1,bb2)
20 | % Info
21 |
22 | switch nargin
23 | case 1
24 | d = 1 - bb_overlap(bb1);
25 | case 2
26 | d = 1 - bb_overlap(bb1,bb2);
27 | end
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_draw.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bb_draw(bb1,varargin)
20 | % Draw
21 |
22 | if isempty(bb1), return; end;
23 | idx = find(bb_isdef(bb1));
24 | if isempty(varargin)
25 | varargin = {'edgecolor','y'};
26 | end
27 | for i = 1:length(idx)
28 | bb = bb1(:,idx(i));
29 | if bb(3)-bb(1) > 0 && bb(4)-bb(2)>0
30 | rectangle('Position',[bb(1) bb(2) bb(3)-bb(1) bb(4)-bb(2)],varargin{:})
31 |
32 | if size(bb,1) == 5
33 | cp = bb_center(bb);
34 | text(cp(1),cp(2),num2str(bb(5),3),'color','w');
35 | end
36 |
37 | end
38 | end
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_get_similar.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function [bb idx] = bb_get_similar(bb0,bb1,thr)
20 |
21 | idx = find(bb_overlap(bb1(1:4,:),bb0)>thr);
22 | bb = bb1(:,idx);
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_height.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bbH = bb_height(bb)
20 | % Info
21 |
22 | bbH = bb(4,:)-bb(2,:)+1;
23 |
24 |
25 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_hull.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bb = bb_hull(bb0)
20 |
21 | bb=[min(bb0(1,:)); ...
22 | min(bb0(2,:)); ...
23 | max(bb0(3,:)); ...
24 | max(bb0(4,:))];
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_isdef.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function id = bb_isdef(bb)
20 | % Info
21 |
22 | id = isfinite(bb(1,:));
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_isin.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function flag = bb_isin(bb,imsize)
20 |
21 | flag = bb(1,:) >= 1 & ...
22 | bb(2,:) >= 1 & ...
23 | bb(3,:) <= imsize(2) & ...
24 | bb(4,:) <= imsize(1);
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_isout.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function idx_out = bb_isout(bb,imsize)
20 |
21 | idx_out = bb(1,:) > imsize(2) | ...
22 | bb(2,:) > imsize(1) | ...
23 | bb(3,:) < 1 | ...
24 | bb(4,:) < 1;
25 |
26 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_normalize.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bb2 = bb_normalize(bb1,bb0)
20 | % Change
21 | % Shifts and rescales bboxes in BB1 according to the first bbox in BB0.
22 |
23 | W = bb_width( bb0(:,1)) / bb_width(bb1(:,1));
24 | H = bb_height( bb0(:,1)) / bb_height(bb1(:,1));
25 | SH = bb_center( bb0(:,1)) - bb_center(bb1(:,1));
26 |
27 | bb2 = bb_rescale(bb_shift(bb1,SH),[W,H]);
28 |
29 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_points.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function pt = bb_points(bb,numM,numN,margin)
20 | % Generates numM x numN points on BBox.
21 |
22 | bb(1:2) = bb(1:2)+margin;
23 | bb(3:4) = bb(3:4)-margin;
24 |
25 | if (numM == 1 && numN ==1)
26 | pt = bb_center(bb);
27 | return;
28 | end
29 |
30 | if (numM == 1 && numN > 1)
31 | c = bb_center(bb);
32 | stepW = (bb(3)-bb(1)) / (numN - 1);
33 | pt = ntuples(bb(1):stepW:bb(3),c(2));
34 | return;
35 | end
36 |
37 | if (numM > 1 && numN == 1)
38 | c = bb_center(bb);
39 | stepH = (bb(4)-bb(2)) / (numM - 1);
40 | pt = ntuples(c(1),(bb(2):stepH:bb(4)));
41 | return;
42 | end
43 |
44 | stepW = (bb(3)-bb(1)) / (numN - 1);
45 | stepH = (bb(4)-bb(2)) / (numM - 1);
46 |
47 | pt = ntuples(bb(1):stepW:bb(3),(bb(2):stepH:bb(4)));
48 |
49 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_predict.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function [BB1 shift] = bb_predict(BB0,pt0,pt1)
20 |
21 | of = pt1 - pt0;
22 | dx = median(of(1,:));
23 | dy = median(of(2,:));
24 |
25 | d1 = pdist(pt0','euclidean');
26 | d2 = pdist(pt1','euclidean');
27 | s = median(d2./d1);
28 |
29 | s1 = 0.5*(s-1)*bb_width(BB0);
30 | s2 = 0.5*(s-1)*bb_height(BB0);
31 |
32 | BB1 = [BB0(1)-s1; BB0(2)-s2; BB0(3)+s1; BB0(4)+s2] + [dx; dy; dx; dy];
33 | shift = [s1; s2];
34 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_rescale_absolute.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bb = bb_rescale_absolute(bb,row,col)
20 | % Change
21 |
22 | bb(1) = bb(1) - col;
23 | bb(2) = bb(2) - row;
24 | bb(3) = bb(3) + col;
25 | bb(4) = bb(4) + row;
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_rescale_relative.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function BB = bb_rescale_relative(BB,s)
20 | % Change
21 | BB = BB(1:4);
22 | if length(s) == 1
23 | s = s*[1 1];
24 | end
25 | if isempty(BB), BB = []; return; end
26 |
27 | s1 = 0.5*(s(1)-1)*bb_width(BB);
28 | s2 = 0.5*(s(2)-1)*bb_height(BB);
29 | BB = BB + [-s1; -s2; s1; s2];
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_scale.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function bbScale = bb_scale(bb)
19 | % Returns bbox scale = sqrt(bbox area)
20 |
21 | bbScale = sqrt((bb(4,:)-bb(2,:)+1).*(bb(3,:)-bb(1,:)+1));
22 |
23 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_scan.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function [bb_out,sca] = bb_scan(bb, imsize,min_win)
20 |
21 | SHIFT = 0.1;
22 | SCALE = 1.2.^[-10:10];
23 | MINBB = min_win;
24 |
25 | % Chack if input bbox is smaller than minimum
26 | if min(bb_size(bb)) < MINBB
27 | bb_out = [];
28 | sca = [];
29 | return;
30 | end
31 |
32 | bbW = round(bb_width(bb) .* SCALE);
33 | bbH = round(bb_height(bb) .* SCALE);
34 | bbSHH = SHIFT * min(bbH,bbH);
35 | bbSHW = SHIFT * min(bbH,bbW);
36 |
37 | bbF = [2 2 imsize(2) imsize(1)]';
38 |
39 | bbs = {};
40 | sca = [];
41 | idx = 1;
42 |
43 | for i = 1:length(SCALE)
44 | if bbW(i) < MINBB || bbH(i) < MINBB, continue; end
45 |
46 | left = round(bbF(1):bbSHW(i):bbF(3)-bbW(i)-1);
47 | top = round(bbF(2):bbSHH(i):bbF(4)-bbH(i)-1);
48 |
49 | grid = ntuples(top,left);
50 | if isempty(grid), continue; end
51 |
52 | bbs{end+1} = [grid(2,:); ...
53 | grid(1,:); ...
54 | grid(2,:)+bbW(i)-1; ...
55 | grid(1,:)+bbH(i)-1; ...
56 | idx*ones(1,size(grid,2));
57 | length(left)*ones(1,size(grid,2));];
58 | sca = [sca [bbH(i); bbW(i)]];
59 | idx = idx + 1;
60 | end
61 | bb_out = [];
62 | for i = 1:length(bbs)
63 | bb_out = [bb_out bbs{i}];
64 | end
65 |
66 | % for i = 1:length(bbs)
67 | %
68 | % if i-1 > 0
69 | % idx = bb_overlap(bbs{i},bbs{i-1},2);
70 | % bbs{i}(7,:) = idx;
71 | % end
72 | %
73 | % if i+1 <= length(bbs)
74 | % idx = bb_overlap(bbs{i},bbs{i+1},2);
75 | % bbs{i}(8,:) = idx;
76 | % end
77 | %
78 | % end
79 | % disp(['MINBB: ' num2str(MINBB) ', bb: ' num2str(size(bbs,2))]);
80 | % end
81 |
82 |
83 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_shift_absolute.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bb = bb_shift_absolute(bb,shift)
20 | % Change
21 |
22 | bb(1,:) = bb(1,:) + shift(1);
23 | bb(2,:) = bb(2,:) + shift(2);
24 | bb(3,:) = bb(3,:) + shift(1);
25 | bb(4,:) = bb(4,:) + shift(2);
26 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_shift_relative.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bb = bb_shift_relative(bb,shift)
20 | % Change
21 |
22 | if isempty(bb)
23 | return;
24 | end
25 | bb(1,:) = bb(1,:) + bb_width(bb)*shift(1);
26 | bb(2,:) = bb(2,:) + bb_height(bb)* shift(2);
27 | bb(3,:) = bb(3,:) + bb_width(bb)*shift(1);
28 | bb(4,:) = bb(4,:) + bb_height(bb)*shift(2);
29 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_size.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function s = bb_size(bb)
20 |
21 | s = [bb(4,:)-bb(2,:)+1; bb(3,:)-bb(1,:)+1];
22 |
23 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_square.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bb2 = bb_square(bb1)
20 | % Makes all bboxes square with the same area.
21 |
22 | if isempty(bb1);
23 | bb2 = [];
24 | return;
25 | end
26 |
27 | S = bb_scale(bb1);
28 | C = bb_center(bb1);
29 |
30 | bb2 = [C(1,:) - S/2; C(2,:) - S/2; C(1,:) + S/2; C(2,:) + S/2];
31 |
--------------------------------------------------------------------------------
/3rd_party/TLD/bbox/bb_width.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 |
19 | function bbW = bb_width(bb)
20 | % Info
21 |
22 | bbW = bb(3,:)-bb(1,:)+1;
23 |
24 |
25 |
--------------------------------------------------------------------------------
/3rd_party/TLD/lk.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Zdenek Kalal
2 | //
3 | // This file is part of TLD.
4 | //
5 | // TLD is free software: you can redistribute it and/or modify
6 | // it under the terms of the GNU General Public License as published by
7 | // the Free Software Foundation, either version 3 of the License, or
8 | // (at your option) any later version.
9 | //
10 | // TLD is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License
16 | // along with TLD. If not, see .
17 |
18 | #include "cv.h"
19 | #include "highgui.h"
20 | #include "math.h"
21 | #include
22 | #ifdef _CHAR16T
23 | #define CHAR16_T
24 | #endif
25 | #include "mex.h"
26 |
27 |
28 | const int MAX_COUNT = 500;
29 | const int MAX_IMG = 2;
30 | const int win_size = 4;
31 |
32 | void loadImageFromMatlab(const mxArray *mxImage, IplImage *image) {
33 |
34 | unsigned char *values = (unsigned char *) mxGetPr(mxImage);
35 | int widthStep = image->widthStep;
36 | int N = mxGetN(mxImage); // width
37 | int M = mxGetM(mxImage); // height
38 |
39 | if (N == 0 || M == 0) {
40 | printf("Input image error\n");
41 | return;
42 | }
43 |
44 | for(int i=0;iimageData[j*widthStep+i] = values[j+i*M];
47 | }
48 |
49 | void euclideanDistance (CvPoint2D32f *point1, CvPoint2D32f *point2, float *match, int nPts) {
50 |
51 | for (int i = 0; i < nPts; i++) {
52 |
53 | match[i] = sqrt((point1[i].x - point2[i].x)*(point1[i].x - point2[i].x) +
54 | (point1[i].y - point2[i].y)*(point1[i].y - point2[i].y) );
55 |
56 | }
57 | }
58 |
59 | void normCrossCorrelation(IplImage *imgI, IplImage *imgJ, CvPoint2D32f *points0, CvPoint2D32f *points1, int nPts, char *status, float *match,int winsize, int method) {
60 |
61 |
62 | IplImage *rec0 = cvCreateImage( cvSize(winsize, winsize), 8, 1 );
63 | IplImage *rec1 = cvCreateImage( cvSize(winsize, winsize), 8, 1 );
64 | IplImage *res = cvCreateImage( cvSize( 1, 1 ), IPL_DEPTH_32F, 1 );
65 |
66 | for (int i = 0; i < nPts; i++) {
67 | if (status[i] == 1) {
68 | cvGetRectSubPix( imgI, rec0, points0[i] );
69 | cvGetRectSubPix( imgJ, rec1, points1[i] );
70 | cvMatchTemplate( rec0,rec1, res, method );
71 | match[i] = ((float *)(res->imageData))[0];
72 |
73 | } else {
74 | match[i] = 0.0;
75 | }
76 | }
77 | cvReleaseImage( &rec0 );
78 | cvReleaseImage( &rec1 );
79 | cvReleaseImage( &res );
80 |
81 | }
82 |
83 |
84 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
85 | {
86 |
87 | double nan = std::numeric_limits::quiet_NaN();
88 | double inf = std::numeric_limits::infinity();
89 |
90 | // storage for the operation...
91 | CvPoint2D32f* points[3] = {0,0,0};
92 | IplImage **IMG = 0;
93 | IplImage **PYR = 0;
94 | IMG = (IplImage**) calloc(MAX_IMG,sizeof(IplImage*));
95 | PYR = (IplImage**) calloc(MAX_IMG,sizeof(IplImage*));
96 | //mexPrintf("LK: initialized\n");
97 |
98 | if (nrhs == 0) {
99 | mexPrintf("Lucas-Kanade\n");
100 | return;
101 | }
102 |
103 | // 0: init
104 | // 2: track
105 | int opcode = (int) *mxGetPr(prhs[0]);
106 | if(opcode == 0)
107 | return;
108 |
109 | if (IMG == 0 || (nrhs != 5 && nrhs != 6)) {
110 | if(IMG == 0)
111 | {
112 | mexPrintf("IMG==0");
113 | return;
114 | }
115 | else
116 | {
117 |
118 | mexPrintf("lk(2,imgI,imgJ,ptsI,ptsJ,Level)\n");
119 | // 0 1 2 3 4
120 | return;
121 | }
122 | }
123 | int Level;
124 | if (nrhs == 6) {
125 | Level = (int) *mxGetPr(prhs[5]);
126 | } else {
127 | Level = 5;
128 | }
129 |
130 |
131 | int I = 0;
132 | int J = 1;
133 | int Winsize = 10;
134 |
135 | // Images
136 | if (IMG[I] != 0) {
137 | loadImageFromMatlab(prhs[1],IMG[I]);
138 | } else {
139 | CvSize imageSize = cvSize(mxGetN(prhs[1]),mxGetM(prhs[1]));
140 | IMG[I] = cvCreateImage( imageSize, 8, 1 );
141 | PYR[I] = cvCreateImage( imageSize, 8, 1 );
142 | loadImageFromMatlab(prhs[1],IMG[I]);
143 | }
144 |
145 | if (IMG[J] != 0) {
146 | loadImageFromMatlab(prhs[2],IMG[J]);
147 | } else {
148 | CvSize imageSize = cvSize(mxGetN(prhs[2]),mxGetM(prhs[2]));
149 | IMG[J] = cvCreateImage( imageSize, 8, 1 );
150 | PYR[J] = cvCreateImage( imageSize, 8, 1 );
151 | loadImageFromMatlab(prhs[2],IMG[J]);
152 | }
153 |
154 | // Points
155 | double *ptsI = mxGetPr(prhs[3]); int nPts = mxGetN(prhs[3]);
156 | double *ptsJ = mxGetPr(prhs[4]);
157 |
158 | if (nPts != mxGetN(prhs[4])) {
159 | mexPrintf("Inconsistent input!\n");
160 | return;
161 | }
162 |
163 | points[0] = (CvPoint2D32f*)cvAlloc(nPts*sizeof(CvPoint2D32f)); // template
164 | points[1] = (CvPoint2D32f*)cvAlloc(nPts*sizeof(CvPoint2D32f)); // target
165 | points[2] = (CvPoint2D32f*)cvAlloc(nPts*sizeof(CvPoint2D32f)); // forward-backward
166 |
167 | for (int i = 0; i < nPts; i++) {
168 | points[0][i].x = ptsI[2*i]; points[0][i].y = ptsI[2*i+1];
169 | points[1][i].x = ptsJ[2*i]; points[1][i].y = ptsJ[2*i+1];
170 | points[2][i].x = ptsI[2*i]; points[2][i].y = ptsI[2*i+1];
171 | }
172 |
173 | // allocate space for the LK results...
174 | float *ncc = (float*) cvAlloc(nPts*sizeof(float));
175 | float *ssd = (float*) cvAlloc(nPts*sizeof(float));
176 | float *fb = (float*) cvAlloc(nPts*sizeof(float));
177 | char *status = (char*) cvAlloc(nPts);
178 | char *backStatus = (char*) cvAlloc(nPts);
179 |
180 | cvCalcOpticalFlowPyrLK( IMG[I], IMG[J], PYR[I], PYR[J], points[0], points[1], nPts, cvSize(win_size,win_size), Level, status, 0, cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03), CV_LKFLOW_INITIAL_GUESSES);
181 | cvCalcOpticalFlowPyrLK( IMG[J], IMG[I], PYR[J], PYR[I], points[1], points[2], nPts, cvSize(win_size,win_size), Level, backStatus, 0, cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03), CV_LKFLOW_INITIAL_GUESSES | CV_LKFLOW_PYR_A_READY | CV_LKFLOW_PYR_B_READY );
182 |
183 | normCrossCorrelation(IMG[I],IMG[J],points[0],points[1],nPts, status, ncc, Winsize,CV_TM_CCOEFF_NORMED);
184 | //normCrossCorrelation(IMG[I],IMG[J],points[0],points[1],nPts, status, ssd, Winsize,CV_TM_SQDIFF);
185 | euclideanDistance( points[0],points[2],fb,nPts);
186 |
187 |
188 | // Output
189 | int M = 4;
190 | plhs[0] = mxCreateDoubleMatrix(M, nPts, mxREAL);
191 | double *output = mxGetPr(plhs[0]);
192 | for (int i = 0; i < nPts; i++) {
193 | if (status[i] == 1) {
194 | output[M*i] = (double) points[1][i].x;
195 | output[M*i+1] = (double) points[1][i].y;
196 | output[M*i+2] = (double) fb[i];
197 | output[M*i+3] = (double) ncc[i];
198 | //output[M*i+4] = (double) ssd[i];
199 | } else {
200 | output[M*i] = nan;
201 | output[M*i+1] = nan;
202 | output[M*i+2] = nan;
203 | output[M*i+3] = nan;
204 | //output[M*i+4] = nan;
205 | }
206 | }
207 |
208 | // free storage
209 | for (int i = 0; i < MAX_IMG; i++) {
210 | cvReleaseImage(&(IMG[i])); IMG[i] = 0;
211 | cvReleaseImage(&(PYR[i])); PYR[i] = 0;
212 | }
213 | free(IMG); IMG = 0;
214 | free(PYR); PYR = 0;
215 | //mexPrintf("LK: deallocated\n");
216 | cvFree(&ncc);
217 | cvFree(&ssd);
218 | cvFree(&fb );
219 | cvFree(&status);
220 | cvFree(&backStatus);
221 |
222 | return;
223 | }
224 |
225 |
226 |
--------------------------------------------------------------------------------
/3rd_party/TLD/lkcompile.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 | function lkcompile()
18 | [void,opencv_args] = unix('pkg-config --cflags --libs opencv | sed "s|/usr/lib64/libopencv_superres.so||g"')
19 | cmd = ['mex -g 3rd_party/TLD/lk.cpp -O ' opencv_args]
20 | eval(cmd);
21 |
22 | lk(0);
23 | end
24 |
25 |
--------------------------------------------------------------------------------
/3rd_party/TLD/tldTracking.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 | %
18 | % JSS3 - 2012.6.19
19 | % Conf, now, comes from LK not from NN validator.
20 | function [BB2 conf Valid] = tldTracking(BB1,I,J)
21 | % Estimates motion of bounding box BB1 from frame I to frame J
22 |
23 | % initialize output variables
24 | BB2 = []; % estimated bounding
25 | conf = []; % confidence of prediction
26 | Valid = 0; % is the predicted bounding box valid? if yes, learning will take place ...
27 |
28 | % estimate BB2
29 | xFI = bb_points(BB1,10,10,5); % generate 10x10 grid of points within BB1 with margin 5 px
30 | xFJ = lk(2,I,J,xFI,xFI); % track all points by Lucas-Kanade tracker from frame I to frame J, estimate Forward-Backward error, and NCC for each point
31 | medFB = median2(xFJ(3,:)); % get median of Forward-Backward error
32 | medNCC = median2(xFJ(4,:)); % get median for NCC
33 | idxF = xFJ(3,:) <= medFB & xFJ(4,:)>= medNCC; % get indexes of reliable points
34 | BB2 = bb_predict(BB1,xFI(:,idxF),xFJ(1:2,idxF)); % estimate BB2 using the reliable points only
35 | % assert(~gt_occluded(BB2'))
36 |
37 | %tld.xFJ = xFJ(:,idxF); % save selected points (only for display purposes)
38 |
39 | % detect failures
40 | %if ~bb_isdef(BB2) || bb_isout(BB2,size(I)), BB2 = []; return; end % bounding box out of image
41 | %if medFB > 10, BB2 = []; return; end % too unstable predictions
42 |
43 | % JSS3 - compute the confidence
44 | % get the valid points.
45 | %keyboard;
46 | xFI = xFI(1:2,idxF);
47 | xFJ = xFJ(1:2,idxF);
48 | total = size(xFI',1);
49 | correct = sum(rect_contains(BB2',xFJ'));
50 | conf = correct/total;
51 |
52 | % failed prediction ?
53 | if total < 1
54 | BB2 = BB1(1:4,:);
55 | conf = 0;
56 | end
57 |
--------------------------------------------------------------------------------
/3rd_party/TLD/utils/idx2id.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function id = idx2id(idx,N)
19 |
20 | id = zeros(1,N);
21 | id(idx) = 1;
22 | id = logical(id);
--------------------------------------------------------------------------------
/3rd_party/TLD/utils/mat2img.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function img = mat2img(data,no_row)
19 | % 'Data' contains square images stored in columns.
20 |
21 | if ~exist('RATIO','var')
22 | RATIO = 1;
23 | end
24 |
25 |
26 | if isempty(data)
27 | img = []; return;
28 | end
29 |
30 | [M,N] = size(data);
31 |
32 | sM = sqrt(M);
33 | if ceil(sM) ~= sM
34 | img = []; disp('Wrong input!'); return;
35 | end
36 |
37 | W = sM;
38 | H = sM;
39 |
40 | if no_row > N, no_row = N; end
41 | no_col = ceil(N/no_row);
42 | %no_row = ceil(N/no_col);
43 | img = zeros(no_row*H,no_col*W);
44 |
45 | for i = 1:N
46 |
47 | [I, J] = ind2sub([no_row, no_col], i);
48 |
49 | row = 1+(I-1)*H:(I-1)*H+H;
50 | col = 1+(J-1)*W:(J-1)*W+W;
51 |
52 | img0 = reshape(data(:,i),sM,sM);
53 | img0 = (img0 - min(img0(:))) / (max(img0(:)) - min(img0(:)));
54 | img(row, col) = img0;
55 |
56 | end
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/3rd_party/TLD/utils/maximize.m:
--------------------------------------------------------------------------------
1 | function maximize(fig)
2 | % MAXIMIZE Size a window to fill the entire screen.
3 | %
4 | % maximize(HANDLE fig)
5 | % Will size the window with handle fig such that it fills the entire screen.
6 | %
7 |
8 | % Modification History
9 | % ??/??/2001 WHF Created.
10 | % 04/17/2003 WHF Found 'outerposition' undocumented feature.
11 | %
12 |
13 | % Original author: Bill Finger, Creare Inc.
14 | % Free for redistribution as long as credit comments are preserved.
15 | %
16 |
17 | if nargin==0, fig=gcf; end
18 |
19 | units=get(fig,'units');
20 | set(fig,'units','normalized','outerposition',[0 0 1 1]);
21 | set(fig,'units',units);
22 |
23 | % Old way:
24 | % These are magic numbers which are probably system dependent.
25 | dim=get(0,'ScreenSize')-[0 -5 0 72];
26 |
27 | set(fig,'Position',dim);
28 |
29 |
30 |
--------------------------------------------------------------------------------
/3rd_party/TLD/utils/median2.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function m = median2(x)
19 | % Median without nan
20 |
21 | x(isnan(x)) = [];
22 | m = median(x);
23 |
--------------------------------------------------------------------------------
/3rd_party/TLD/utils/n2s.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function s = n2s(x,N)
19 | % Number to string.
20 |
21 | s = num2str(x,['%0' num2str(N) 'd']);
22 |
--------------------------------------------------------------------------------
/3rd_party/TLD/utils/ntuples.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function ntuple = ntuples(varargin)
19 | % Computes all possible ntupples.
20 |
21 | x = varargin;
22 |
23 | ntuple = x{1};
24 | for i = 2:length(x)
25 | num_col = size(ntuple,2);
26 | num_item = length(x{i});
27 | ntuple = repcel(ntuple, 1, num_item);
28 | newline = repmat(x{i},1,num_col);
29 | ntuple = [ntuple;newline];
30 | end
31 |
--------------------------------------------------------------------------------
/3rd_party/TLD/utils/pseudorandom_indexes.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function idx = pseudorandom_indexes(N,k)
19 |
20 | start = randi(k,1,1);
21 |
22 | idx = start:k:N;
--------------------------------------------------------------------------------
/3rd_party/TLD/utils/randvalues.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function out = randvalues(in,k)
19 | % Randomly selects 'k' values from vector 'in'.
20 |
21 | out = [];
22 |
23 | N = size(in,2);
24 |
25 | if k == 0
26 | return;
27 | end
28 |
29 | if k > N
30 | k = N;
31 | end
32 |
33 | if k/N < 0.0001
34 | i1 = unique(ceil(N*rand(1,k)));
35 | out = in(:,i1);
36 |
37 | else
38 | i2 = randperm(N);
39 | out = in(:,sort(i2(1:k)));
40 | end
--------------------------------------------------------------------------------
/3rd_party/TLD/utils/repcel.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function out = repcel(in,M,N)
19 | % Repeats cells MxN times.
20 |
21 | out = in(repmat(1:size(in,1),M,1),repmat(1:size(in,2),N,1));
--------------------------------------------------------------------------------
/3rd_party/TLD/utils/uniquecount.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function out = uniquecount(in)
19 | % Replaces value with number of occurences.
20 |
21 | uin = unique(in);
22 | out = in;
23 | for i = 1:length(uin)
24 |
25 | id = in == uin(i);
26 | out(id) = sum(id);
27 | end
28 |
29 |
--------------------------------------------------------------------------------
/3rd_party/TLD/utils/vnormp.m:
--------------------------------------------------------------------------------
1 | % Copyright 2011 Zdenek Kalal
2 | %
3 | % This file is part of TLD.
4 | %
5 | % TLD is free software: you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation, either version 3 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % TLD is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License
16 | % along with TLD. If not, see .
17 |
18 | function out = vnormp(in,p)
19 | % p-norm of columns
20 |
21 | out = (sum(abs(in).^p,1)).^(1/p);
--------------------------------------------------------------------------------
/3rd_party/addpath/addpath_recurse.m:
--------------------------------------------------------------------------------
1 | function addpath_recurse(strStartDir, caStrsIgnoreDirs, strXorIntAddpathMode, blnRemDirs, blnDebug)
2 | %ADDPATH_RECURSE Adds (or removes) the specified directory and its subfolders
3 | % addpath_recurse(strStartDir, caStrsIgnoreDirs, strXorIntAddpathMode, blnRemDirs, blnDebug)
4 | %
5 | % By default, all hidden directories (preceded by '.'), overloaded method directories
6 | % (preceded by '@'), and directories named 'private' or 'CVS' are ignored.
7 | %
8 | % Input Variables
9 | % ===============
10 | % strStartDir::
11 | % Starting directory full path name. All subdirectories (except ignore list) will be added to the path.
12 | % By default, uses current directory.
13 | % caStrsIgnoreDirs::
14 | % Cell array of strings specifying directories to ignore.
15 | % Will also ignore all subdirectories beneath these directories.
16 | % By default, empty list. i.e. {''}.
17 | % strXorIntAddpathMode::
18 | % Addpath mode, either 0/1, or 'begin','end'.
19 | % By default, prepends.
20 | % blnRemDirs::
21 | % Boolean, when true will run function "in reverse", and
22 | % recursively removes directories from starting path.
23 | % By default, false.
24 | % blnDebug::
25 | % Boolean, when true prints debug info.
26 | % By default, false.
27 | %
28 | % Output Variables
29 | % ================
30 | % None. If blnDebug is specified, diagnostic information will print to the screen.
31 | %
32 | % Example(s)
33 | % ==========
34 | % (1) addpath_recurse(); %Take all defaults.
35 | % (2) addpath_recurse('strStartDir'); %Start at 'strStartDir', take other defaults. i.e. Do addpath().
36 | % (3) addpath_recurse('strStartDir', '', 0, true); %Start at 'strStartDir', and undo example (2). i.e. Do rmpath().
37 | % (4) addpath_recurse('strStartDir', '', 'end', false, true); %Do example (2) again, append to path, and display debug info.
38 | % (5) addpath_recurse('strStartDir', '', 1, true, true); %Undo example (4), and display debug info.
39 |
40 | %
41 | % See Also
42 | % ========
43 | % addpath()
44 | %
45 | % Developers
46 | % ===========
47 | % Init Name Contact
48 | % ---- --------------- ---------------------------------------------
49 | % AK Anthony Kendall anthony [dot] kendall [at] gmail [dot] com
50 | % JMcD Joe Mc Donnell
51 | %
52 | % Modifications
53 | % =============
54 | % Version Date Who What
55 | % -------- -------- ----- --------------------------------------------------------------------
56 | % 00.00.00 20080808 AK First created.
57 | % 20090410 JMcD Redo input argument processing/checking.
58 | % Only do processing/checking once. Do recursion in separate function.
59 | % 20090411 JMcD Add debugging mode to display run info.
60 | % 20090414 AK Modified variable names, small edits to code, ignoring CSV by default
61 | % 20091104 AK Modified an optimization for Mac compatibility,
62 | % recursive calls to just build the string for
63 | % addpath/rmpath rather than call it each time
64 |
65 | %--------------------------------------------------------------------------
66 | %Error messages.
67 | strErrStartDirNoExist = 'Start directory does not exist ???';
68 | strErrIgnoreDirsType = 'Ignore directories must be a string or cell array. See HELP ???';
69 | strErrIllAddpathMode = 'Illegal value for addpath() mode. See HELP ???';
70 | strErrIllRevRecurseRemType = 'Illegal value for reverse recurse remove, must be a logical/boolean. See HELP ??';
71 |
72 | strErrWrongNumArg = 'Wrong number of input arguments. See HELP ???';
73 | strAddpathErrMessage = strErrIllAddpathMode;
74 |
75 | %Set input args defaults and/or check them.
76 | intNumInArgs = nargin();
77 | assert(intNumInArgs <= 5, strErrWrongNumArg);
78 |
79 | if intNumInArgs < 1
80 | strStartDir = pwd();
81 | end
82 |
83 | if intNumInArgs < 2
84 | caStrsIgnoreDirs = {''};
85 | end
86 |
87 | if intNumInArgs >= 2 && ischar(caStrsIgnoreDirs)
88 | caStrsIgnoreDirs = { caStrsIgnoreDirs };
89 | end
90 |
91 | if intNumInArgs < 3 || (intNumInArgs >= 3 && isempty(strXorIntAddpathMode))
92 | strXorIntAddpathMode = 0;
93 | end
94 |
95 | if intNumInArgs >= 3 && ischar(strXorIntAddpathMode) %Use 0/1 internally.
96 | strAddpathErrMessage = sprintf('Input arg addpath() mode "%s" ???\n%s', strXorIntAddpathMode, strErrIllAddpathMode);
97 | assert(any(strcmpi(strXorIntAddpathMode, {'begin', 'end'})), strAddpathErrMessage);
98 | strXorIntAddpathMode = strcmpi(strXorIntAddpathMode, 'end'); %When 'end' 0 sets prepend, otherwise 1 sets append.
99 | end
100 |
101 | if intNumInArgs < 4
102 | blnRemDirs = false;
103 | end
104 |
105 | if intNumInArgs < 5
106 | blnDebug = false;
107 | end
108 |
109 | if size(caStrsIgnoreDirs, 1) > 1
110 | caStrsIgnoreDirs = caStrsIgnoreDirs'; %Transpose from column to row vector, in theory.
111 | end
112 |
113 | %Check input args OK, before we do the thing.
114 | strErrStartDirNoExist = sprintf('Input arg start directory "%s" ???\n%s', strStartDir, strErrStartDirNoExist);
115 | assert(exist(strStartDir, 'dir') > 0, strErrStartDirNoExist);
116 | assert(iscell(caStrsIgnoreDirs), strErrIgnoreDirsType);
117 | assert(strXorIntAddpathMode == 0 || strXorIntAddpathMode == 1, strAddpathErrMessage);
118 | assert(islogical(blnRemDirs), strErrIllRevRecurseRemType);
119 | assert(islogical(blnDebug), 'Debug must be logical/boolean. See HELP.');
120 |
121 | if blnDebug
122 | intPrintWidth = 34;
123 | rvAddpathModes = {'prepend', 'append'};
124 | strAddpathMode = char(rvAddpathModes{ fix(strXorIntAddpathMode) + 1});
125 | strRevRecurseDirModes = { 'false', 'true' };
126 | strRevRecurseDirs = char(strRevRecurseDirModes{ fix(blnRemDirs) + 1 });
127 | strIgnoreDirs = '';
128 | for intD = 1 : length(caStrsIgnoreDirs)
129 | if ~isempty(strIgnoreDirs)
130 | strIgnoreDirs = sprintf('%s, ', strIgnoreDirs);
131 | end
132 | strIgnoreDirs = sprintf('%s%s', strIgnoreDirs, char(caStrsIgnoreDirs{intD}));
133 | end
134 | strTestModeResults = sprintf('... Debug mode, start recurse addpath arguments ...');
135 | strTestModeResults = sprintf('%s\n%*s: "%s"', strTestModeResults, intPrintWidth, 'Start directory', strStartDir);
136 | strTestModeResults = sprintf('%s\n%*s: "%s"', strTestModeResults, intPrintWidth, 'Ignore directories', strIgnoreDirs);
137 | strTestModeResults = sprintf('%s\n%*s: "%s"', strTestModeResults, intPrintWidth, 'addpath() mode', strAddpathMode);
138 | strTestModeResults = sprintf('%s\n%*s: "%s"', strTestModeResults, intPrintWidth, 'Reverse recurse remove directories', strRevRecurseDirs);
139 | disp(strTestModeResults);
140 | end
141 |
142 | %Don't print the MATLAB warning if remove path string is not found
143 | if blnRemDirs, warning('off', 'MATLAB:rmpath:DirNotFound'); end
144 |
145 | %Build the list of directories
146 | caAddRemDirs = {};
147 | [caAddRemDirs] = addpath_recursively(caAddRemDirs, strStartDir, caStrsIgnoreDirs, strXorIntAddpathMode, blnRemDirs,blnDebug);
148 |
149 | %Remove or add the directory from the search path
150 | if blnRemDirs
151 | if blnDebug, fprintf('"%s", removing from search path ...', strStartDir); end
152 | rmpath(caAddRemDirs{:})
153 | else
154 | if blnDebug, fprintf('"%s", adding to search path ...', strStartDir); end
155 | addpath(caAddRemDirs{:}, strXorIntAddpathMode);
156 | end
157 |
158 | %Restore the warning state for rmpath
159 | if blnRemDirs, warning('on', 'MATLAB:rmpath:DirNotFound'); end
160 |
161 | end % function addpath_recurse
162 | %--------------------------------------------------------------------------
163 |
164 | %--------------------------------------------------------------------------
165 | function [caAddRemDirs] = addpath_recursively(caAddRemDirs, strStartDir, caStrsIgnoreDirs, strXorIntAddpathMode, blnRemDirs, blnDebug)
166 | %Note:Don't need to check input arguments, because caller already has.
167 |
168 | %Add this directory to the add/remove path list
169 | caAddRemDirs = [caAddRemDirs,strStartDir];
170 |
171 | strFileSep = filesep();
172 | %Get list of directories beneath the specified directory, this two-step process is faster.
173 | if ispc
174 | saSubDirs = dir(sprintf('%s%s%s', strStartDir, strFileSep, '*.'));
175 | else
176 | saSubDirs = dir(strStartDir);
177 | end
178 | saSubDirs = saSubDirs([saSubDirs.isdir]); %Handles files without extensions that otherwise pass through previous filter
179 |
180 | %Loop through the directory list and recursively call this function.
181 | for intDirIndex = 1 : length(saSubDirs)
182 | strThisDirName = saSubDirs(intDirIndex).name;
183 | blnIgnoreDir = any(strcmpi(strThisDirName, { 'private', 'CVS', '.', '..', caStrsIgnoreDirs{:} }));
184 | blnDirBegins = any(strncmp(strThisDirName, {'@', '.'}, 1));
185 | if ~(blnIgnoreDir || blnDirBegins)
186 | strThisStartDir = sprintf('%s%s%s', strStartDir, strFileSep, strThisDirName);
187 | if blnDebug, fprintf('"%s", recursing ...', strThisStartDir); end
188 | [caAddRemDirs] = addpath_recursively(caAddRemDirs, strThisStartDir, caStrsIgnoreDirs, strXorIntAddpathMode, blnRemDirs, blnDebug);
189 | end
190 | end % for each directory.
191 |
192 | end % function addpath_recursively
193 | %--------------------------------------------------------------------------
194 | %__END__
195 |
--------------------------------------------------------------------------------
/3rd_party/addpath/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009, Anthony Kendall
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/3rd_party/sfigure.m:
--------------------------------------------------------------------------------
1 | % SFIGURE Create figure window (minus annoying focus-theft).
2 | %
3 | % Usage is identical to figure.
4 | %
5 | % Daniel Eaton, 2005
6 | % JSS3 2012.5.16 : cleaned up the format.
7 | %% See also "help figure"
8 | function h = sfigure(h)
9 | % debug
10 | %'sfigure!'
11 | %keyboard;
12 |
13 |
14 | % functionality
15 | if nargin>=1
16 | if ishandle(h)
17 | set(0, 'CurrentFigure', h);
18 | else
19 | h = figure(h);
20 | end
21 | else
22 | h = figure;
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/3rd_party/uninit/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011, James Tursa
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/3rd_party/uninit/uninit.m:
--------------------------------------------------------------------------------
1 | % UNINIT returns an unitialized array of specified size and class.
2 | %*************************************************************************************
3 | %
4 | % MATLAB (R) is a trademark of The Mathworks (R) Corporation
5 | %
6 | % Function: uninit
7 | % Filename: uninit.c
8 | % Programmer: James Tursa
9 | % Version: 1.00
10 | % Date: May 03, 2011
11 | % Copyright: (c) 2011 by James Tursa, All Rights Reserved
12 | %
13 | % Change Log:
14 | % 2011/May/03 --> 1.00, Initial Release
15 | %
16 | % This code uses the BSD License:
17 | %
18 | % Redistribution and use in source and binary forms, with or without
19 | % modification, are permitted provided that the following conditions are
20 | % met:
21 | %
22 | % * Redistributions of source code must retain the above copyright
23 | % notice, this list of conditions and the following disclaimer.
24 | % * Redistributions in binary form must reproduce the above copyright
25 | % notice, this list of conditions and the following disclaimer in
26 | % the documentation and/or other materials provided with the distribution
27 | %
28 | % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 | % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32 | % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 | % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 | % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 | % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 | % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 | % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 | % POSSIBILITY OF SUCH DAMAGE.
39 | %
40 | % Building:
41 | %
42 | % UNINIT is typically self building. That is, the first time you call UNINIT,
43 | % the uninit.m file recognizes that the mex routine needs to be compiled and
44 | % then the compilation will happen automatically. UNINIT uses the undocumented
45 | % MATLAB API function mxCreateUninitNumericMatrix. It has been tested in PC
46 | % versions R2008b through R2011a, but may not work in future versions of MATLAB.
47 | %
48 | % Syntax (nearly identical to the ZEROS function)
49 | %
50 | % B = uninit
51 | % B = uninit(n)
52 | % B = uninit(m,n)
53 | % B = uninit([m n])
54 | % B = uninit(m,n,p,...)
55 | % B = uninit([m n p ...])
56 | % B = uninit(size(A))
57 | % B = uninit(m, n,...,classname)
58 | % B = uninit([m,n,...],classname)
59 | % B = uninit(m, n,...,complexity)
60 | % B = uninit([m,n,...],complexity)
61 | % B = uninit(m, n,...,classname,complexity)
62 | % B = uninit([m,n,...],classname,complexity)
63 | %
64 | % Description
65 | %
66 | % B = uninit
67 | % Returns a 1-by-1 scalar uninitialized value.
68 | %
69 | % B = uninit(n)
70 | % Returns an n-by-n matrix of uninitialized values. An error message
71 | % appears if n is not a scalar.
72 | %
73 | % B = uninit(m,n) or B = uninit([m n])
74 | % Returns an m-by-n matrix of uninitialized values.
75 | %
76 | % B = uninit(m,n,p,...) or B = uninit([m n p ...])
77 | % Returns an m-by-n-by-p-by-... array of uninitialized values. The
78 | % size inputs m, n, p, ... should be nonnegative integers. Negative
79 | % integers are treated as 0.
80 | %
81 | % B = uninit(size(A))
82 | % Returns an array the same size as A consisting of all uninitialized
83 | % values.
84 | %
85 | % If any of the numeric size inputs are empty, they are taken to be 0.
86 | %
87 | % The optional classname argument can be used with any of the above.
88 | % classname is a string specifying the data type of the output.
89 | % classname can have the following values:
90 | % 'double', 'single', 'int8', 'uint8', 'int16', 'uint16',
91 | % 'int32', 'uint32', 'int64', 'uint64', 'logical', or 'char'.
92 | % (Note: 'logical' and 'char' are not allowed in the ZEROS function)
93 | % The default classname is 'double'.
94 | %
95 | % The optional complexity argument can be used with any of the above.
96 | % complexity can be 'real' or 'complex', except that 'logical' and 'char'
97 | % outputs cannot be complex. (this option not allowed in the ZEROS function)
98 | % The default complexity is 'real'.
99 | %
100 | % UNINIT is very similar to the ZEROS function, except that UNINIT returns
101 | % an uninitialized array instead of a zero-filled array. Thus, UNINIT is
102 | % faster than the ZEROS function for large size arrays. Since the return
103 | % variable is uninitialized, the user must take care to assign values to
104 | % the elements before using them. UNINIT is useful for preallocation of an
105 | % array where you know the elements will be assigned values before using them.
106 | %
107 | % Example
108 | %
109 | % x = uninit(2,3,'int8');
110 | %
111 | %***************************************************************************/
112 |
113 | function varargout = uninit(varargin)
114 | fname = 'uninit';
115 | disp(' ');
116 | disp(['Detected that the mex routine for ' fname ' is not yet built.']);
117 | disp('Attempting to do so now ...');
118 | disp(' ');
119 | try
120 | mname = mfilename('fullpath');
121 | catch
122 | mname = fname;
123 | end
124 | cname = [mname '.c'];
125 | if( isempty(dir(cname)) )
126 | disp(['Cannot find the file ' fname '.c in the same directory as the']);
127 | disp(['file ' fname '.m. Please ensure that they are in the same']);
128 | disp('directory and try again. The following file was not found:');
129 | disp(' ');
130 | disp(cname);
131 | disp(' ');
132 | error(['Unable to compile ' fname '.c']);
133 | else
134 | disp(['Found file ' fname '.c in ' cname]);
135 | disp(' ');
136 | disp('Now attempting to compile ...');
137 | disp('(If prompted, please press the Enter key and then select any C/C++');
138 | disp('compiler that is available, such as lcc.)');
139 | disp(' ');
140 | disp(['mex(''' cname ''',''-output'',''',mname,''')']);
141 | disp(' ');
142 | try
143 | mex(cname,'-output',mname);
144 | disp([ fname ' mex build completed ... you may now use ' fname '.']);
145 | disp(' ');
146 | catch
147 | disp(' ');
148 | error(['Unable to compile ' fname ' ... Contact author.']);
149 | end
150 | [varargout{1:nargout}] = uninit(varargin{:});
151 | end
152 | end
153 |
--------------------------------------------------------------------------------
/3rd_party/uninit/uninit.mexa64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jsupancic/SPLTT-Release/40c1723b7958ea3068c37effa5d9f3d4edf4f426/3rd_party/uninit/uninit.mexa64
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | To actually get this beast to run on your computer, you'll probably have to
2 | edit some of the matlab files in the config/ subdirectory.
3 | (1) config/datapath.m should return the path where you have your videos stored.
4 | The path should point to a directory which includes a subdirectory for each video.
5 | E.g. $(datapath)/tiger2/.
6 | Each subdirectory should contain files with ground truth labelings and images similar
7 | to what MIL-Track uses.
8 | As an example, see my track-data.zip file.
9 | (2) cluster_ctl is called like so cluster_ctl('on',...) or cluster_ctl('off',...)
10 | to enable or disable the matlab pool. I have three pools, with different characteristics,
11 | available to me so this function, heuristically, selects the best one. Depending on what
12 | type of MATLAB pools you have, you'll need to rewrite this function. The simplest option
13 | would be to call "matlabpool open" when called with "on" and "matlabpool close" when
14 | called with "off".
15 | (3) You should be able to compile by simplying calling "compile.m". I've tested this on Linux
16 | and it should work on other OSs... I welcome patches.
17 | (4) config/cfg.m : lets you stitch many of the parameters of the tracker. Of particular
18 | interest will be the option 'tmp_dir'. You'll want to point this to an empty directory
19 | which is writable. It is used for caching results.
20 |
21 | Then, you "should" be able to run it with a command similar to the following:
22 | addpath(genpath('.')); matlab_init('coke11'); track = track_online('coke11');
23 |
24 | Alternatively, you might just use track_tbd('coke11'); which doesn't do any learning (after
25 | the first frame) or use a motion model. It is much faster and still performs quite well.
26 |
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SPLTT-Release
2 | =============
3 |
4 | The Release Code for our CVPR 2013 Submission "Self-paced learning for long-term tracking".
--------------------------------------------------------------------------------
/compile.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-11
2 | % rebuild the compiled components
3 | function compile()
4 | % compile TLD's LK module.
5 | addpath('3rd_party/TLD/');
6 |
7 | % Compile mex files
8 | % (a) mex version of features.m
9 | % (b) mex version of matlab's image resize
10 | % (c) QP solver
11 | mex CXXFLAGS="-pedantic -Werror -I mex/ -O3 \$CXXFLAGS" detection/features_c.cc
12 | mex CXXFLAGS="-pedantic -Werror -I mex/ -O3 \$CXXFLAGS" detection/mex_resize.cc
13 | mex CXXFLAGS="-pedantic -Werror -I mex/ -O3 \$CXXFLAGS" detection/reduce.cc;
14 | mex CXXFLAGS="-pedantic -Werror -I mex/ -O3 \$CXXFLAGS" detection/nms_c.cc
15 | mex CXXFLAGS="-pedantic -Werror -I mex/ -O3 \$CXXFLAGS" -g -O -largeArrayDims qp/qp_one_c.cc
16 | mex CXXFLAGS="-pedantic -Werror -I mex/ -O3 \$CXXFLAGS" track_dp/dynprog_chain.cc
17 | lkcompile;
18 |
19 | % compile hashMat which requires openssl
20 | [void,args] = unix(['pkg-config --cflags --libs ' ...
21 | 'openssl'])
22 | cmd = sprintf('mex %s -g video/hashMat.cc -O %s','CXXFLAGS="-pedantic -Werror -I mex/ -O3 \$CXXFLAGS"',args);
23 | eval(cmd);
24 | end
25 |
--------------------------------------------------------------------------------
/config/cfg.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-5-30
2 | % function which returns configuration information
3 | function p = cfg(option)
4 | if strcmp(option,'correct_overlap')
5 | p = .25;
6 | elseif strcmp(option,'tmp_dir')
7 | p = '~/tmp/matlabTrack/';
8 | elseif strcmp(option,'sample_negatives')
9 | % sample some negatives from around the positive
10 | % rather than search over all possible negatives.
11 | p = 0;
12 | elseif strcmp(option,'C')
13 | p = .1; % default is .1;
14 | elseif strcmp(option,'cluster_name')
15 | p = 'wildHOG';
16 | elseif strcmp(option,'dp_min_time_occluded')
17 | p = 25;
18 | elseif strcmp(option,'use_lk')
19 | p = 1;
20 | elseif strcmp(option,'cost_dp_lcl');
21 | % this is meaningless legacy option
22 | p = 1;
23 | else
24 | fprintf('bad option name\n');
25 | assert(false);
26 | end
27 | end
--------------------------------------------------------------------------------
/config/cluster_ctl.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.6.15
2 | % function to turn the cluster on or off.
3 | % jobDesc: small, large, local (largest on one machine)
4 | % This file has to be tuned to *your* computational resources.
5 | %
6 | % This simplest way to configure this is to just use a single
7 | % parallel pool, in which case you just want to do
8 | % "matlabpool open" when option is "on"
9 | % "matlabpool close" when option is "off"
10 | %
11 | % For me,
12 | % "small" opens a small 8 to 12 processor pool using parallel
13 | % MATLAB toolbox.
14 | % "local" opens a local pool of maximum size 48 cores on one
15 | % machine using the distributed toolbox.
16 | % "large" opens a multi-machine distributed pool. This may be
17 | % undesirable for some tasks because (1) this pool can become a
18 | % bottleneck and (2) distributing data over the network is slow.
19 | function on = cluster_ctl(option,jobDesc,cores)
20 | % NOP on a worker...
21 | if ~isempty(getCurrentTask) || ~usejava('jvm')
22 | return
23 | end
24 |
25 | % default arguments
26 | if nargin < 2
27 | jobDesc = 'large';
28 | end
29 | if nargin < 3
30 | cores = inf;
31 | end
32 |
33 | % don't give the client more cores than it requested.
34 | if strcmp(option,'on')
35 | matlabpool open;
36 | elseif strcmp(option,'off') && matlabpool('size') > 0
37 | matlabpool close;
38 | elseif strcmp(option,'killall')
39 | matlabpool close;
40 | end
41 | end
42 |
43 |
--------------------------------------------------------------------------------
/config/datapath.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012-5-29
2 | % define the global data storage location
3 | function dp = datapath()
4 | HOSTNAME = getenv('HOSTNAME');
5 |
6 | if strcmp(HOSTNAME,'wildHOG')
7 | HOME = '/home/jsupanci/';
8 | else
9 | HOME = getenv('HOME');
10 | end
11 |
12 | dp = [HOME '/workspace/data/tracking/'];
13 | %dp
14 | end
15 |
--------------------------------------------------------------------------------
/config/matlab_init.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-5-15
2 | % function to configure MATLAB for my code to run.
3 | function [model,Jpos,C] = matlab_init(vidName)
4 | % don't re-initialize unless we are just starting up or
5 | % switching videos.
6 | global G_VID_NAME;
7 | if strcmp(G_VID_NAME,vidName) && nargout < 1
8 | % already initialized
9 | return;
10 | end
11 | G_VID_NAME = vidName;
12 |
13 | global G_HOME;
14 | G_HOME = getenv('HOME')
15 |
16 | % model details...
17 | global ORI_BINS;
18 | ORI_BINS = 18;
19 |
20 | % where to save stuff?
21 | global G_LOG_PREFIX;
22 | G_LOG_PREFIX = [cfg('tmp_dir') date() num2str(now()) ...
23 | '-' vidName '-'];
24 |
25 | % compile?
26 | compile();
27 |
28 | % clear the display
29 | format compact;
30 | %close all;
31 | lk(0);
32 | % the code uses a random number generator in qp_one.m
33 | % it is important that results be reproducible.
34 | if exist('rng') == 2
35 | rng(09221986,'twister');
36 | else
37 | rand('seed',09221986);
38 | end
39 | if hasDisplay()
40 | % configure the image processing toolbox
41 | iptsetpref('ImshowInitialMagnification', 'fit');
42 | % Don't open to many windows...
43 | set(0,'DefaultFigureWindowStyle','docked');
44 | end
45 | % configure the paths
46 | setpath();
47 | % protect against crashes without explanation...
48 | dbstop if error;
49 |
50 | % (a) Initialize model
51 | % (b) Train linear SVM with dual coordinate descent
52 | % (c) Run model on test images
53 | if nargout >= 1
54 | [model,Jpos,C] = genModel(vidName,nan);
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/config/setpath.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.6.15
2 | % configure the paths...
3 | function setpath(force)
4 | if nargin < 1
5 | force = 0;
6 | end
7 |
8 | fprintf('+setpath\n');
9 | persistent paths_set;
10 | if isempty(paths_set) || force
11 | restoredefaultpath
12 | addpath(genpath('./3rd_party'));
13 | addpath_recurse('.','','end');
14 | paths_set = 1;
15 | end
16 | fprintf('-setpath\n');
17 | end
18 |
--------------------------------------------------------------------------------
/detection/cost_lcl_tsvm.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012-5-30
2 | % the transductive local cost computation
3 | function ei = cost_lcl_tsvm(model,vidName,frameIter,k_det,pos,neg)
4 | % dissallow training rectangles larger than the image.
5 | imsz = rect_size(rect_image(get_frame(vidName,frameIter)));
6 | dtsz = rect_size(k_det);
7 | if any(dtsz >= imsz)
8 | ei = inf;
9 | return;
10 | end
11 |
12 | if nargin < 5
13 | pos = 1;
14 | end
15 | if nargin < 6
16 | neg = 1;
17 | end
18 |
19 | ub0 = model.qp.ub;
20 | lb0 = model.qp.lb;
21 | modelPrime = updateModel(model,model.Jpos);
22 | modelPrime = modelPrime.train_one(vidName,get_frame(vidName,frameIter),...
23 | rectKtoB(k_det),pos,neg);
24 | %keyboard;
25 | %[modelPrime.ub, ub0, modelPrime.lb, lb0]
26 | % UB is an estimate, LB is correct
27 | ei = max(modelPrime.qp.lb-lb0,0);
28 | if gt_occluded(k_det)
29 | % add a 'fake' occluded example.
30 | ei = ei + model.qp.C*2; % 2 = worst case, 1 =
31 | % average case, 0 = best case.
32 | end
33 | assert(~isnan(ei));
34 | end
35 |
--------------------------------------------------------------------------------
/detection/feat_code.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012-6-1
2 | % Convert string to code number
3 | function code = feat_code(featName)
4 | if strcmp(featName,'color')
5 | code = 2;
6 | elseif strcmp(featName,'hog')
7 | code = 1;
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/detection/featpyramid.m:
--------------------------------------------------------------------------------
1 | function [feat, scale] = featpyramid(im, sbin, interval,f_features)
2 | if nargin < 4
3 | f_features = @(scaled,sbin) features(scaled,sbin,feat_code('hog'));
4 | end
5 | if nargin >= 4 && isstr(f_features)
6 | f_features = @(scaled,sbin) features(scaled,sbin,feat_code(f_features));
7 | end
8 |
9 | % [feat, scale] = featpyramid(im, sbin, interval);
10 | % Compute feature pyramid.
11 | %
12 | % sbin is the size of a HOG cell - it should be even.
13 | % interval is the number of scales in an octave of the pyramid.
14 | % feat{i} is the i-th level of the feature pyramid.
15 | % scale(i) is the scaling factor used for the i-th level.
16 | % feat{i+interval} is computed at exactly half the resolution of feat{i}.
17 |
18 | sc = 2^(1/interval);
19 | imsize = [size(im, 1) size(im, 2)];
20 | max_scale = 1 + floor(log(min(imsize)/(5*sbin))/log(sc));
21 | feat = cell(max_scale, 1);
22 | scale = zeros(max_scale, 1);
23 |
24 | % our resize function wants floating point values
25 | im = double(im);
26 | for i = 1:interval
27 | %im
28 | sf = 1/sc^(i-1);
29 | scaled = mex_resize(im, sf);
30 | % "first" 2x interval
31 | feat{i} = f_features(scaled, sbin);
32 | scale(i) = sc^(i-1);
33 | % remaining interals
34 | for j = i+interval:interval:max_scale
35 | scaled = reduce(scaled);
36 | feat{j} = f_features(scaled, sbin);
37 | scale(j) = 2 * scale(j-interval);
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/detection/feature_get_for_svm.m:
--------------------------------------------------------------------------------
1 | % JSS3 function to get the HoG feature describing
2 | % a region in the format the SVM requires.
3 | function [feat,featIm] = feature_get_for_svm(model,im,b_bb)
4 | if ~check_rect_size(rectBtoK(b_bb),rect_image(im))
5 | error('logicError','b_bb is to large');
6 | end
7 |
8 | % drop parts of the bounding box multiple of model.sbin?
9 | %bb_width = b_bb(3);
10 | %bb_height = b_bb(4);
11 | % bb_excess_width = mod(bb_width,model.sbin);
12 | % bb_excess_height = mod(bb_height,model.sbin);
13 | % b_bb(1) = b_bb(1) - bb_excess_width/2;
14 | % b_bb(2) = b_bb(2) - bb_excess_height/2;
15 | % b_bb(3) = b_bb(3) - bb_excess_width;
16 | % b_bb(4) = b_bb(4) - bb_excess_height;
17 |
18 | % get the template...
19 | k_bb = rectBtoK(b_bb);
20 | % the next line changes -.6637 to -.8861 when
21 | % -.8918 is the goal. An improvement, a different
22 | % resize algorithm may account for the rest...
23 | dbg_im = im;
24 | crop_bb = [(k_bb(1)-model.sbin) (k_bb(2)-model.sbin) ...
25 | (k_bb(3)+model.sbin) (k_bb(4)+model.sbin)];
26 | im = imcropr(im,crop_bb);
27 | nx = model.nx;
28 | ny = model.ny;
29 | na = model.nx .* model.ny;
30 | imx = size(im,2);
31 | imy = size(im,1);
32 | im_area = imx .* imy;
33 | sbins = round(sqrt(im_area/na));
34 | im = imresize(im,[(model.ny+2)*model.sbin,(model.nx+2)*model.sbin]);
35 |
36 | % get the feature
37 | featIm = features(double(im),model.sbin,feat_code('hog'));
38 | %keyboard;
39 |
40 | zSize = size(model.w,3); % throw out extra components (work
41 | % with color or not).
42 | feat = featIm(:,:,1:zSize);
43 | feat = [feat(:); model.sb];
44 |
45 | if isfield(model,'qp')
46 | assert(~isfield(model.qp,'x') || size(model.qp.x,1) == numel(feat))
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/detection/features.m:
--------------------------------------------------------------------------------
1 | function feat = features(im,sbin,featCode)
2 | % res = features(im,sbin)
3 | % Let [imy,imx] = size(impatch)
4 | % -Result will be (imy/8-1) by (imx/8-1) by (4+9) for
5 | % 9 orientation bins and 4 normalizations for every 8x8 pixel-block
6 | % -This won't produce exact same results as features.cc because this
7 | % uses hard-binning rather than soft binning
8 | memo = [cfg('tmp_dir') 'features/' ...
9 | 'imHash=' hashMat(im) ...
10 | 'sbin=' num2str(sbin) ...
11 | 'featCode=' num2str(featCode) '.mat'];
12 | MEMO = 0;
13 | if exist(memo,'file') && MEMO
14 | load(memo,'feat');
15 | return;
16 | end
17 |
18 | MEX = 1;
19 | if MEX
20 | feat = features_c(im,sbin,featCode);
21 | if MEMO
22 | save(memo,'feat');
23 | end
24 | return;
25 | end
26 |
27 | % Crop/pad image to make its size a multiple of sbin
28 | [ty,tx,tz] = size(im);
29 | imy = round(ty/sbin)*sbin;
30 | if imy > ty,
31 | im = padarray(im,[imy-ty 0 0],'post');
32 | elseif imy < ty,
33 | im = im(1:imy,:,:);
34 | end
35 | imx = round(tx/sbin)*sbin;
36 | if imx > tx,
37 | im = padarray(im,[0 imx-tx 0],'post');
38 | elseif imx < tx,
39 | im = im(:,1:imx,:);
40 | end
41 | im = double(im);
42 | n = (imy-2)*(imx-2);
43 |
44 | % Pick the strongest gradient across color channels
45 | dy = im(3:end,2:end-1,:) - im(1:end-2,2:end-1,:); dy = reshape(dy,n,3);
46 | dx = im(2:end-1,3:end,:) - im(2:end-1,1:end-2,:); dx = reshape(dx,n,3);
47 | len = dx.^2 + dy.^2;
48 | [len,I] = max(len,[],2);
49 | len = sqrt(len);
50 | I = sub2ind([n 3],[1:n]',I);
51 | dy = dy(I); dx = dx(I);
52 |
53 | % Snap each gradient to an orientation
54 | [uu,vv] = pol2cart([0:pi/9:pi-.01],1);
55 | v = dy./(len+eps); u = dx./(len+eps);
56 | [dummy,I] = max(abs(u(:)*uu + v(:)*vv),[],2);
57 |
58 | % Spatially bin orientation channels
59 | ssiz = [imy imx]/sbin;
60 | feat = zeros(prod(ssiz), 9);
61 | for i = 1:9,
62 | tmp = reshape(len.*(I == i),imy-2,imx-2);
63 | tmp = padarray(tmp,[1 1]);
64 | feat(:,i) = sum(im2col(tmp,[sbin sbin],'distinct'))';
65 | end
66 |
67 | % Compute features for all overlapping 2x2 windows
68 | ind = reshape(1:prod(ssiz),ssiz);
69 | ind = im2col(ind,[2 2])';
70 | n = size(ind,1);
71 | feat = reshape(feat(ind,:),n,4*9);
72 |
73 | % Normalize and clip to .2
74 | nn = sqrt(sum(feat.^2,2)) + eps;
75 | feat = bsxfun(@times,feat,1./nn);
76 | feat = min(feat,.2);
77 |
78 | % Re-align features so that 4*9 values refer to same 8x8 spatial bin
79 | % Take projections along 4 normalization regions and 9 orientations
80 | feat = reshape(feat,[ssiz-1 4 9]);
81 | feat = cat(3,feat(2:end,2:end,1,:),feat(1:end-1,2:end,2,:),...
82 | feat(2:end,1:end-1,3,:),feat(1:end-1,1:end-1,4,:));
83 | feat = cat(3,.5*reshape(sum(feat,3),[ssiz-2 9]),.2357*sum(feat,4));
84 |
--------------------------------------------------------------------------------
/detection/gt_filter_detections.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-03-24
2 | % Filter out the detections which overlap the ground
3 | % truth
4 | function [box,feat] = gt_filter_detections(box,feat,gt)
5 | % filter out the positives if any
6 | if(~gt_occluded(gt))
7 | width = gt(3);
8 | height = gt(4);
9 | halfThePixels = .5*width*height;
10 |
11 | rectB = rectKtoB(box);
12 | posneg = rectint(rectB,gt) < halfThePixels;
13 | box = box(posneg,:);
14 | feat = feat(:,posneg);
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/detection/mex_resize.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "mex.h"
5 |
6 | #ifndef bzero(s,n)
7 | #define bzero(s,n) memset ((s), 0, (n))
8 | #endif
9 | #ifndef round(x)
10 | #define round(x) (x<0?ceil((x)-0.5):floor((x)+0.5))
11 | #endif
12 |
13 | // struct used for caching interpolation values
14 | struct alphainfo {
15 | int si, di;
16 | double alpha;
17 | };
18 |
19 | // copy src into dst using pre-computed interpolation values
20 | void alphacopy(double *src, double *dst, struct alphainfo *ofs, int n) {
21 | struct alphainfo *end = ofs + n;
22 | while (ofs != end) {
23 | dst[ofs->di] += ofs->alpha * src[ofs->si];
24 | ofs++;
25 | }
26 | }
27 |
28 | // resize along each column
29 | // result is transposed, so we can apply it twice for a complete resize
30 | void resize1dtran(double *src, int sheight, double *dst, int dheight,
31 | int width, int chan) {
32 | double scale = (double)dheight/(double)sheight;
33 | double invscale = (double)sheight/(double)dheight;
34 |
35 | // we cache the interpolation values since they can be
36 | // shared among different columns
37 | int len = (int)ceil(dheight*invscale) + 2*dheight;
38 | alphainfo*ofs = static_cast(calloc(len,sizeof(alphainfo)));
39 | int k = 0;
40 | for (int dy = 0; dy < dheight; dy++) {
41 | double fsy1 = dy * invscale;
42 | double fsy2 = fsy1 + invscale;
43 | int sy1 = (int)ceil(fsy1);
44 | int sy2 = (int)floor(fsy2);
45 |
46 | if (sy1 - fsy1 > 1e-3) {
47 | assert(k < len);
48 | //assert(sy-1 >= 0);
49 | ofs[k].di = dy*width;
50 | ofs[k].si = sy1-1;
51 | ofs[k++].alpha = (sy1 - fsy1) * scale;
52 | }
53 |
54 | for (int sy = sy1; sy < sy2; sy++) {
55 | assert(k < len);
56 | assert(sy < sheight);
57 | ofs[k].di = dy*width;
58 | ofs[k].si = sy;
59 | ofs[k++].alpha = scale;
60 | }
61 |
62 | if (fsy2 - sy2 > 1e-3) {
63 | assert(k < len);
64 | assert(sy2 < sheight);
65 | ofs[k].di = dy*width;
66 | ofs[k].si = sy2;
67 | ofs[k++].alpha = (fsy2 - sy2) * scale;
68 | }
69 | }
70 |
71 | // resize each column of each color channel
72 | bzero(dst, chan*width*dheight*sizeof(double));
73 | for (int c = 0; c < chan; c++) {
74 | for (int x = 0; x < width; x++) {
75 | double *s = src + c*width*sheight + x*sheight;
76 | double *d = dst + c*width*dheight + x;
77 | alphacopy(s, d, ofs, k);
78 | }
79 | }
80 |
81 | free(ofs);
82 | }
83 |
84 | // main function
85 | // takes a double color image and a scaling factor
86 | // returns resized image
87 | mxArray *resize(const mxArray *mxsrc, const mxArray *mxscale) {
88 | double *src = (double *)mxGetPr(mxsrc);
89 | const int *sdims = mxGetDimensions(mxsrc);
90 | if (mxGetNumberOfDimensions(mxsrc) != 3 ||
91 | mxGetClassID(mxsrc) != mxDOUBLE_CLASS)
92 | mexErrMsgTxt("image doens't have 3 dimensions (x,y,rgb) or isn't double");
93 |
94 | double scale = mxGetScalar(mxscale);
95 | if (scale > 1)
96 | mexErrMsgTxt("Invalid scaling factor");
97 |
98 | int ddims[3];
99 | ddims[0] = (int)round(sdims[0]*scale);
100 | ddims[1] = (int)round(sdims[1]*scale);
101 | ddims[2] = sdims[2];
102 | mxArray *mxdst = mxCreateNumericArray(3, ddims, mxDOUBLE_CLASS, mxREAL);
103 | double *dst = (double *)mxGetPr(mxdst);
104 |
105 | double *tmp = (double *)mxCalloc(ddims[0]*sdims[1]*sdims[2], sizeof(double));
106 | resize1dtran(src, sdims[0], tmp, ddims[0], sdims[1], sdims[2]);
107 | resize1dtran(tmp, sdims[1], dst, ddims[1], ddims[0], sdims[2]);
108 | mxFree(tmp);
109 |
110 | return mxdst;
111 | }
112 |
113 | // matlab entry point
114 | // dst = resize(src, scale)
115 | // image should be color with double values
116 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
117 | if (nrhs != 2)
118 | mexErrMsgTxt("Wrong number of inputs");
119 | if (nlhs != 1)
120 | mexErrMsgTxt("Wrong number of outputs");
121 | plhs[0] = resize(prhs[0], prhs[1]);
122 | }
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/detection/nms.m:
--------------------------------------------------------------------------------
1 | % res = nms(boxes,overlap)
2 | % Greedily removes blobs that intersect by more than overlap
3 | function res = nms(boxes,overlap,scalex,scaley)
4 | boxes = shrink(boxes,scalex,scaley);
5 |
6 | res = nms_c(boxes,overlap);
7 | res = flipdim(sortrows(res,5),1);
8 | return;
9 |
10 | if isempty(boxes),
11 | res = [];
12 | else
13 | x1 = boxes(:,1);
14 | y1 = boxes(:,2);
15 | x2 = boxes(:,3);
16 | y2 = boxes(:,4);
17 | r = boxes(:,5);
18 | area = (x2-x1+1) .* (y2-y1+1);
19 |
20 | [vals,I] = sort(r);
21 | pick = [];
22 | while ~isempty(I),
23 | last = length(I);
24 | i = I(last);
25 | pick = [pick; i];
26 | suppress = [last];
27 | for pos = 1:last-1,
28 | j = I(pos);
29 | xx1 = max(x1(i), x1(j));
30 | yy1 = max(y1(i), y1(j));
31 | xx2 = min(x2(i), x2(j));
32 | yy2 = min(y2(i), y2(j));
33 | w = xx2-xx1+1;
34 | h = yy2-yy1+1;
35 | if w > 0 && h > 0
36 | % compute overlap
37 | o = w * h / area(j);
38 | % VOC criterion for overlap
39 | % o = w*h/ (area(i) + area(j) - w*h);
40 | if o > overlap
41 | suppress = [suppress; pos];
42 | end
43 | end
44 | end
45 | I(suppress) = [];
46 | end
47 | res = boxes(pick,:);
48 | end
49 |
50 | function box = shrink(box,sx,sy)
51 | % box = shrink(box,scalex,scaley)
52 |
53 | x1 = box(:,1);
54 | y1 = box(:,2);
55 | x2 = box(:,3);
56 | y2 = box(:,4);
57 | w = x2-x1+1;
58 | h = y2-y1+1;
59 |
60 | x1 = x1 + (w-1)/2 - (w*sx-1)/2;
61 | y1 = y1 + (h-1)/2 - (h*sy-1)/2;
62 | x2 = x1 + w*sx - 1;
63 | y2 = y1 + h*sy - 1;
64 |
65 | box(:,1:4) = [x1 y1 x2 y2];
66 |
--------------------------------------------------------------------------------
/detection/nms_c.cc:
--------------------------------------------------------------------------------
1 | /**
2 | * JSS3 2012-5-28
3 | * Do greedy non-maximumal suppression
4 | **/
5 |
6 | #include "mex.h"
7 | #include "math.h"
8 | #include
9 | #include
10 | #include "../mex/compat.h"
11 |
12 | static const mwSize boxWidth = 5;
13 |
14 | using std::numeric_limits;
15 | using std::vector;
16 | using std::min;
17 | using std::max;
18 |
19 | static int maxUnsuppressed(
20 | vector&suppressed,double*boxes,
21 | int nBoxes,vector&used)
22 | {
23 | double max = -numeric_limits::infinity();
24 | int maxIdx = -1;
25 | for(int iter = 0; iter < nBoxes; iter++)
26 | {
27 | double max_rp = *(boxes + nBoxes*4 + iter);
28 | if(max_rp >= max && !suppressed[iter] && !used[iter])
29 | {
30 | max = max_rp;
31 | maxIdx = iter;
32 | }
33 | }
34 |
35 | return maxIdx;
36 | }
37 |
38 | void trySuppressOther(
39 | double*boxes,mwSize nBoxes, int otherIdx,
40 | double max_x1, double max_y1, double max_x2, double max_y2, double overlap,
41 | vector&suppressed)
42 | {
43 | double other_x1 = *(boxes + nBoxes*0 + otherIdx);
44 | double other_y1 = *(boxes + nBoxes*1 + otherIdx);
45 | double other_x2 = *(boxes + nBoxes*2 + otherIdx);
46 | double other_y2 = *(boxes + nBoxes*3 + otherIdx);
47 | double other_rp = *(boxes + nBoxes*4 + otherIdx);
48 | double other_wd = other_x2 - other_x1 + 1;
49 | double other_hi = other_y2 - other_y1 + 1;
50 | double other_ar = other_wd*other_hi;
51 |
52 | // intersection
53 | double xx1 = max(other_x1,max_x1);
54 | double yy1 = max(other_y1,max_y1);
55 | double xx2 = min(other_x2,max_x2);
56 | double yy2 = min(other_y2,max_y2);
57 | double w = xx2-xx1+1;
58 | double h = yy2-yy1+1;
59 |
60 | // occlusion
61 | bool max_occ = isnan(max_x1);
62 | bool other_occ = isnan(other_x1);
63 | bool occCmpat = max_occ == other_occ;
64 |
65 | double o = w*h/other_ar;
66 | if(w > 0 && h > 0 && o > overlap && occCmpat)
67 | {
68 | // mexPrintf("nms_c.cc: suppressing %d\n",otherIdx);
69 | suppressed[otherIdx] = true;
70 | // mexPrintf("nms_c.cc: suppressed %d\n",otherIdx);
71 | }
72 | }
73 |
74 | /**
75 | * MEX main...
76 | * function res = nms(boxes,overlap)
77 | **/
78 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
79 | // check arguments
80 | if (nrhs != 2)
81 | mexErrMsgTxt("Wrong number of inputs");
82 | if (nlhs != 1)
83 | mexErrMsgTxt("Wrong number of outputs");
84 |
85 | // get the input.
86 | double overlap = mxGetScalar(prhs[1]);
87 | double*boxes = mxGetPr(prhs[0]);
88 | mwSize nBoxes = mxGetM(prhs[0]);
89 |
90 | // do the computation.
91 | vector suppressed(nBoxes,false), used(nBoxes,false);
92 | int maxIter = 0;
93 | while(true)
94 | {
95 | maxIter++;
96 | // mexPrintf("nms_c.cc: maxIter = %d\n",maxIter);
97 | // find max...
98 | int maxIdx = maxUnsuppressed(suppressed,boxes,nBoxes,used);
99 | // mexPrintf("nms_c.cc: maxIdx = %d\n",maxIdx);
100 | if(maxIdx < 0)
101 | {
102 | // mexPrintf("nms_c.cc: Breaking out of calcs\n");
103 | break;
104 | }
105 | used[maxIdx] = true;
106 | // mexPrintf("nms_c.cc: starting next iteration!\n");
107 |
108 | // MATLAB data is columknwise, so incrementing by one moves us
109 | // down the current column (from row to row).
110 | double max_x1 = *(boxes + nBoxes*0 + maxIdx);
111 | double max_y1 = *(boxes + nBoxes*1 + maxIdx);
112 | double max_x2 = *(boxes + nBoxes*2 + maxIdx);
113 | double max_y2 = *(boxes + nBoxes*3 + maxIdx);
114 | double max_rp = *(boxes + nBoxes*4 + maxIdx);
115 | double max_wd = max_x2 - max_x1 + 1;
116 | double max_hi = max_y2 - max_y1 + 1;
117 | double max_ar = max_wd*max_hi;
118 |
119 | for(int otherIdx = 0; otherIdx < nBoxes; otherIdx++)
120 | {
121 | trySuppressOther(
122 | boxes,nBoxes, otherIdx,
123 | max_x1, max_y1, max_x2, max_y2, overlap,
124 | suppressed);
125 | }
126 | }
127 | // mexPrintf("nms_c.cc: calculations complete\n");
128 |
129 | // produce the output.
130 | // count the number of boxes which are used after NMS
131 | int outCt = 0;
132 | for(int iter = 0; iter < used.size(); iter++)
133 | if(used[iter])
134 | outCt++;
135 |
136 | // mexPrintf("boxCt = %d\noutCt = %d\n",nBoxes,outCt);
137 | plhs[0] = mxCreateDoubleMatrix(outCt,boxWidth,mxREAL);
138 | double* out = mxGetPr(plhs[0]);
139 | for(int iter = 0, outIter = 0; iter < used.size(); iter++)
140 | if(used[iter])
141 | {
142 | *(out + outCt*0 + outIter) = *(boxes + nBoxes*0 + iter);
143 | *(out + outCt*1 + outIter) = *(boxes + nBoxes*1 + iter);
144 | *(out + outCt*2 + outIter) = *(boxes + nBoxes*2 + iter);
145 | *(out + outCt*3 + outIter) = *(boxes + nBoxes*3 + iter);
146 | *(out + outCt*4 + outIter) = *(boxes + nBoxes*4 + iter);
147 | outIter++;
148 | }
149 | }
150 |
151 |
--------------------------------------------------------------------------------
/detection/reduce.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "mex.h"
5 |
6 | #ifndef bzero(s,n)
7 | #define bzero(s,n) memset ((s), 0, (n))
8 | #endif
9 | #ifndef round(x)
10 | #define round(x) (x<0?ceil((x)-0.5):floor((x)+0.5))
11 | #endif
12 |
13 | // reduce(im) resizes im to half its size, using a 5-tap binomial filter for anti-aliasing
14 | // (see Burt & Adelson's Laplacian Pyramid paper)
15 |
16 | // reduce each column
17 | // result is transposed, so we can apply it twice for a complete reduction
18 | void reduce1dtran(double *src, int sheight, double *dst, int dheight,
19 | int width, int chan) {
20 | // resize each column of each color channel
21 | bzero(dst, chan*width*dheight*sizeof(double));
22 | int y;
23 | double *s, *d;
24 |
25 | for (int c = 0; c < chan; c++) {
26 | for (int x = 0; x < width; x++) {
27 | s = src + c*width*sheight + x*sheight;
28 | d = dst + c*dheight*width + x;
29 |
30 | // First row
31 | *d = s[0]*.6875 + s[1]*.2500 + s[2]*.0625;
32 |
33 | for (y = 1; y < dheight-2; y++) {
34 | s += 2;
35 | d += width;
36 | *d = s[-2]*0.0625 + s[-1]*.25 + s[0]*.375 + s[1]*.25 + s[2]*.0625;
37 | }
38 |
39 | // Last two rows
40 | s += 2;
41 | d += width;
42 | if (dheight*2 <= sheight) {
43 | *d = s[-2]*0.0625 + s[-1]*.25 + s[0]*.375 + s[1]*.25 + s[2]*.0625;
44 | } else {
45 | *d = s[1]*.3125 + s[0]*.3750 + s[-1]*.2500 + s[-2]*.0625;
46 | }
47 | s += 2;
48 | d += width;
49 | *d = s[0]*.6875 + s[-1]*.2500 + s[-2]*.0625;
50 | }
51 | }
52 | }
53 |
54 | // main function
55 | // takes a double color image and a scaling factor
56 | // returns resized image
57 | mxArray *reduce(const mxArray *mxsrc) {
58 | double *src = (double *)mxGetPr(mxsrc);
59 |
60 | const int *sdims = mxGetDimensions(mxsrc);
61 | if (mxGetNumberOfDimensions(mxsrc) != 3 ||
62 | mxGetClassID(mxsrc) != mxDOUBLE_CLASS)
63 | mexErrMsgTxt("Invalid input");
64 |
65 | int ddims[3];
66 | ddims[0] = (int)round(sdims[0]*.5);
67 | ddims[1] = (int)round(sdims[1]*.5);
68 | ddims[2] = sdims[2];
69 |
70 | if (sdims[0] < 5|| sdims[1] < 5)
71 | mexErrMsgTxt("Minimum size of image is 5x5");
72 |
73 | mxArray *mxdst = mxCreateNumericArray(3, ddims, mxDOUBLE_CLASS, mxREAL);
74 | double *dst = (double *)mxGetPr(mxdst);
75 |
76 | double *tmp = (double *)mxCalloc(ddims[0]*sdims[1]*sdims[2], sizeof(double));
77 | reduce1dtran(src, sdims[0], tmp, ddims[0], sdims[1], sdims[2]);
78 | reduce1dtran(tmp, sdims[1], dst, ddims[1], ddims[0], sdims[2]);
79 | mxFree(tmp);
80 |
81 | return mxdst;
82 | }
83 |
84 | // matlab entry point
85 | // dst = resize(src, scale)
86 | // image should be color with double values
87 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
88 | if (nrhs != 1)
89 | mexErrMsgTxt("Wrong number of inputs");
90 | if (nlhs != 1)
91 | mexErrMsgTxt("Wrong number of outputs");
92 | plhs[0] = reduce(prhs[0]);
93 | }
94 |
95 | /**********
96 | d = repmat([1:6]',[1 5 3]);
97 | a = reduce(d);
98 | *********/
99 |
100 |
--------------------------------------------------------------------------------
/detection/scoreBox.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-20
2 | % get the response for a given box.
3 | function score = scoreBox(model,im,k_rect)
4 | %fprintf('+scoreBox\n');
5 | imsz = rect_size(rect_image(im));
6 | bbsz = rect_size(k_rect);
7 | sz = rect_size(k_rect);
8 | if any(bbsz > 2.*imsz)
9 | score = -1; % bad bb because it is to large.
10 | elseif gt_occluded(k_rect) || sz(1) < 2 || sz(2) < 2 ...
11 | || rect_area(k_rect) > rect_area(rect_image(im))
12 | score = -1;
13 | else
14 | %fprintf('scoreBox: getting SVM feature\n');
15 | %keyboard;
16 | feat = feature_get_for_svm(model,im,rectKtoB(k_rect));
17 | %fprintf('scoreBox: got SVM feature\n');
18 | featSz = numel(feat)-1;
19 | score = feat(1:featSz)'*model.w(1:featSz)' + model.b*model.sb;
20 | end
21 | %fprintf('-scoreBox\n');
22 | end
23 |
--------------------------------------------------------------------------------
/evalOnVids.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -x
2 |
3 | FUNC=$1
4 | INIT=$2
5 |
6 | echo "starting evaluation..."
7 | VIDS=$(ls ~/workspace/data)
8 | SUITE='coke11 david motocross tiger2 girl panda pedestrian1 sylv tiger1 volkswagen faceocc faceocc2'
9 | #SUITE='panda'
10 | MATLAB=matlab
11 | SERIAL='0'
12 |
13 | # configure our X server
14 | # Xnest still crashes randomly :-(
15 | #nohup Xnest :1 -geometry 1280x1024 &
16 | #export DISPLAY=:1
17 | #wmaker &
18 |
19 | # compile shared components
20 | #
21 | # clear existing jobs
22 | # $MATLAB -nodesktop -r "matlabpool close force; "
23 | # compile the shared components.
24 | # -nodisplay?
25 | $MATLAB -nodesktop -r "addpath(genpath('.'),'-END'); cluster_ctl('killall'); compile; exit;"
26 |
27 | # test the vids
28 | #for VID in 'volkswagen'
29 | #for VID in $VIDS
30 | for VID in $SUITE
31 | do
32 | ID="$FUNC-$VID-$(date +%Y%m%d)"
33 |
34 | if [ $SERIAL == 1 ]
35 | then
36 | SETUP="$INIT addpath(genpath('.')); cluster_ctl('on'); vidName='$VID';"
37 | else
38 | SETUP="$INIT addpath(genpath('.')); vidName='$VID';"
39 | fi
40 | RUN="track = $FUNC(vidName);"
41 | FINISH="save([cfg('tmp_dir') 'track_$ID.mat'],'vidName','track'); "
42 | F1FILE="[cfg('tmp_dir') 'f1=' num2str(f1) '_$ID.mat']"
43 | CMP_F1="f1 = score_track_file(vidName,track); save($F1FILE,'f1');"
44 | PROG="$SETUP $RUN $FINISH $CMP_F1 cluster_ctl('off'); exit;"
45 | echo $PROG
46 | #$MATLAB -nosplash -nodesktop -r '$PROG'
47 | screen -d -m -S $FUNC$VID nice -n 10 $MATLAB -nodisplay -nosplash -nodesktop -r "$PROG"
48 | sleep 5
49 | #screen -d -m -S $FUNC$VID $MATLAB -nodesktop -r "$FUNC('$VID');"
50 | done
51 |
52 | # restore the terimanl...
53 | reset
54 |
--------------------------------------------------------------------------------
/hashMat_mat.m:
--------------------------------------------------------------------------------
1 | % if you can't compile hashMat.cc
2 | % you can just use this. The caching feature
3 | % won't work properly but it's mainly usefull for
4 | % development anyway.
5 | function h = hashMat_mat(m)
6 | chars = ['a':'z' 'A':'Z' '0':'9'];
7 | idxs = randi(numel(chars),[1 32]);
8 | h = chars(idxs);
9 | end
10 |
11 |
--------------------------------------------------------------------------------
/learning/compute_tsvm_deltas.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.8.7
2 | % Simplified interface to learn_tsvm_score.
3 | function deltas = compute_tsvm_deltas(vidName,model,k_track)
4 | evalFrames = zeros(size(k_track(:,1)));
5 | [top_detections,NStates] = getDetsEst(vidName,model, ...
6 | k_track);
7 | deltas = learn_tsvm_score(evalFrames,NStates,top_detections,...
8 | vidName,model);
9 | end
10 |
--------------------------------------------------------------------------------
/learning/getDetsEst.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.7.3
2 | function [top_detections,NStates] = getDetsEst(vidName,model, ...
3 | k_track)
4 | NStates = 1;
5 | num_top_dets = min(vidLen(vidName),size(k_track,1));
6 | top_detections = cell(num_top_dets,1);
7 | for detIter = 1:numel(top_detections)
8 | top_detections{detIter} = k_track(detIter,:);
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/learning/learn_tsvm_score.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.7.31
2 | % Computes the true TSVM delta for a set of lambda.
3 | function scores = learn_tsvm_score(lambda,NStates,top_detections,...
4 | vidName,model)
5 | % try to find the result in our cache
6 | wHash = hashMat(model.w);
7 | lHash = hashMat(lambda);
8 | vidName;
9 | filename = [cfg('tmp_dir') 'learn_tsvm_score' ...
10 | vidName wHash lHash '.mat'];
11 | if exist(filename,'file')
12 | load(filename,'scores');
13 | return;
14 | end
15 |
16 | % what is the original score?
17 | ub0 = model.qp.ub;
18 | lb0 = model.qp.lb;
19 |
20 | % score matrix Frames by Detections
21 | scoresComp = inf(numel(lambda),NStates);
22 |
23 | % use the SVM objective function to, in parallel, fill the
24 | % matrix.
25 | cluster_ctl('on');
26 | spmd
27 | %setpath();
28 | progFrames = labindex:numlabs:(numel(top_detections));
29 | for frameIter = progFrames
30 | fprintf('learn_tsvm: computing scores for frame %d of %d\n',frameIter,numel(top_detections));
31 | for detectionIdx = 1:NStates
32 | cur_det = ...
33 | top_detections{frameIter}...
34 | (detectionIdx,:);
35 |
36 | if lambda(frameIter)
37 | continue;
38 | end
39 |
40 | scoresComp(frameIter,detectionIdx) = ...
41 | cost_lcl_tsvm(model,vidName,frameIter-1,cur_det);
42 | end
43 | end
44 | end
45 | fprintf('learn_tsvm_score.m: DONE\n');
46 |
47 | % collect the scores composite into a scores matrix...
48 | scores = inf(numel(lambda),NStates);
49 | for iter = 1:numel(scoresComp)
50 | subScores = scoresComp{iter};
51 | scores(subScores ~= inf) = subScores(subScores ~= inf);
52 | end
53 | cluster_ctl('off');
54 |
55 | % save to the cache
56 | save(filename,'scores');
57 | end
58 |
--------------------------------------------------------------------------------
/mex/compat.h:
--------------------------------------------------------------------------------
1 | // file which tries to add compatibility with other operating
2 | // systems (aside from Linux)
3 |
4 | #ifdef _MSC_VER
5 | // code for windows
6 | typedef __int32 int32_t;
7 | typedef unsigned __int32 uint32_t;
8 | #define isnan _isnan
9 | #else
10 | // code for Linux
11 | #include
12 | #endif
13 |
--------------------------------------------------------------------------------
/model/Model.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.7.30
2 | % I'm finally making the big change; converting the model to a
3 | % class.
4 | classdef Model
5 | properties(SetAccess = private)
6 | gt_width;
7 | gt_height;
8 | aspect;
9 | Jpos;
10 | nx;
11 | ny;
12 | nf;
13 | featType;
14 | w;
15 | b;
16 | sb;
17 | scalex;
18 | scaley;
19 | interval;
20 | sbin;
21 | sym;
22 | thresh;
23 | qp;
24 | end
25 |
26 | methods
27 | % use of this method is strongly discouraged
28 | % as it breaks encapsulation.
29 | function qp = qp_get(obj)
30 | qp = obj.qp;
31 | end
32 |
33 | % use of this method is strongly discouraged
34 | % as it breaks encapsulation.
35 | function obj = qp_set(obj,qp)
36 | obj.qp = qp;
37 | obj = updateModel(obj,obj.Jpos);
38 | end
39 |
40 | function aspect = getAspect(obj)
41 | aspect = obj.aspect;
42 | end
43 |
44 | function scalex = getScaleX(obj)
45 | scalex = obj.scalex;
46 | end
47 |
48 | function scaley = getScaleY(obj)
49 | scaley = obj.scaley;
50 | end
51 |
52 | function Jpos = getJpos(obj)
53 | Jpos = obj.Jpos;
54 | end
55 |
56 | function C = getC(obj)
57 | C = obj.qp.getC();
58 | end
59 |
60 | function qp = getQP(obj)
61 | qp = obj.qp;
62 | end
63 |
64 | function model = setThresh(model,thresh)
65 | model.thresh = thresh;
66 | end
67 |
68 | function d = detector(obj)
69 | d = Detector(obj.w,obj.thresh,obj.sbin,obj.interval,...
70 | obj.b,obj.sb,obj.scalex,obj.scaley,obj.Jpos,...
71 | obj.nx,obj.ny);
72 | end
73 |
74 | function top_detections = detect_all(obj,frames,vidName, ...
75 | NDetStates)
76 | d = obj.detector();
77 | top_detections = d.detect_all(frames,vidName,NDetStates);
78 | end
79 |
80 | function [box,feat] = detect(obj,im,model,maxdet)
81 | [box,feat] = detect(im,model,maxdet);
82 | end
83 |
84 | function h = hash(obj)
85 | h = hashMat(obj.w);
86 | end
87 |
88 | % score some boxes! Oh Yea!
89 | function score = score_box(obj,im,k_rect)
90 | boxCt = size(k_rect,1);
91 | score = zeros(boxCt,1);
92 | for iter = 1:boxCt
93 | score(iter,1) = scoreBox(obj,im,k_rect(iter,:));
94 | end
95 | end
96 |
97 | % support two different construtction methods.
98 | function obj = Model(ctor,varargin)
99 | if strcmp(ctor,'init')
100 | obj = obj.init(varargin{:});
101 | elseif strcmp(ctor,'gen')
102 | obj = obj.generate(varargin{:});
103 | elseif strcmp(ctor,'copy')
104 | obj = obj.copy(varargin{:});
105 | else
106 | error('Model::Model invalid constructor');
107 | end
108 | end
109 |
110 | function obj = copy(obj,other)
111 | props = properties(other);
112 | for iter = 1:length(props)
113 | obj.(props{iter}) = other.(props{iter});
114 | end
115 | end
116 |
117 | function model = init(model,sbins,nx,ny,Jpos,~,gt_width,gt_height)
118 | featType = 'hog';
119 |
120 | % model = initmodel(bigbox,smallbox,sbin)
121 | % Initialize model given size of bounding boxes in positive images
122 | model.gt_width = gt_width;
123 | model.gt_height = gt_height;
124 | model.aspect = gt_width/gt_height;
125 |
126 | model.Jpos = Jpos;
127 |
128 | model.nx = nx;
129 | model.ny = ny;
130 | model.nf = length(features(zeros([3 3 3]),1,feat_code(featType)));
131 | model.featType = featType;
132 |
133 | % Main parameters; linearly-scored template and bias
134 | model.w = zeros([model.ny model.nx model.nf])
135 | model.b = 0;
136 |
137 | % Encode scale factor for bias, width and height
138 | model.sb = 10;
139 | model.scalex = gt_width/(nx*sbins); % needed because hog templates cannot exactly
140 | model.scaley = gt_height/(ny*sbins); % have same aspect ratio as image templates.
141 |
142 | % Default number of scales in a 2X octave for image pyramid
143 | model.interval = 4;
144 |
145 | % Size of spatial bin
146 | model.sbin = sbins;
147 |
148 | % Enforce symmetry
149 | model.sym = true;
150 |
151 | % default threshold...
152 | model.thresh = -1;
153 | end
154 |
155 | function model = generate(model,vidName,~,AREA, trainOn)
156 | if nargin < 4 || isempty(AREA)
157 | AREA = 36;
158 | end
159 | featType = 'hog';
160 | if nargin < 5
161 | trainOn = [0];
162 | end
163 |
164 | C = cfg('C');
165 | Jpos = 1;
166 | b_gts = gt_load(vidName);
167 | b_gt1 = b_gts(1,:);
168 | gt_width = b_gt1(3)
169 | gt_height = b_gt1(4)
170 | gt_area = gt_width*gt_height;
171 | % compute
172 | nx = round(sqrt(AREA)*sqrt(gt_width)/sqrt(gt_height))
173 | ny = round(sqrt(AREA)*sqrt(gt_height)/sqrt(gt_width))
174 | na = nx*ny;
175 | sbins = round(sqrt(gt_area/na));
176 |
177 | model = model.init(sbins,nx,ny,Jpos,featType,gt_width,gt_height);
178 | model.qp = qp_init(model,C);
179 |
180 | % set the variance filter
181 | imM = get_frame(vidName,0);
182 | T0 = imcropr(imM,rectBtoK(b_gts(1,:)));
183 |
184 | model_cache_file = [cfg('tmp_dir') 'model_' ...
185 | featType num2str(AREA) hashMat(trainOn) ...
186 | vidName '.mat'];
187 | if exist(model_cache_file,'file')
188 | load(model_cache_file,'model');
189 | else
190 | for trainIter = 1:numel(trainOn)
191 | trainFrame = trainOn(trainIter);
192 | imM = get_frame(vidName,trainFrame);
193 |
194 | % train on frame
195 | for tIter = 1:5
196 | fprintf('track_dp: training iteration %d of %d\n',tIter,5);
197 | model = model.train_one(vidName,imM,b_gts(trainFrame+1,:));
198 | showModel(model.w);
199 | drawnow;
200 | end
201 | end
202 | save(model_cache_file,'model');
203 | end
204 | end
205 |
206 | % Train the SVM on one frame.
207 | function [model] = train_one(model,vidName,im,B_bb,p,n)
208 | % default args
209 | if nargin < 5
210 | p = 1;
211 | end
212 | if nargin < 6
213 | n = 1;
214 | end
215 | qp_out = @qp_write;
216 | update_model = 1;
217 | featSrc = @featpyramid;
218 | weight = 1;
219 | maxneg = inf;
220 | Jpos = model.Jpos;
221 |
222 | % dissallow training rectangles larger than the image.
223 | imsz = rect_size(rect_image(im));
224 | dtsz = rect_size(rectBtoK(B_bb));
225 | if any(dtsz > imsz)
226 | dtsz = dtsz
227 | assert(~any(dtsz > imsz));
228 | end
229 |
230 | featpyr = [];
231 | scales = [];
232 | if n >= 1
233 | [featpyr,scales] = featSrc(im,model.sbin,model.interval);
234 | end
235 |
236 | % add the positive examples...
237 | [model] = train_one_pos(model,B_bb,im,update_model,p,qp_out,weight);
238 |
239 | % now add the negative examples...
240 | model.thresh = -weight;
241 | %model.minVar = -inf;
242 | for i = 1:n
243 | [model] = train_one_neg...
244 | (model,im,featpyr,scales,B_bb,qp_out,update_model,weight,maxneg);
245 | end
246 | %showModel(model.w,1);
247 | %keyboard;
248 | end
249 |
250 | function [model] = train_one_neg...
251 | (model,im,featpyr,scales,B_bb,qp_out,update_model,weight,maxneg)
252 | model.qp = qp_prune(model.qp);
253 | maxnum = model.qp.nmax - model.qp.n;
254 | detor = model.detector();
255 | feat = detor.training_neg(B_bb,im,weight,featpyr,scales,min(maxnum,maxneg));
256 |
257 | % make sure we don't overfill the cache...
258 | if size(feat,2)+model.qp.n >= model.qp.nmax
259 | model.qp = qp_prune(model.qp);
260 | end
261 | assert(size(feat,2)+model.qp.n <= model.qp.nmax);
262 |
263 | % model.qp = qp_out(model.qp,-feat,1,1+box(:,end));
264 | model.qp = qp_out(model.qp,weight.*-feat,weight.*1,1,0);
265 | model.qp = qp_opt(model.qp);
266 | if update_model
267 | model = updateModel(model,model.Jpos);
268 | end
269 | end
270 |
271 | function [model] = train_one_pos(model,B_bb,im,update_model,p,qp_out,weight)
272 | Jpos = model.Jpos;
273 |
274 | % add the positive examples
275 | for iter = 1:p
276 | % if we don't have enough room for the sample try to prune non-svs
277 | if model.qp.n + 1 >= model.qp.nmax
278 | model.qp = qp_prune(model.qp);
279 | end
280 | % if pruning doesn't work, quit.
281 | if model.qp.n + 1 >= model.qp.nmax
282 | break;
283 | end
284 |
285 | feat = model.detector().training_pos(B_bb,im,weight);
286 | if isempty(feat)
287 | continue;
288 | end
289 | model.qp = qp_out(model.qp,weight.*Jpos*feat,weight.*Jpos,Jpos,1);
290 | model.qp = qp_opt(model.qp);
291 | end
292 |
293 | % update model and show template
294 | if update_model
295 | model = updateModel(model,Jpos);
296 | end
297 | end
298 |
299 | % Update model with current QP solution
300 | function model = updateModel(model,Jpos)
301 | model.w = reshape(model.qp.w(1:end-1),size(model.w));
302 | model.b = model.qp.w(end);
303 |
304 | model.interval = 14;
305 | end
306 |
307 | function ot = occ_thresh(obj)
308 | ot = -1;
309 | return;
310 |
311 | posProb = .95;
312 |
313 | % Store model threshold that allows us to find 95% of training
314 | % positives
315 | qp = obj.qp;
316 | r = qp.w'*qp.x(:,find(qp.pos));
317 | r = sort(r);
318 | idx = round(clamp(1,length(r)*(1-posProb),numel(r)));
319 | ot = double(r(idx)/obj.Jpos);
320 | end
321 |
322 | function c = cost(obj)
323 | c = obj.qp.lb;
324 | end
325 |
326 | function obj = train_all(obj,vidName,k_track,lambda)
327 | trainer = SVM_trainer;
328 | obj = trainer.train_all(vidName,k_track,lambda,[],obj);
329 | end
330 | end
331 | end
332 |
--------------------------------------------------------------------------------
/model/SVM_trainer.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.7.25 Class to train an SVM and produce a model.
2 | classdef SVM_trainer
3 | properties(SetAccess = private)
4 | % configuration (number of positive and negative passes to
5 | % do with each frame).
6 | p = 1;
7 | n = 1;
8 |
9 | % State
10 | passes;
11 | PASS_CT;
12 | frameCt;
13 | weights;
14 | track;
15 | vidName;
16 |
17 | % to cumbersome to pass around
18 | new_poss;
19 | new_poss_weights;
20 | new_negs;
21 | new_negs_weights;
22 | end
23 |
24 | methods
25 | % How many positive passes to do for each frame?
26 | function obj = setP(obj,p)
27 | obj.p = p;
28 | end
29 |
30 | % How many negative passes to do for each frame?
31 | function obj = setN(obj,n)
32 | obj.n = n;
33 | end
34 |
35 | % CTOR
36 | function obj = SVM_trainer()
37 | end
38 |
39 | function model = train_all(obj,vidName,track,weights,passes,model)
40 | memo = [cfg('tmp_dir') 'train_all_' ...
41 | hashMat(track) ...
42 | hashMat(weights) '.mat'];
43 | if exist(memo,'file')
44 | load(memo,'model')
45 | return;
46 | end
47 |
48 | if nargin < 6 || isempty(model)
49 | model = Model('gen',vidName,[],[],[]);
50 | end
51 |
52 | if sum(weights > 0) == 1
53 | % we are only training on a single frame, don't
54 | % make things to complicated.
55 | frameIter = find(weights)-1;
56 | im = get_frame(vidName,frameIter);
57 | b_bb = rectKtoB(track(frameIter+1,:));
58 | model = model.train_one(vidName,im,b_bb,5,5);
59 | else
60 | % handle default arguments
61 | if nargin < 5 || isempty(passes)
62 | passes = obj.default_passes(track,weights);
63 | end
64 | obj.PASS_CT = numel(passes);
65 | obj.passes = passes;
66 |
67 | % assert valid arguments
68 | assert(~all(weights <= 0));
69 |
70 | % store arguments on object
71 | obj.track = track;
72 | obj.vidName = vidName;
73 | obj.weights = weights;
74 |
75 | % ensure we don't try to train without any positive SVs.
76 | if weights(1) > .5
77 | model = model.train_one(vidName,...
78 | get_frame(vidName,0),...
79 | rectKtoB(track(1,:)),...
80 | 1,1);
81 | end
82 |
83 | % update for frame 2 to N (transduce)
84 | obj.frameCt = size(track,1);
85 | % start with an empty model...
86 | for pass = 1:obj.PASS_CT
87 | model = obj.one_training_pass(pass,model);
88 | end
89 | end
90 |
91 | save(memo,'model');
92 | end
93 |
94 | % if the user doesn't tell us how our pass structure
95 | % should be, then generate a sensible default.
96 | function passes = default_passes(obj,k_track,weights)
97 | trainingSetSize = sum(weights > 0);
98 | base = 2;
99 | iter = 1;
100 |
101 | passes = {};
102 | while 2.^iter < trainingSetSize
103 | passes{end+1} = 2.^iter;
104 | iter = iter+1;
105 | end
106 |
107 | FULL_CT = 2;
108 | % final passes with the full set.
109 | for iter = 1:FULL_CT
110 | passes{end+1} = trainingSetSize;
111 | end
112 | end
113 |
114 | % default sizes for a fixed number of passes.
115 | function passes = default_passes_fixed_ct(obj,k_track,weights)
116 | DEFAULT_PASS_CT = 5;
117 | passes = {};
118 | base = nthroot(size(k_track,1),DEFAULT_PASS_CT);
119 | % trainingSetSize = size(k_track,1);
120 | trainingSetSize = sum(weights > 0);
121 |
122 | % build the default pass sequence.
123 | for pass = 1:DEFAULT_PASS_CT
124 | if pass == DEFAULT_PASS_CT
125 | passSize = trainingSetSize;
126 | else
127 | passSize = clamp(1,round(base.^pass),trainingSetSize);
128 | end
129 |
130 | passes{end+1} = passSize;
131 | end
132 | end
133 |
134 | function model = one_training_pass(obj,pass,model)
135 | % compute the new feats for each frame
136 | bj.new_negs = {};
137 | obj.new_negs_weights = {};
138 | obj.new_poss = {};
139 | obj.new_poss_weights = {};
140 | passSize = obj.passes{pass};
141 | if passSize >= 32
142 | % use a local cluster because of network overhead.
143 | cluster_ctl('on','local');
144 | end
145 | frames = find(obj.weights > 0) - 1;
146 | rand_frame_order = frames(randi([1,numel(frames)],size(obj.track,1),1));
147 | maxneg = round((model.qp.nmax - model.qp.n)./passSize);
148 | detector = model.detector();
149 | parfor pFrameIter = 1:passSize
150 | [np,npw,nn,nnw] = obj.svs_for_pass...
151 | (detector,pFrameIter,rand_frame_order,maxneg,passSize,frames,pass);
152 | new_poss{pFrameIter} = np;
153 | new_poss_weights{pFrameIter} = npw;
154 | new_negs{pFrameIter} = nn;
155 | new_negs_weights{pFrameIter} = nnw;
156 | end
157 | % copy into the object
158 | obj.new_poss = new_poss;
159 | obj.new_poss_weights = new_poss_weights;
160 | obj.new_negs = new_negs;
161 | obj.new_negs_weights = new_negs_weights;
162 | cluster_ctl('off');
163 |
164 | % train with the new feats
165 | %keyboard;
166 | model = obj.train_all_commit(model);
167 | %keyboard;
168 | end
169 |
170 | function [np,npw,nn,nnw] = svs_for_pass...
171 | (obj,detector,pFrameIter,rand_frame_order,maxneg,passSize,frames,pass)
172 | if passSize == numel(frames)
173 | frameIter = frames(pFrameIter);
174 | else
175 | frameIter = rand_frame_order(pFrameIter);
176 | end
177 | fprintf('train_all pass %d: visiting %d of %d\n',...
178 | pass,frameIter,size(obj.track,1));
179 | curPos = obj.track(frameIter+1,:);
180 | b_pos = rectKtoB(curPos);
181 |
182 | % find margin violators.
183 | weight = obj.weights(frameIter+1);
184 | if weight > 0
185 | imN = get_frame(obj.vidName,frameIter);
186 | imsz = rect_size(rect_image(imN));
187 | dtsz = rect_size(curPos);
188 | end
189 |
190 | new_pos = [];
191 | new_neg = [];
192 | if weight > 0 && all(dtsz < imsz) && gt_valid(curPos);
193 | [featPyr,scale] = featpyramid(imN, detector.sbin, detector.interval);
194 | if obj.p > 0
195 | new_pos = detector.training_pos(b_pos,imN,weight);
196 | np = weight.*new_pos.*detector.getJpos();
197 | npw = double(repmat(weight.*detector.getJpos(),[size(new_pos,2),1]));
198 | end
199 | if obj.n > 0
200 | new_neg = detector.training_neg(b_pos,imN,weight,featPyr,scale,maxneg);
201 | nn = weight.*-new_neg;
202 | nnw = double(repmat(weight,[size(new_neg,2),1]));
203 | end
204 | %showBox(imN,curPos);
205 | end
206 |
207 | xlen = numel(detector.getW())+1;
208 | if isempty(new_pos)
209 | np = zeros(xlen,0);
210 | npw = double([]);
211 | end
212 | if isempty(new_neg)
213 | nn = single(zeros(xlen,0));
214 | nnw = double([]);
215 | end
216 |
217 | % the first frame must always contain one positive
218 | % support vector.
219 | assert(~(frameIter == 0 && isempty(np) && obj.p > 0));
220 | end
221 |
222 | % add all the Support Vectors we found into the cache and optimize.
223 | function model = train_all_commit...
224 | (obj,model)
225 | function c = c2d(c)
226 | c = cellfun(@(x) double(x), c, 'UniformOutput', false);
227 | end
228 |
229 | %keyboard;
230 | new_neg = cell2mat(c2d(obj.new_negs));
231 | new_pos = cell2mat(c2d(obj.new_poss));
232 | neg_weight = cell2mat(obj.new_negs_weights');
233 | pos_weight = cell2mat(obj.new_poss_weights');
234 | fprintf('train_all: writing %d new examples\n',size(new_neg,2)+size(new_pos,2));
235 | qp = model.qp_get();
236 | % pos
237 | qp = qp_write(qp,new_pos,pos_weight,model.Jpos,1);
238 | % neg
239 | qp = qp_write(qp,new_neg,neg_weight,1,0);
240 | % opt
241 | qp = qp_opt(qp);
242 | qp = qp_prune(qp);
243 | % update
244 | model = model.qp_set(qp);
245 | model = model.updateModel(model.Jpos);
246 | fprintf('train_all_commit: model updated\n');
247 |
248 | % Show the updated model...
249 | showModel(model.w); drawnow;
250 | end
251 | end
252 | end
253 |
254 |
--------------------------------------------------------------------------------
/model/genModel.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.5.29
2 | % high level, give a valid blank model for the video.
3 | function [model,Jpos,C] = genModel(varargin)
4 | model = Model('gen',varargin{:});
5 | Jpos = model.getJpos();
6 | C = model.getQP().getC();
7 | end
8 |
9 | % with AREA = 80
10 | %
11 | % C = .01 gives .6549 on coke11
12 | % C = .05 gives .7080 on coke11
13 | % C = .5 gives .72
14 |
15 | % with AREA = 40
16 | % C = .5
17 |
--------------------------------------------------------------------------------
/qp/QP.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.7.26
2 | % This is a class defining a Quadratic Program
3 | % OOP interface to the methods in this directory
4 | % (Primal) min_{w,e} .5*||w||^2 + C*sum_i e_i
5 | % s.t. w*x_i >= b_i - e_i
6 | % e_i >= 0
7 | %
8 | % (Dual) max_{a} -.5*sum_ij a_i(x_ix_j)a_j + sum_i b_i*a_i
9 | % s.t. 0 <= a_i <= C
10 | classdef QP
11 | properties(SetAccess = protected)
12 | % Define global QP problem using 1GB of memory
13 | % 2e7 = 2GB
14 | % 5e6 = 500 MB
15 | QP_SIZE;
16 | nmax;
17 | x;
18 | b;
19 | d;
20 | a;
21 | sv;
22 | % JSS3 2012-5-26, which examples are positive?
23 | pos;
24 | w;
25 | n;
26 | ub;
27 | lb;
28 | l;
29 | C;
30 | svfix;
31 | lb_old;
32 | obj;
33 |
34 | % prevent addition of duplicate features using a map of md5
35 | % hashes
36 | containment;
37 | end
38 |
39 | methods
40 | % getter for n
41 | function n = get_n(obj)
42 | n = obj.n;
43 | end
44 |
45 | % getter for nmax
46 | function nmax = get_nmax(obj)
47 | nmax = obj.nmax;
48 | end
49 |
50 | function C = getC(obj)
51 | C = obj.C;
52 | end
53 |
54 | % CTOR
55 | function obj = QP(model,C)
56 | if nargin == 1
57 | % Copy CTOR
58 | prps = properties(model);
59 | for iter = 1:length(prps)
60 | obj.(prps{iter}) = model.(prps{iter});
61 | end
62 | elseif nargin == 2
63 | obj = obj.init(model,C);
64 | end
65 | end
66 |
67 | function obj = init(obj,model,C)
68 | % Define model length
69 | len = numel(model.w) + numel(model.b);
70 |
71 | % 2e7 = 2GB
72 | % 5e6 = 500 MB
73 | QP_SIZE = 2e7;
74 | nmax = floor(QP_SIZE/len);
75 | obj.nmax = nmax;
76 | obj.x = zeros(len,nmax,'single');
77 | obj.b = zeros(nmax,1,'single');
78 | obj.d = zeros(nmax,1,'double');
79 | obj.a = zeros(nmax,1,'double');
80 | obj.sv = logical(zeros(1,nmax));
81 | % JSS3 2012-5-26, which examples are positive?
82 | obj.pos= logical(zeros(1,nmax));
83 | obj.w = zeros(len,1);
84 | obj.n = 0;
85 | obj.ub = 0;
86 | obj.lb = 0;
87 | obj.l = 0;
88 | obj.C = C;
89 | obj.svfix = [];
90 |
91 | % prevent addition of duplicate features using a map of md5
92 | % hashes
93 | obj.containment = containers.Map();
94 | end
95 |
96 | function obj = assert(obj,feat,margin,slack,pos)
97 | if isempty(feat)
98 | return
99 | end
100 |
101 | % Add constraints to QP
102 | % w*feat(:,i) >= margin(i) - slack(i)
103 | i = obj.n+1:obj.n + size(feat,2);
104 | obj.x(:,i) = feat;
105 | obj.d(i) = sum(feat.^2);
106 | obj.b(i) = margin;
107 | obj.sv(i) = 1;
108 | obj.pos(i) = pos;
109 | obj.ub = obj.ub + obj.C*sum(max(slack,0));
110 | obj.n = obj.n + size(feat,2);
111 | assert(obj.n <= obj.nmax);
112 | end
113 |
114 | function obj = opt_one(obj)
115 | MEX = true;
116 |
117 | % Random ordering of support vectors
118 | I = find(obj.sv);
119 | I = I(randperm(length(I)));
120 | assert(~isempty(I));
121 |
122 | % Mex file is much faster
123 | if MEX,
124 | bSize = size(obj.b);
125 |
126 | [loss,obj.a,obj.w,obj.sv,obj.l] = qp_one_c(obj.x,obj.b,obj.d,obj.a,obj.w,obj.sv,obj.l,obj.C,I);
127 | %keyboard;
128 |
129 | assert(all(bSize == size(obj.b)));
130 | else
131 | loss = 0;
132 | for i = I,
133 | % Compute clamped gradient
134 | G = obj.w'*obj.x(:,i) - obj.b(i);
135 | if (obj.a(i) == 0 && G >= 0) || (obj.a(i) == obj.C && G <= 0),
136 | PG = 0;
137 | else
138 | PG = G;
139 | end
140 | if (obj.a(i) == 0 && G > 0),
141 | obj.sv(i) = 0;
142 | end
143 | if G < 0,
144 | loss = loss - G;
145 | end
146 | % Update alpha,w, dual objective, support vector
147 | if (abs(PG) > 1e-12)
148 | a = obj.a(i);
149 | obj.a(i) = min(max(obj.a(i) - G/obj.d(i),0),obj.C);
150 | obj.w = obj.w + (obj.a(i) - a)*obj.x(:,i);
151 | obj.l = obj.l + (obj.a(i) - a)*obj.b(i);
152 | end
153 | end
154 | end
155 |
156 | % Update objective
157 | obj.sv(obj.svfix) = 1;
158 | obj.lb_old = obj.lb;
159 | obj.lb = obj.l - obj.w'*obj.w*.5;
160 | obj.ub = obj.w'*obj.w*.5 + obj.C*loss;
161 | assert(all(obj.a(1:obj.n) >= 0 - 1e-5));
162 | assert(all(obj.a(1:obj.n) <= obj.C + 1e-5));
163 |
164 | %{
165 | % Sanity check (expensive to commute)
166 | J = find(mask);
167 | K = obj.x(:,J)*obj.a(J);
168 | dual = obj.b(J)'*obj.a(J) - K'*K*.5;
169 | fprintf('obj=(%.3f,%.3f)',obj.obj,dual);
170 | assert(abs(obj.obj - dual) < .1);
171 | %}
172 | end
173 |
174 | function obj = opt(obj,tol,iter)
175 | % obj_opt(tol,iter)
176 | % Optimize QP until relative difference between lower and upper bound is below 'tol'
177 |
178 | if nargin < 2 || isempty(tol)
179 | tol = .05;
180 | end
181 |
182 | if nargin < 3 || isempty(iter)
183 | iter = 1000;
184 | end
185 |
186 | slack = obj.b' - obj.w'*obj.x;
187 | loss = sum(max(slack,0));
188 | ub = obj.w'*obj.w*.5 + obj.C*loss;
189 | lb = obj.lb;
190 | %fprintf('\n LB=%.4f,UB=%.4f [',lb,ub);
191 | %fprintf('[');
192 |
193 | % Iteratively apply coordinate descent, pruning active set (support vectors)
194 | % If we've possible converged over active set
195 | % 1) Compute true upper bound over full set
196 | % 2) If we haven't actually converged,
197 | % reinitialize optimization to full set
198 | obj.sv(1:obj.n) = 1;
199 | for t = 1:iter,
200 | obj = qp_one(obj);
201 | lb = obj.lb;
202 | ub_est = min(obj.ub,ub);
203 | %fprintf('.');
204 | if lb > 0 && 1 - lb/ub_est < tol,
205 | slack = obj.b' - obj.w'*obj.x;
206 | loss = sum(max(slack,0));
207 | ub = min(ub,obj.w'*obj.w*.5 + obj.C*loss);
208 | if 1 - lb/ub < tol,
209 | break;
210 | end
211 | obj.sv(1:obj.n) = 1;
212 | end
213 | %fprintf('t=%d: LB=%.4f,UB_true=%.5f,UB_est=%.5f,#SV=%d\n',t,lb,ub,ub_est,sum(obj.sv));
214 | end
215 |
216 | obj.ub = ub;
217 | %fprintf(']');
218 | %fprintf('] LB=%.4f,UB=%.4f\n',lb,ub);
219 |
220 | end
221 |
222 | % Re-indexes qp.x to begin with active consrtaints (eg, the support vectors)
223 | function [obj,n] = prune(obj)
224 | % if cache is full of support vectors, only keep non-zero (and fixed) ones
225 | if all(obj.sv),
226 | obj.sv = obj.a > 0;
227 | obj.sv(obj.svfix) = 1;
228 | end
229 |
230 | I = find(obj.sv > 0);
231 | n = length(I);
232 | assert(n > 0);
233 |
234 | % remove the non-support vectors from the
235 | NI = find(obj.sv(1:obj.n) <= 0);
236 | for i = 1:numel(NI)
237 | feat = obj.x(:,NI(i));
238 | hash = hashMat(feat);
239 | if obj.containment.isKey(hash)
240 | remove(obj.containment,hash);
241 | end
242 | end
243 |
244 | % move svs into the front of the cache
245 | obj.l = 0;
246 | obj.w = zeros(size(obj.w));
247 | for j = 1:n,
248 | i = I(j);
249 | obj.x(:,j) = obj.x(:,i);
250 | obj.b(j) = obj.b(i);
251 | obj.d(j) = obj.d(i);
252 | obj.a(j) = obj.a(i);
253 | obj.sv(j) = obj.sv(i);
254 | obj.pos(j) = obj.pos(i);
255 | obj.l = obj.l + double(obj.b(j))*obj.a(j);
256 | obj.w = obj.w + double(obj.x(:,j))*obj.a(j);
257 | end
258 |
259 | % clear the rest of the cache
260 | obj.sv(1:n) = 1;
261 | j = n+1:length(obj.a);
262 | obj.sv(j) = 0;
263 | obj.a(j) = 0;
264 | obj.b(j) = 0;
265 | obj.pos(j) = 0;
266 | obj.x(:,j) = 0;
267 | obj.obj = obj.l - obj.w'*obj.w*.5;
268 | obj.n = n;
269 | %fprintf('\n Pruned to %d/%d with dual=%.4f \n',obj.n,length(obj.a),obj.obj);
270 | end
271 |
272 | function obj = retract(obj,what,margin,slack)
273 | if numel(what) == 1
274 | num = what;
275 | else
276 | feat = what;
277 | num = size(feat,2);
278 | end
279 |
280 | index = obj.n:-1:(obj.n-num+1);
281 | obj.x(:,index) = 0;
282 | obj.d(index) = 0;
283 | obj.b(index) = 0;
284 | obj.sv(index) = 0;
285 | obj.ub = obj.ub - obj.C*sum(max(slack,0));
286 | obj.n = obj.n - num;
287 | assert(obj.n <= obj.nmax);
288 | end
289 |
290 | function obj = write(obj,feat,margin,slack,isPos)
291 | % Compute the (md5) hash code for the feature vector.
292 | %keyboard;
293 | hashCode = hashMat(feat);
294 |
295 | % make sure we don't overfill the cache...
296 | assert(size(feat,2) == numel(margin) || numel(margin) == 1);
297 | if size(feat,2)+obj.n >= obj.nmax
298 | obj = obj.prune();
299 | end
300 | num_keep = clamp(0,obj.nmax-obj.n,size(feat,2));
301 | feat = feat(:,1:num_keep);
302 | if numel(margin) ~= 1
303 | margin = margin(1:num_keep);
304 | end
305 |
306 | % only add the feature to the cache if it hasn't
307 | % already been added....
308 | if ~obj.containment.isKey(hashCode)
309 | % function obj_write(feat,margin,slack)
310 | obj = obj.assert(feat,margin,slack,isPos);
311 |
312 | obj.containment(hashCode) = 1;
313 | else
314 | 'would add duplicate key';
315 | end
316 | end
317 |
318 | % JSS3 - 2012.8.15
319 | % quick estimate for UB given a w
320 | function loss = compute_loss(obj,w)
321 | if nargin < 2
322 | w = obj.w;
323 | end
324 |
325 | % compute loss
326 | is = 1:obj.n;
327 | resp = w' * obj.x(:,is);
328 | margins = obj.b(is);
329 | slacks = max(margins' - resp,0);
330 | %.5*||w||^2 + C*sum_i e_i
331 | % loss = .5.*w'*w + obj.C .* sum(slacks);
332 | loss = obj.C .* sum(slacks);
333 | end
334 | end
335 | end
336 |
--------------------------------------------------------------------------------
/qp/qp_assert.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-21
2 | function qp = qp_assert(qp,feat,margin,slack,pos)
3 | qp = qp.assert(feat,margin,slack,pos);
4 | end
5 |
--------------------------------------------------------------------------------
/qp/qp_clear.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.5.14
2 | % remove most of the data in the qp for storage.
3 | function qpPrime = qp_clear(qp)
4 | qpPrime = QP_fixed(qp);
5 | end
6 |
--------------------------------------------------------------------------------
/qp/qp_init.m:
--------------------------------------------------------------------------------
1 | % Deva Ramanan 2012-03-19
2 | % qp_init(len,nmax,C)
3 | %
4 | %
5 | % Define global QP problem
6 | % 2012-04-25 JSS3 made it local for parfor.
7 | %
8 | % (Primal) min_{w,e} .5*||w||^2 + C*sum_i e_i
9 | % s.t. w*x_i >= b_i - e_i
10 | %
11 | % (Dual) max_{a} -.5*sum_ij a_i(x_ix_j)a_j + sum_i b_i*a_i
12 | % s.t. 0 <= a_i <= C
13 | %
14 | % where w = sum_i a_i x_i
15 | %
16 | % qp.x(:,i) = x_i where size(qp.x) = [len nmax]
17 | % qp.b(:,i) = b_i
18 | % qp.d(i) = ||x(i)||^2
19 | % qp.a(i) = a_i
20 | % qp.w = sum_i a_i x_i
21 | % qp.l = sum_i b_i a_i
22 | % qp.n = number of constraints
23 | % qp.ub = .5*||qp.w||^2 + C*sum_i e_i
24 | % qp.lb = -.5*sum_ij a_i(x_ix_j)a_j + sum_i b_i*a_i
25 | % qp.C = C
26 | % qp.svfix = pointers to examples that are always kept in memory
27 | % JSS3 2012-03-18
28 | % init a blank Quadratic Program...
29 | function [qp,nmax] = qp_init(model,C)
30 | qp = QP(model,C);
31 | nmax = qp.nmax;
32 | end
33 |
--------------------------------------------------------------------------------
/qp/qp_one.m:
--------------------------------------------------------------------------------
1 | % Perform one pass through current set of support vectors
2 | function qp = qp_one(qp)
3 | qp = qp.opt_one();
4 | end
5 |
--------------------------------------------------------------------------------
/qp/qp_one_c.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include "../mex/compat.h"
3 | #include "mex.h"
4 | #include "matrix.h"
5 |
6 | #define MAX(A,B) ((A) < (B) ? (B) : (A))
7 | #define MIN(A,B) ((A) > (B) ? (B) : (A))
8 |
9 | // Undocumented Features!
10 | //extern int mxUnshareArray(mxArray *pr, int noDeepCopy); // true if not successful
11 | //extern bool mxUnshareArray(const mxArray *pr, const bool noDeepCopy);
12 | extern "C" int mxUnshareArray(mxArray *pa, int level);
13 | extern "C" int mxIsSharedArray(mxArray* pa);
14 | extern "C" mxArray *mxCreateSharedDataCopy(const mxArray *pr);
15 |
16 | // x(:,1:length(I)) = x(:,I);
17 | // qp_one_c(qp.x,qp.b,qp.d,qp.a,qp.w,qp.sv,qp.l,qp.C,I);
18 | void mexFunction( int nlhs, mxArray *plhs[],
19 | int nrhs, const mxArray *prhs[] )
20 | {
21 | if (nlhs < 5) mexErrMsgTxt("qp_one_c.cc: Incorrect number of output arguments.");
22 | if (nrhs < 9) mexErrMsgTxt("qp_one_c.cc: Incorrect number of input arguments.");
23 |
24 | // prevent erronous sharing.
25 | mxArray *Areturn, *Wreturn, *SVreturn, *Lreturn;
26 | Areturn = mxCreateSharedDataCopy(prhs[3]);
27 | Wreturn = mxCreateSharedDataCopy(prhs[4]);
28 | SVreturn = mxCreateSharedDataCopy(prhs[5]);
29 | Lreturn = mxCreateSharedDataCopy(prhs[6]);
30 | mxUnshareArray(Areturn, 0);
31 | mxUnshareArray(Wreturn, 0);
32 | mxUnshareArray(SVreturn, 0);
33 | mxUnshareArray(Lreturn, 0);
34 |
35 | float const *X = (float *)mxGetPr(prhs[0]);
36 | float const *B = (float *)mxGetPr(prhs[1]);
37 | double const *D = (double *)mxGetPr(prhs[2]);
38 | double *A = (double *)mxGetPr(Areturn);
39 | double *W = (double *)mxGetPr(Wreturn);
40 | bool *SV = (bool *)mxGetPr(SVreturn);
41 | double *L = (double *)mxGetPr(Lreturn);
42 | double C = (double )mxGetScalar(prhs[7]);
43 | double const *I = (double *)mxGetPr(prhs[8]);
44 |
45 | if (mxIsSingle(prhs[0]) == false) mexErrMsgTxt("Argument 0 is not single.");
46 | if (mxIsSingle(prhs[1]) == false) mexErrMsgTxt("Argument 1 is not single.");
47 | if (mxIsDouble(prhs[2]) == false) mexErrMsgTxt("Argument 2 is not double.");
48 | if (mxIsDouble(prhs[3]) == false) mexErrMsgTxt("Argument 3 is not double.");
49 | if (mxIsDouble(prhs[4]) == false) mexErrMsgTxt("Argument 4 is not double.");
50 | if (mxIsLogical(prhs[5]) == false) mexErrMsgTxt("Argument 6 is not logical.");
51 | if (mxIsDouble(prhs[6]) == false) mexErrMsgTxt("Argument 7 is not double.");
52 | if (mxIsDouble(prhs[7]) == false) mexErrMsgTxt("Argument 8 is not double.");
53 | if (mxIsDouble(prhs[8]) == false) mexErrMsgTxt("Argument 9 is not double.");
54 |
55 | mwSize m = mxGetM(prhs[0]);
56 | mwSize n = MAX(mxGetN(prhs[8]),mxGetM(prhs[8]));
57 |
58 | double loss = 0;
59 | //printf("Intro: (m,n,C) = (%d,%d,%g)\n",m,n,C);
60 |
61 | for (int cnt = 0; cnt < n; cnt++) {
62 | // Use C indexing
63 | int i = (int)I[cnt] - 1;
64 | double G = -(double)B[i];
65 | float const *x = X + m*i;
66 |
67 | for (int d = 0; d < m; d++) {
68 | G += W[d] * (double)x[d];
69 | //printf("(%g,%g,%g)",G,W[d],x[d]);
70 | }
71 |
72 | double PG = G;
73 |
74 | if ((A[i] == 0 && G >= 0) || (A[i] == C && G <= 0)) {
75 | PG = 0;
76 | }
77 |
78 | if (A[i] == 0 && G > 0) {
79 | SV[i] = false;
80 | }
81 |
82 | if (G < 0) {
83 | loss -= G;
84 | }
85 |
86 | //printf("[%d,%d,%g,%g,%g]\n",cnt,i,G,PG,A[i]);
87 | if (PG > 1e-12 || PG < -1e-12) {
88 | double dA = A[i];
89 | A[i] = MIN ( MAX ( A[i] - G/D[i], 0 ) , C );
90 | dA = A[i] - dA;
91 | L[0] += dA * (double) B[i];
92 | //printf("%g,%g,%g,%g\n",A[i],B[i],dA,*L);
93 | for (int d = 0; d < m; d++) {
94 | W[d] += dA * (double) x[d];
95 | }
96 | }
97 | }
98 |
99 | // pack the output arguments...
100 | plhs[0] = mxCreateDoubleScalar(loss);
101 | plhs[1] = Areturn;
102 | plhs[2] = Wreturn;
103 | plhs[3] = SVreturn;
104 | plhs[4] = Lreturn;
105 | }
106 |
107 | /* Mex code equivalent to below
108 | % Perform one pass through variables indicated by binary mask
109 | for i = I,
110 | % Compute clamped gradient
111 | G = qp.w'*qp.x(:,i) - qp.b(i);
112 | if (qp.a(i) == 0 && G >= 0) || (qp.a(i) == qp.C && G <= 0),
113 | PG = 0;
114 | else
115 | PG = G;
116 | end
117 | if (qp.a(i) == 0 && G > 0),
118 | qp.sv(i) = 0;
119 | end
120 | if G < 0,
121 | loss = loss - G;
122 | end
123 | % Update alpha,w, dual objective, support vector
124 | if (abs(PG) > 1e-12)
125 | a = qp.a(i);
126 | qp.a(i) = min(max(qp.a(i) - G/qp.d(i),0),qp.C);
127 | qp.w = qp.w + (qp.a(i) - a)*qp.x(:,i);
128 | qp.l = qp.l + (qp.a(i) - a)*qp.b(i);
129 | end
130 | */
131 |
--------------------------------------------------------------------------------
/qp/qp_opt.m:
--------------------------------------------------------------------------------
1 | function qp = qp_opt(qp,tol,iter)
2 | qp = qp.opt();
3 | end
4 |
--------------------------------------------------------------------------------
/qp/qp_prune.m:
--------------------------------------------------------------------------------
1 | % Re-indexes qp.x to begin with active consrtaints (eg, the support vectors)
2 | function [qp,n] = qp_prune(qp)
3 | [qp,n] = qp.prune();
4 | end
5 |
--------------------------------------------------------------------------------
/qp/qp_write.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.7.3
2 | % To weight a sample,
3 | % (Primal) min_{w,e} .5*||w||^2 + C*sum_i v_i*e_i
4 | % s.t. w*x_i >= b_i - e_i
5 | % if u_i = v_i * e_i
6 | % then w*x_i >= b_i - u_i/v_i or
7 | % w*v_i*x_i >= v_i*b_i - u_i with .5*||w||^2 + C*sum_i u_i
8 | % so multiply the feature and the margin by the weight (2nd and 3rd arguments)
9 | function qp = qp_write(qp,feat,margin,slack,isPos)
10 | qp = qp.write(feat,margin,slack,isPos);
11 | end
12 |
--------------------------------------------------------------------------------
/rect/check_rect_size.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.8.31
2 | % return 1 if a bb is ok,
3 | % 0 other (maybe it is to large or truncated)
4 | function ok = check_rect_size(k_bb,k_im)
5 | % size constraints
6 | n = size(k_bb,1);
7 | imsz = repmat(rect_size(k_im),[n,1]);
8 | bbsz = rect_size(k_bb);
9 | ok = all(bbsz <= 2.*imsz,2);
10 | end
11 |
--------------------------------------------------------------------------------
/rect/csvBtoK.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.6.28
2 | % convert Babenko BBs to Kalal BBs in a CSV file
3 | function csvBtoK(filename)
4 | b_track = csvread(filename);
5 | k_track = rectBtoK(b_track);
6 | csvwrite(filename,k_track);
7 | end
8 |
--------------------------------------------------------------------------------
/rect/rectBtoK.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012-03-18
2 | % convert rectnalge from [x1 y1 w h] format
3 | % to [x1 y1 x2 y2]
4 | function K = rectKtoB(B)
5 | K = [B(:,1) B(:,2) (B(:,1)+B(:,3)) (B(:,2)+B(:,4))];
6 | end
7 |
--------------------------------------------------------------------------------
/rect/rectKtoB.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012-03-18
2 | % convert rectnalge from [x1 y1 x2 y2] format
3 | % to [x1 y1 w h]
4 | function B = rectKtoB(K)
5 | B = [K(:,1) K(:,2) (K(:,3)-K(:,1)) (K(:,4)-K(:,2))];
6 | end
7 |
--------------------------------------------------------------------------------
/rect/rect_area.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.7.10
2 | % Return area of a rectangle
3 | function ar = rect_area(k_rect)
4 | width = k_rect(:,3) - k_rect(:,1);
5 | height = k_rect(:,4) - k_rect(:,2);
6 | ar = width .* height;
7 | end
8 |
--------------------------------------------------------------------------------
/rect/rect_aspect.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.7.10
2 | % Return aspect ratio of a rectangle
3 | function aspect = rect_aspect(k_rect)
4 | width = k_rect(:,3) - k_rect(:,1);
5 | height = k_rect(:,4) - k_rect(:,2);
6 | aspect = width ./ height;
7 | end
8 |
--------------------------------------------------------------------------------
/rect/rect_center.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-14
2 | % return the center of a Kalal format rectangle...
3 | function center = rect_center(k_rect)
4 | x = (k_rect(:,1)+k_rect(:,3))./2;
5 | y = (k_rect(:,2)+k_rect(:,4))./2;
6 |
7 | center = [x y];
8 | end
9 |
--------------------------------------------------------------------------------
/rect/rect_contains.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.6.19
2 | function c = rect_contains(k_rect,k_pts)
3 | c = k_pts(:,1) >= k_rect(:,1) & k_pts(:,1) <= k_rect(:,3) & ...
4 | k_pts(:,2) >= k_rect(:,2) & k_pts(:,2) <= k_rect(:,4);
5 | end
6 |
--------------------------------------------------------------------------------
/rect/rect_correct_aspect.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-13
2 | % rect_correct_aspect changes the aspect ratio of a rectangle to
3 | % the desired aspect ratio without changing its area.
4 | function k_rect2 = rect_correct_aspect(k_rect,newAspectRatio)
5 | % aspect = width/height
6 |
7 | % find the new size
8 | oldWidth = k_rect(3) - k_rect(1);
9 | oldHeight = k_rect(4) - k_rect(2);
10 | oldArea = oldWidth.*oldHeight;
11 | % newArea = newWidth * newHeight
12 | % newArea = oldArea
13 | % newAspectRatio = newWidth/newHeight
14 | % newWidth = newAspectRatio * newHeight
15 | % oldArea = newHeight * newAspectRatio * newHeight
16 | % oldArea = newHeight^2 * newAspectRatio
17 | % newHeight = sqrt(oldArea/newAspectRatio)
18 | %newAspectRatio
19 | newHeight = sqrt(oldArea/newAspectRatio);
20 | newWidth = newAspectRatio*newHeight;
21 |
22 | % find the old center
23 | oldCenX = (k_rect(1)+k_rect(3))./2;
24 | oldCenY = (k_rect(2)+k_rect(4))./2;
25 |
26 | k_rect2 = rect_from_center([oldCenX,oldCenY],[newWidth,newHeight]);
27 | end
28 |
--------------------------------------------------------------------------------
/rect/rect_equal.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012-06-03
2 | % Are two rectangles equal?
3 | function eq = rect_equal(rect1,rect2)
4 | eq = (gt_occluded(rect1) && gt_occluded(rect2)) || ...
5 | all(rect1(:,1:4) == rect2(:,1:4));
6 | end
7 |
--------------------------------------------------------------------------------
/rect/rect_from_center.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-13
2 | % rect_from_center takes a center and a size and returns a
3 | % Kalal format rectangle.
4 | function k_rect = rect_from_center(cen,sz)
5 | % find the extreme pts.
6 | x1 = cen(:,1) - sz(:,1)./2;
7 | y1 = cen(:,2) - sz(:,2)./2;
8 | x2 = cen(:,1) + sz(:,1)./2;
9 | y2 = cen(:,2) + sz(:,2)./2;
10 |
11 | % return
12 | k_rect = [x1 y1 x2 y2];
13 | end
14 |
--------------------------------------------------------------------------------
/rect/rect_image.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.7.10
2 | % Return the rectnagle bounding an image
3 | function rect = rect_image(im)
4 | [h,w,d] = size(im);
5 | rect = [0 0 w h];
6 | end
7 |
--------------------------------------------------------------------------------
/rect/rect_overlap.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-14
2 | % JSS3 multiple rectangle support 2012-5-14
3 | % Computes the intersection over union overlap
4 | % for two Kalal format rectangles
5 | function overlap = rect_overlap(k_rect1, k_rect2)
6 | if gt_occluded(k_rect1) && gt_occluded(k_rect2)
7 | overlap = 1;
8 | elseif xor(gt_occluded(k_rect1),gt_occluded(k_rect2))
9 | overlap = 0;
10 | else
11 | rect1 = rectKtoB(k_rect1);
12 | rect2 = rectKtoB(k_rect2);
13 |
14 | % intersection of rectangle 1 and rectangle 2
15 | intersection = rectint(rect1,rect2);
16 | % area of rectangle 1
17 | area1 = rect1(:,3) .* rect1(:,4); % a = w*h
18 | % area of rectangle 2
19 | area2 = rect2(:,3) .* rect2(:,4); % a = w*h
20 |
21 | % union over intersection
22 | overlap = intersection ./ (area1+area2-intersection);
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/rect/rect_scale.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-20
2 | % scale a rect by the given factors
3 | function k_rect = rect_scale(k_rect,xScale,yScale)
4 | center = rect_center(k_rect);
5 | width = k_rect(:,3) - k_rect(:,1);
6 | height = k_rect(:,4) - k_rect(:,2);
7 | k_rect = rect_from_center(center,[xScale.*width yScale.*height]);
8 | end
9 |
--------------------------------------------------------------------------------
/rect/rect_size.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-05-04
2 | function sz = rect_size(k_rect)
3 | sz = zeros(size(k_rect,1),2);
4 | % width
5 | sz(:,1) = k_rect(:,3) - k_rect(:,1);
6 | % height
7 | sz(:,2) = k_rect(:,4) - k_rect(:,2);
8 | end
9 |
--------------------------------------------------------------------------------
/rect/rect_trans.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-13
2 | % Translate a Kalal rectangle
3 | function k_rect = rect_trans(k_rect,offset)
4 | k_rect([1,3]) = k_rect([1,3]) + offset(1);
5 | k_rect([2,4]) = k_rect([2,4]) + offset(2);
6 | end
7 |
--------------------------------------------------------------------------------
/rect/rect_zero_orig.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-13
2 | % rect_zero_orig translates a rectangle so that it is rooted at the
3 | % origin
4 | function k_rect = rect_zero_orig(k_rect)
5 | k_rect([1,3]) = k_rect([1,3]) - k_rect(1);
6 | k_rect([2,4]) = k_rect([2,4]) - k_rect(2);
7 | end
8 |
--------------------------------------------------------------------------------
/rect/rects_overlap.m:
--------------------------------------------------------------------------------
1 | %% JSS3 2012.8.20
2 | % Compute overlap between two lists of rectangles
3 | function ols = rects_overlap(k_A,k_B)
4 | ols = zeros(size(k_A,1),1);
5 | for iter = 1:numel(ols)
6 | ols(iter) = rect_overlap(k_A(iter,:),k_B(iter,:));
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/show/hasDisplay.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-05-27
2 | % predicate function to indicate if the current MATLAB
3 | % has a display to show graphics on...
4 | function yes = hasDisplay()
5 | yes = ~usejava('jvm') || feature('ShowFigureWindows');
6 | end
7 |
--------------------------------------------------------------------------------
/show/linWidth.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.7.5
2 | % Compute the proper line with when showing N boxes
3 | function width = linWidth(N)
4 | a = 7.5;
5 | b = -.05;
6 | width = a*exp(b*N);
7 | width = ceil(width);
8 | end
9 |
--------------------------------------------------------------------------------
/show/plot_resp.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-06
2 | % MATLAB function to plot the response values
3 | % against some other useful information.
4 | function [p,r] = plot_resp(b_gts,k_boxes,vidName,show)
5 | if nargin < 4
6 | show = 0;
7 | end
8 |
9 | makePlot = isempty(getCurrentTask) && show;
10 | if makePlot
11 | clf;
12 | hold on;
13 | end
14 |
15 | % compute the graph, frame by frame
16 | [cAccept,gAccept,nAccept,...
17 | goodIdx,goodResp,badIdx,badResp,...
18 | gtVisIdx,gtVisResp,trVisIdx,trVisResp] ...
19 | = plot_resp_accum(b_gts,k_boxes,vidName);
20 |
21 | if makePlot
22 | % plot visibilities
23 | phs = [];
24 | phs(end+1) = plot(gtVisIdx,gtVisResp,' o','DisplayName','gt accept');
25 | phs(end+1) = plot(trVisIdx,trVisResp,' s','DisplayName','tracker accept');
26 | % generate the plot
27 | phs(end+1) = plot(goodIdx,goodResp,'b+','DisplayName','Correct');
28 | phs(end+1) = plot(badIdx,badResp,'r+','DisplayName','Incorrect');
29 | legend show;
30 |
31 | % label the plot
32 | title(vidName);
33 | xlabel('Frame Number');
34 | ylabel('Cost');
35 |
36 | hold off;
37 |
38 | PRESENTATION = 1;
39 | if PRESENTATION
40 | legend hide;
41 | set(gca,'position',[0 0 1 1]) ;
42 | h = gca;
43 | set(h,'XTick',[]);
44 | set(h,'YTick',[]);
45 | for iter = 1:numel(phs)
46 | set(phs(iter),'MarkerSize',12);
47 | end
48 | end
49 | end
50 |
51 | % report p and r
52 | cAccept
53 | gAccept
54 | nAccept
55 | p = cAccept/nAccept;
56 | r = cAccept/gAccept;
57 | end
58 |
59 | function [cAccept,gAccept,nAccept,...
60 | goodIdx,goodResp,badIdx,badResp,...
61 | gtVisIdx,gtVisResp,trVisIdx,trVisResp] ...
62 | = plot_resp_accum(b_gts,k_boxes,vidName)
63 | % precision = correctly accepted / number accepted
64 | % recall = correctly accepted / gt accepted
65 | cAccept = 0;
66 | gAccept = 0;
67 | nAccept = 0;
68 |
69 | % error plotting
70 | goodIdx = [];
71 | goodResp = [];
72 | badIdx = [];
73 | badResp = [];
74 | % occlusion plotting
75 | gtVisIdx = [];
76 | gtVisResp = [];
77 | trVisIdx = [];
78 | trVisResp = [];
79 |
80 | for i = 2:size(b_gts,1)
81 | gt = b_gts(i,:);
82 | box = k_boxes(i,:);
83 | derivative = 0;
84 | if derivative
85 | lastBox = k_boxes(i-1,:);
86 | else
87 | lastBox = 2.*box;
88 | end
89 |
90 | % update the counts for p/r
91 | [l,c,g,n] = score_track_one(gt,box);
92 | cAccept = cAccept + c;
93 | gAccept = gAccept + g;
94 | nAccept = nAccept + n;
95 |
96 | % plot pt
97 | if l > 0
98 | if c > 0
99 | % correct
100 | goodIdx(end+1) = i;
101 | goodResp(end+1) = lastBox(5)-box(5);
102 | else
103 | % incorrect
104 | badIdx(end+1) = i;
105 | badResp(end+1) = lastBox(5)-box(5);
106 | end
107 |
108 | if g > 0
109 | gtVisIdx(end+1) = i;
110 | gtVisResp(end+1) = lastBox(5)-box(5);
111 | end
112 |
113 | if n > 0
114 | trVisIdx(end+1) = i;
115 | trVisResp(end+1) = lastBox(5)-box(5);
116 | end
117 | end
118 | end
119 | end
120 |
--------------------------------------------------------------------------------
/show/showBox.m:
--------------------------------------------------------------------------------
1 | % showBox(im,rect)
2 | % Input:
3 | % im is a N X M grayscale image
4 | % rect is a 1 X 4 array of rectangle coordinates
5 | % ([x1 y1 x2 y2] coordinates assumed)
6 | % Output: None
7 | % This function shows an image with a rectangle on it
8 | % Hint: use Matlab's "imshow.m", "hold.m" and "line.m" functions
9 | function showBox(im,rect,clean)
10 | if nargin < 3
11 | clean = 0;
12 | end
13 |
14 | if clean
15 | set(gca,'position',[0 0 1 1]) ;
16 | % im and rect must be fixed
17 | crop_r = rect_scale(rect,2,2);
18 | rect([1 3]) = rect([1 3]) - crop_r(1);
19 | rect([2 4]) = rect([2 4]) - crop_r(2);
20 | im = imcropr(im,crop_r);
21 | end
22 |
23 | % can't show on the cluster worker.
24 | if ~isempty(getCurrentTask)
25 | return
26 | end
27 |
28 | showBoxes(im,rect,clean);
29 | end
30 |
--------------------------------------------------------------------------------
/show/showBoxVia.m:
--------------------------------------------------------------------------------
1 | function showBoxVia(im,rect,via)
2 | % extract the params
3 | x1 = rect(1); y1 = rect(2);
4 | x2 = rect(3); y2 = rect(4);
5 | % draw the image
6 | colormap gray(256);
7 | via(im);
8 | hold on;
9 | % draw the box.
10 | line([x1 x2],[y1 y1]) % top
11 | line([x1 x2],[y2 y2]) % bottom
12 | line([x1 x1],[y1 y2]) % left
13 | line([x2 x2],[y1 y2]) % right
14 | hold off;
15 | drawnow;
16 | end
17 |
--------------------------------------------------------------------------------
/show/showBoxes.m:
--------------------------------------------------------------------------------
1 | function showBoxes(im,boxes,clean)
2 | % showBoxes(im,boxes)
3 | if nargin < 3
4 | clean = 0;
5 | end
6 |
7 | cla;
8 | if clean
9 | set(gca,'position',[0 0 1 1]) ;
10 | end
11 | imagesc(im);
12 |
13 | width = linWidth(size(boxes,1));
14 |
15 | if ~isempty(boxes),
16 | % use light red line to show everyone
17 | if size(boxes,1) > 1
18 | showGhostBoxes(boxes(2:end,:),'r',width);
19 | end
20 |
21 | % plot the best box in dark blue.
22 | x1 = boxes(1,1);
23 | y1 = boxes(1,2);
24 | x2 = boxes(1,3);
25 | y2 = boxes(1,4);
26 | line([x1 x1 x2 x2 x1]',[y1 y2 y2 y1 y1]','color','b','linewidth', ...
27 | width*2);
28 |
29 | % plot numbers...
30 | if clean
31 | return;
32 | end
33 | for boxIter = 1:size(boxes,1)
34 | boxTexts = {};
35 | curBox = boxes(boxIter,:);
36 | cen = deal(rect_center(curBox));
37 | % add the response?
38 | if size(boxes,2) > 4
39 | boxTexts{end+1} = ['resp = ' num2str(curBox(:,5))];
40 | end
41 | %if size(boxes,2) >= 6
42 | % boxTexts{end+1} = ['occ = ' num2str(curBox(:,6))];
43 | %end
44 | %if size(boxes,2) >= 7
45 | % boxTexts{end+1} = ['emg = ' num2str(curBox(:,7))];
46 | %end
47 | text(cen(1),cen(2),boxTexts,'Color','g');
48 | end
49 | end
50 |
51 | drawnow;
52 |
--------------------------------------------------------------------------------
/show/showGhostBoxes.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.10.9
2 | % advanced box drawing function with support for alpha transparency
3 | function showGhostBoxes(boxes,color,width)
4 | % compute coordinates
5 | D = max(.5,width./4);
6 | x1 = boxes(:,1);
7 | y1 = boxes(:,2);
8 | x2 = boxes(:,3);
9 | y2 = boxes(:,4);
10 |
11 | % compute alphas
12 | N = size(boxes,1);
13 | %alphas = ((N:-1:1)./N)';
14 | alphas = ((1:N)./N)';
15 |
16 | % draw the top and bottom
17 | patch([x1-D x2+D x2+D x1-D]',[y1-D y1-D y1+D y1+D]',color,'edgecolor','none',...
18 | 'FaceAlpha','flat','FaceVertexAlphaData',alphas);
19 | patch([x1-D x2+D x2+D x1-D]',[y2+D y2+D y2-D y2-D]',color,'edgecolor','none',...
20 | 'FaceAlpha','flat','FaceVertexAlphaData',alphas);
21 | % draw left and right
22 | patch([x1-D x1+D x1+D x1-D]',[y1+D y1+D y2-D y2-D]',color,'edgecolor','none',...
23 | 'FaceAlpha','flat','FaceVertexAlphaData',alphas);
24 | patch([x2-D x2+D x2+D x2-D]',[y1+D y1+D y2-D y2-D]',color,'edgecolor','none',...
25 | 'FaceAlpha','flat','FaceVertexAlphaData',alphas);
26 | end
27 |
--------------------------------------------------------------------------------
/show/showModel.m:
--------------------------------------------------------------------------------
1 | % Display the HOG template
2 | % Only the first argument is required.
3 | function [hogPos,hogNeg] = showModel(ww,n,sc)
4 |
5 | % can't show on the cluster worker.
6 | if ~isempty(getCurrentTask)
7 | return
8 | end
9 |
10 | % the second two arguments are optinal.
11 | if nargin >= 2
12 | sfigure(n);
13 | clf;
14 | else
15 | n = 1;
16 | end
17 | if nargin < 3,
18 | %Set the scale so that the maximum weight is 255
19 | sc = max(abs(ww(:)));
20 | end
21 |
22 | sc = 255/sc;
23 |
24 | siz = 20;
25 |
26 | im1 = HOGpicture( ww,siz)*sc;
27 | hogPos = im1;
28 | im2 = HOGpicture(-ww,siz)*sc;
29 | hogNeg = im2;
30 |
31 | %Combine into 1 image
32 | buff = 10;
33 | im1 = padarray(im1,[buff buff],200,'both');
34 | im2 = padarray(im2,[buff buff],200,'both');
35 | im = cat(2,im1,im2);
36 | im = uint8(im);
37 | imagesc(im); colormap gray;
38 | title(['HoG Model: ' n]);
39 | %keyboard;
40 |
41 | function im = HOGpicture(w, bs)
42 | % HOGpicture(w, bs)
43 | % Make picture of positive HOG weights.
44 | global ORI_BINS;
45 |
46 | % construct a "glyph" for each orientaion
47 | bim1 = zeros(bs, bs);
48 | %bim1(:,round(bs/2):round(bs/2)+1) = 1;
49 | bim1(1:(round(size(bim1,1)./2)+1),round(20/2):round(20/2)+1) = 1;
50 | bim = zeros([size(bim1) ORI_BINS]);
51 | bim(:,:,1) = bim1;
52 | for i = 2:ORI_BINS,
53 | bim(:,:,i) = imrotate(bim1, -(i-1)*20, 'crop');
54 | end
55 |
56 | % make pictures of positive weights bs adding up weighted glyphs
57 | s = size(w);
58 | w(w < 0) = 0;
59 | im = zeros(bs*s(1), bs*s(2),3);
60 | for i = 1:s(1),
61 | iis = (i-1)*bs+1:i*bs;
62 | for j = 1:s(2),
63 | jjs = (j-1)*bs+1:j*bs;
64 | % draw the background
65 | if(size(w,3) > ORI_BINS+4)
66 | im(iis,jjs,1) = w(i,j,ORI_BINS+4+1);
67 | im(iis,jjs,2) = w(i,j,ORI_BINS+4+2);
68 | im(iis,jjs,3) = w(i,j,ORI_BINS+4+3);
69 | end
70 |
71 | % draw the lines
72 | for k = 1:ORI_BINS,
73 | im(iis,jjs,1) = im(iis,jjs,1) + bim(:,:,k) * w(i,j,k);
74 | im(iis,jjs,2) = im(iis,jjs,2) + bim(:,:,k) * w(i,j,k);
75 | im(iis,jjs,3) = im(iis,jjs,3) + bim(:,:,k) * w(i,j,k);
76 | end
77 | end
78 | end
79 |
80 |
81 |
--------------------------------------------------------------------------------
/track_dp/dynprog_chain.cc:
--------------------------------------------------------------------------------
1 | // JSS3 - 2012-6-21
2 | #include "mex.h"
3 | #include "matrix.h"
4 | #include "../mex/compat.h"
5 | #include
6 | #include
7 | #include
8 |
9 | using std::numeric_limits;
10 | using std::max;
11 | using std::min;
12 |
13 | // Undocumented Features!
14 | extern "C" int mxUnshareArray(mxArray *pa, int level);
15 | extern "C" int mxIsSharedArray(mxArray* pa);
16 | extern "C" mxArray *mxCreateSharedDataCopy(const mxArray *pr);
17 |
18 | #define OCCLUDED isnan
19 | #define INF (numeric_limits::infinity())
20 |
21 | #ifndef round(x)
22 | #define round(x) (x<0?ceil((x)-0.5):floor((x)+0.5))
23 | #endif
24 |
25 | static double rect_overlap(double newX1, double newY1, double newX2, double newY2,
26 | double oldX1, double oldY1, double oldX2, double oldY2)
27 | {
28 | // intersection
29 | double
30 | int_x1 = max(newX1,oldX1),
31 | int_y1 = max(newY1,oldY1),
32 | int_x2 = min(newX2,oldX2),
33 | int_y2 = min(newY2,oldY2);
34 | double
35 | int_w = int_x2 - int_x1 + 1,
36 | int_h = int_y2 - int_y1 + 1;
37 | double int_ar = int_w*int_h;
38 |
39 | // area new
40 | double
41 | new_w = newX2 - newX1 + 1,
42 | new_h = newY2 - newY1 + 1;
43 | double new_ar= new_w*new_h;
44 |
45 | // area old
46 | double
47 | old_w = oldX2 - oldX1 + 1,
48 | old_h = oldY2 - oldY1 + 1;
49 | double old_ar= old_w*old_h;
50 |
51 | if(int_w <= 0 || int_h <= 0)
52 | return -1;
53 | else
54 | return int_ar/(new_ar+old_ar-int_ar);
55 | }
56 |
57 | static double cost_pw_corner(double newX1, double newY1, double newX2, double newY2,
58 | double oldX1, double oldY1, double oldX2, double oldY2)
59 | {
60 | double cost;
61 | if(!OCCLUDED(newX1) && !OCCLUDED(oldX1))
62 | {
63 | // neither is occluded
64 | double cost_tl = (newX1-oldX1)*(newX1-oldX1)+(newY1-oldY1)*(newY1-oldY1);
65 | double cost_br = (newX2-oldX2)*(newX2-oldX2)+(newY2-oldY2)*(newY2-oldY2);
66 | cost = (cost_tl+cost_br)/2;
67 | }
68 | else
69 | {
70 | cost = 0.0;
71 | }
72 | return cost;
73 | }
74 |
75 | static double cost_pw_infi(double newX1, double newY1, double newX2, double newY2,
76 | double newOcc, double newEmg,
77 | double oldX1, double oldY1, double oldX2, double oldY2,
78 | double oldOcc, double oldEmg)
79 | {
80 | int dp_min_time_occluded = 25;
81 | int oldTime = round(oldY2);
82 | int newTime = round(newY2);
83 |
84 | if(!OCCLUDED(newX1) && OCCLUDED(oldX1))
85 | {
86 | // leaving occlusion
87 | if(oldTime >= dp_min_time_occluded && newEmg > .5)
88 | return 0;
89 | else
90 | return INF;
91 | }
92 | else if(OCCLUDED(newX1) && !OCCLUDED(oldX1))
93 | {
94 | // moving into occlusion
95 | if(newTime == 0 && oldOcc > .5)
96 | return 0;
97 | else
98 | return INF;
99 | }
100 | else if(OCCLUDED(oldX1))
101 | {
102 | // staying in occlusion
103 | if(oldTime + 1 == newTime || (newTime == oldTime && newTime >= dp_min_time_occluded))
104 | return 0.0;
105 | else
106 | return INF;
107 | }
108 | else
109 | {
110 | // staying visible
111 | //double maxDist = 25;
112 | //double cost_pw = sqrt(cost_pw_corner(newX1, newY1, newX2, newY2,
113 | // oldX1, oldY1, oldX2, oldY2));
114 | //if(cost_pw > maxDist)
115 | // return INF;
116 | // else
117 | // return 0.0;
118 |
119 | double o = rect_overlap(newX1, newY1, newX2, newY2,
120 | oldX1, oldY1, oldX2, oldY2);
121 | if(o > .25)
122 | return 0.0;
123 | else
124 | return INF;
125 | }
126 | }
127 |
128 | static void do_dynprog_chain(int newStates_count,int oldStates_count,
129 | double*new_states,uint32_t*bps,
130 | double*old_states,double*new_dets,double*projRects)
131 | {
132 | // relax each edge
133 | for(int newIter = 0; newIter < newStates_count; newIter++)
134 | {
135 | // extract the new state
136 | double newX1 = *(new_states + newStates_count*0 + newIter);
137 | double newY1 = *(new_states + newStates_count*1 + newIter);
138 | double newX2 = *(new_states + newStates_count*2 + newIter);
139 | double newY2 = *(new_states + newStates_count*3 + newIter);
140 | double newCost = *(new_states + newStates_count*4 + newIter);
141 | // extract the corresponding detection
142 | double detX1 = *(new_dets + newStates_count*0 + newIter);
143 | double detY1 = *(new_dets + newStates_count*1 + newIter);
144 | double detX2 = *(new_dets + newStates_count*2 + newIter);
145 | double detY2 = *(new_dets + newStates_count*3 + newIter);
146 | double detResp = *(new_dets + newStates_count*4 + newIter);
147 | double detOcc = *(new_dets + newStates_count*5 + newIter);
148 | double detEmg = *(new_dets + newStates_count*6 + newIter);
149 | // extract the back pointer
150 | uint32_t*backPtr = &bps[newIter];
151 |
152 | for(int oldIter = 0; oldIter < oldStates_count; oldIter++)
153 | {
154 | // extract the old state
155 | double oldX1 = *(old_states + oldStates_count*0 + oldIter);
156 | double oldY1 = *(old_states + oldStates_count*1 + oldIter);
157 | double oldX2 = *(old_states + oldStates_count*2 + oldIter);
158 | double oldY2 = *(old_states + oldStates_count*3 + oldIter);
159 | double oldCost = *(old_states + oldStates_count*4 + oldIter);
160 | double oldOcc = *(old_states + oldStates_count*5 + oldIter);
161 | double oldEmg = *(old_states + oldStates_count*6 + oldIter);
162 | if(isnan(oldCost))
163 | continue;
164 | // extract the old LK Projection
165 | double projX1 = *(projRects + (oldStates_count)*0 + oldIter);
166 | double projY1 = *(projRects + (oldStates_count)*1 + oldIter);
167 | double projX2 = *(projRects + (oldStates_count)*2 + oldIter);
168 | double projY2 = *(projRects + (oldStates_count)*3 + oldIter);
169 |
170 | // compute the cost
171 | double lcl_cost = -detResp;
172 | //double corner_cost = cost_pw_corner(detX1, detY1, detX2, detY2,
173 | // projX1, projY1, projX2, projY2);
174 | double pw_cost = cost_pw_infi(detX1, detY1, detX2, detY2, detOcc, detEmg,
175 | projX1, projY1, projX2, projY2, oldOcc, oldEmg);
176 | double cost = lcl_cost + pw_cost + oldCost;
177 |
178 | // relax
179 | if(cost <= newCost)
180 | {
181 | //mexPrintf("allowing connection from: %f %f %f %f\n",oldX1,oldY1,oldX2,oldY2);
182 | //mexPrintf("\t to: %f %f %f %f\n",detX1,detY1,detX2,detY2);
183 | //mexPrintf("\tcorner_cost = %f\n",corner_cost);
184 | //mexPrintf("\t pwCost = %f\n",pw_cost);
185 | newCost = *(new_states + newStates_count*4 + newIter) = cost;
186 | *backPtr = (uint32_t)(oldIter+1);
187 | }
188 | }
189 | }
190 | }
191 |
192 | // do dynamic programming on a markov chain.
193 | // [states,bp] = dynprog_chain(states,projRects,new_detections);
194 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
195 | {
196 | // check arguments
197 | if (nrhs != 3)
198 | mexErrMsgTxt("usage: [states,bp] = dynprog_chain(states,oldRects,new_detections)");
199 | if (nlhs != 2)
200 | mexErrMsgTxt("usage: [states,bp] = dynprog_chain(states,oldRects,new_detections)");
201 | if (mxIsDouble(prhs[0]) == false) mexErrMsgTxt("states is not double.");
202 | if (mxIsDouble(prhs[1]) == false) mexErrMsgTxt("projRects is not double.");
203 | if (mxIsDouble(prhs[2]) == false) mexErrMsgTxt("new_detections is not double.");
204 |
205 | // get sizes
206 | mwSize newStates_count = mxGetM(prhs[2]);
207 | mwSize oldStates_count = mxGetM(prhs[0]);
208 |
209 | // init the output matrices
210 | plhs[0] = mxCreateDoubleMatrix(newStates_count,5,mxREAL);
211 | plhs[1] = mxCreateNumericMatrix(newStates_count,1,mxUINT32_CLASS,mxREAL);
212 |
213 | // get out ptrs
214 | double *new_states = mxGetPr(plhs[0]); // 5 column
215 | uint32_t*bps = (uint32_t*)mxGetData(plhs[1]);
216 | // get in ptrs
217 | double *old_states = mxGetPr(prhs[0]); // 5 column
218 | double *new_dets = mxGetPr(prhs[2]); // 5 column
219 | double *projRects = mxGetPr(prhs[1]); // 4 column
220 |
221 | // init the outputs to defautl values
222 | for(int newIter = 0; newIter < newStates_count; newIter++)
223 | {
224 | *(new_states + newStates_count*0 + newIter) = *(new_dets + newStates_count*0 + newIter);
225 | *(new_states + newStates_count*1 + newIter) = *(new_dets + newStates_count*1 + newIter);
226 | *(new_states + newStates_count*2 + newIter) = *(new_dets + newStates_count*2 + newIter);
227 | *(new_states + newStates_count*3 + newIter) = *(new_dets + newStates_count*3 + newIter);
228 | *(new_states + newStates_count*4 + newIter) = INF;
229 | }
230 | for(int bIter = 0; bIter < newStates_count; bIter++)
231 | bps[bIter] = 0;
232 |
233 | // now we can actually do some dynamic programming?
234 | do_dynprog_chain(newStates_count,oldStates_count,
235 | new_states,bps,
236 | old_states,new_dets,projRects);
237 | }
238 |
239 |
--------------------------------------------------------------------------------
/track_dp/track_dp.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-14
2 | % Dynamic Programming Motion Model for HoG-SVM
3 | % based tracker.
4 | % old_boxes : [0 0 0 0 0] if we don't know the position for the
5 | % frame otherwise we put [x y w h r].
6 | % track_dp(vidName,model,old_boxes,weights)
7 | function [trajectory,model,f1,backPtrs,track_forward] = track_dp(varargin)
8 | tracker = DPTracker;
9 | [trajectory,model,f1,backPtrs,track_forward] = tracker.track_dp(varargin{:});
10 | end
11 |
--------------------------------------------------------------------------------
/track_dp/track_dp_backward.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-14
2 | % backwards pass of a dynamic program
3 | function boxes = track_dp_backward(vidName,backPtrs,show)
4 | if nargin < 3
5 | show = 1;
6 | end
7 |
8 | % find the index of the least cost bb
9 | bbs = backPtrs{numel(backPtrs)}.boxes;
10 | ptrs= backPtrs{numel(backPtrs)}.bPtr;
11 | [void,idx] = min(bbs(:,5));
12 | assert(idx > 0);
13 | k_gts = rectBtoK(gt_load(vidName)); % so we can live plot f1 score
14 |
15 | % init the output...
16 | boxes = zeros(numel(backPtrs),5);
17 | backBox = backPtrs{numel(backPtrs)}.boxes(idx,:);
18 | boxes(end,:) = backBox(:,1:size(boxes,2));
19 | scorer = track_scorer();
20 |
21 | % backwards pass
22 | for frameIter = (numel(backPtrs)-1):-1:0
23 | %
24 | fprintf('\n Dynamic Program Backward %d of %d',frameIter,numel(backPtrs));
25 |
26 | % current frame info...
27 | bbs = backPtrs{frameIter+1}.boxes;
28 | ptrs= backPtrs{frameIter+1}.bPtr;
29 |
30 | % walk back
31 | bb = bbs(idx,:);
32 | if numel(ptrs) == 1
33 | idx = ptrs(1);
34 | else
35 | idx = ptrs(idx,:);
36 | end
37 | assert(idx > 0 || isnan(idx));
38 |
39 | % yield it!
40 | boxes(frameIter+1,:) = bb(:,1:size(boxes,2));
41 | % plot
42 | scorer = scorer.put(k_gts(frameIter+1,:),bb);
43 | if show
44 | showBox(get_frame(vidName,frameIter),bb);
45 | f1 = scorer.score();
46 | xlabel(['f1 = ' num2str(f1)]);
47 | drawnow;
48 | end
49 |
50 | if isnan(idx)
51 | break;
52 | end
53 | end
54 | fprintf('\n\n')
55 | end
56 |
--------------------------------------------------------------------------------
/track_dp/track_dp_forward.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-14
2 | % old_boxes contains information we assume about the trajectory.
3 | % If we don't know the location of an object at a point of time,
4 | % we set that row of old_boxes to [0 0 0 0 0].
5 | function [boxes,detections,backPtrs] = track_dp_forward(vidName, ...
6 | model,gts, ...
7 | old_boxes,weights)
8 | if nargin < 2
9 | model = Model('gen',vidName,[],[],[0]);
10 | end
11 | if nargin < 3
12 | gts = rectBtoK(gt_load(vidName));
13 | end
14 | if nargin < 4
15 | old_boxes = [];
16 | end
17 | if nargin < 5
18 | weights = [];
19 | end
20 |
21 | tracker = DPTracker;
22 | [boxes,detections,backPtrs] = tracker.forward(vidName,model,gts,old_boxes,weights);
23 | end
24 |
--------------------------------------------------------------------------------
/track_dp/track_dp_forward_augment_states.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012.5.10
2 | % new_detections : the states detected in the current frame
3 | % detections : the states in the previous frame.
4 | function new_detections = track_dp_forward_augment_states(model, ...
5 | new_detections,detections,vidName,frameIter)
6 | %fprintf('+track_dp_forward_augment_states\n');
7 | assert(isscalar(frameIter));
8 | imM = get_frame(vidName,frameIter-1);
9 | imN = get_frame(vidName,frameIter);
10 |
11 | % HERE BE DRAGONS (PARAMS)
12 | % add the occluded state
13 | % OCC_COST = cfg('hog_svm/occlusion_cost');
14 | OCC_COST = model.occ_thresh();
15 | % generate occlusion states
16 | new_detections = track_dp_gen_occlusions...
17 | (detections,new_detections,cfg('dp_min_time_occluded'),OCC_COST);
18 |
19 | % generate the LK tracked state...
20 | visibleDetections = ...
21 | detections(find(~gt_occluded(detections)),:);
22 | % shrink scales are only required for detections.
23 | visibleDetections = flipdim(nms(visibleDetections,.75,model.getScaleX(),model.getScaleY()),1);
24 | lkImax = min(5,size(visibleDetections,1));
25 | for lkI = 1:lkImax
26 | %fprintf('track_dp_forward_augment_states: LK State %d\n',...
27 | % lkI);
28 | if lkI > size(visibleDetections,1)
29 | break;
30 | end
31 | best_det = visibleDetections(lkI,:);
32 | if cfg('use_lk')
33 | % it seems my implementation is quite slow...
34 | %[lk_rect,failed] = LucasKanade(best_det(1:4),imM,imN,0,0); % Use *my* implementation
35 | lk_rect = tldTracking(best_det',imM,imN)';
36 | lk_rect = rect_correct_aspect(lk_rect,model.getAspect());
37 | else
38 | lk_rect = best_det(:,1:4);
39 | end
40 | %fprintf('track_dp_forward_augment_states: LK Projection Complete\n');
41 |
42 | % add LK state with score and occ prob.
43 | lk_out_of_frame = rect_overlap(lk_rect,[0 0 size(imM,2) size(imN,1)]) <= 0;
44 | imsz = rect_size(rect_image(imN));
45 | dtsz = rect_size(lk_rect);
46 | lk_too_large = any(dtsz >= imsz);
47 | if lk_out_of_frame || lk_too_large
48 | %new_detections = [new_detections; NaN NaN NaN NaN -OCC_COST];
49 | else
50 | %fprintf('track_dp_forward_augment_states: computing poc\n');
51 | poc = 1;
52 | %fprintf('track_dp_forward_augment_states: computing poe\n');
53 | poe = 1;
54 | %fprintf('track_dp_forward_augment_states: lk score computing\n');
55 | lk_score = model.score_box(imN,lk_rect);
56 | %fprintf('track_dp_forward_augment_states: appending result\n');
57 | new_detections = [new_detections; ...
58 | lk_rect lk_score ...
59 | poc poe];
60 | %fprintf('track_dp_forward_augment_states: iteration complete\n');
61 | end
62 | end
63 | %fprintf('-track_dp_forward_augment_states\n');
64 | end
65 |
--------------------------------------------------------------------------------
/track_dp/track_dp_forward_one.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-5-10
2 | % one forward step of the dynamic program for tracking.
3 | % one iteration of the dynamic program forward pass
4 | % states = states from the previous frame
5 | % (:,5) = responce = -cost
6 | % new_detections = detections in the current frame
7 | % (:,5) = cost = -response
8 | % imM, imN = the previous and current frames, respectively.
9 | % NStates = the number of states
10 | % (Number of Detections + Occluded + LK State)
11 | function [states,backPtrs,states_unsorted] = track_dp_forward_one...
12 | (states, new_detections,imM,imN,~,backPtrs)
13 | %fprintf('+track_dp_forward_one\n');
14 | % predict bbs
15 | oldRects = track_dp_forward_one_predict_rects(states,imM,imN);
16 |
17 | % if all equal inf, all are equally likely.
18 | if all(states(:,5) == inf)
19 | states(:,5) = 0;
20 | end
21 |
22 | % disable occ/emrg constraints
23 | % new_detections(:,6:7) = 1;
24 |
25 | oldRects = cell2mat(oldRects');
26 | oldRects = oldRects(:,1:4);
27 | %keyboard;
28 | assert(size(new_detections,2) >= 7);
29 | assert(size(states,2) >= 7);
30 | [states,bp] = dynprog_chain(states,oldRects,new_detections);
31 | states = [states(:,1:5) new_detections(:,6:end)];
32 | %keyboard;
33 |
34 | % update the backptrs for a backwards pass if required.
35 | states_unsorted = states;
36 | [states,dIdx] = sortrows(states,5);
37 | if nargin >= 6
38 | backPtrs{end+1} = ...
39 | struct('boxes',states,'bPtr',bp(dIdx));
40 | else
41 | backPtrs = [];
42 | end
43 |
44 | %fprintf('-track_dp_forward_one\n');
45 | end
46 |
47 | function oldRects = track_dp_forward_one_predict_rects(states,imM,imN)
48 | %fprintf('+track_dp_forward_one_predict_rects\n');
49 | % compute the flows for each old rect
50 | oldRects = {};
51 | parfor oldIter = 1:size(states,1)
52 | oldRect = states(oldIter,1:4);
53 |
54 | if ~gt_occluded(oldRect)
55 | if cfg('use_lk')
56 | %Use LK CRF
57 | projection = tldTracking(oldRect',imM,imN)';
58 | if gt_occluded(projection)
59 | % LK failed
60 | projection = oldRect;
61 | end
62 | else
63 | % use use MRF.
64 | projection = oldRect;
65 | end
66 |
67 | % only use LK if it doens't fail.
68 | if ~gt_occluded(projection)
69 | oldRect = projection;
70 | end
71 | end
72 | oldRects{oldIter} = oldRect;
73 | end
74 | %fprintf('-track_dp_forward_one_predict_rects\n');
75 | end
76 |
77 |
--------------------------------------------------------------------------------
/track_dp/track_dp_gen_occlusions.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-6-5 Genreate occluded states for a DP tracker
2 | % stash the time occluded in the 4th element.
3 | function [boxes] = track_dp_gen_occlusions(states,boxes,max_occlusions,occ_cost)
4 | numStates = size(states,1);
5 | for stateIter = 1:numStates
6 | curState = states(stateIter,:);
7 | if gt_occluded(curState)
8 | occlusionTime = curState(:,4);
9 | curState(:,4) = occlusionTime + 1;
10 | curState(:,5) = occ_cost;
11 | if occlusionTime <= max_occlusions
12 | boxes(end+1,:) = nan(size(boxes(end,:)));
13 | boxes(end,1:size(curState,2)) = curState;
14 | end
15 | end
16 | end
17 | boxExtraData = size(boxes,2) - 5;
18 | boxes = [boxes; nan(1,3) 0 occ_cost nan(1,boxExtraData)];
19 | %keyboard;
20 | end
21 |
--------------------------------------------------------------------------------
/track_dp/track_dp_init.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.5.14
2 | % Setup the data structures for a dynamic program tracker
3 | function [NDetStates,NStates,detections,boxes,backPtrs] = ...
4 | track_dp_init(k_gts,extraStates)
5 | if nargin < 2
6 | extraStates = 2;
7 | end
8 |
9 | NDetStates = 25;
10 | NStates = NDetStates + extraStates; % Occluded State and LK Projected State
11 | detections = repmat([k_gts(1,:) 0 0 0],NStates,1);
12 |
13 | boxes = [k_gts(1,1:4), inf];
14 | backPtrs = {struct('boxes',detections,'bPtr',nan)};
15 | %backPtrs = {struct('boxes',detections,'bPtr',NaN(NStates,1))};
16 | end
17 |
--------------------------------------------------------------------------------
/track_dp/track_dp_lcl.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-15
2 | % get the local score weight
3 | function L = track_dp_lcl()
4 | % HERE BE DRAGONS (paramters)
5 | global GBL_PARM_TRACK_DP_L;
6 | if isempty(GBL_PARM_TRACK_DP_L)
7 | %L = 15625;
8 | L = cfg('cost_dp_lcl');
9 | %L = 625;
10 | else
11 | L = GBL_PARM_TRACK_DP_L;
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/trackers/track_offline.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.8.6
2 | % Track Online
3 | function [k_track,f1s] = track_offline(vidName)
4 | % DP Track until we find enough new data to learn, then learn
5 | % and track.
6 | model = genModel(vidName);
7 | [k_track,~,f1s,~,~] = track_dp(vidName,model); % DP-online
8 | tracks = {k_track};
9 | lambda = zeros(vidLen(vidName),1);
10 | lambda(1) = 1;
11 |
12 | % run the offline algorithm
13 | batch_count = 6;
14 | for iter = 1:batch_count
15 | % SELECT:A
16 | last_lambda = lambda;
17 | % remove retained *NEW* occlusions.
18 | if iter > 1
19 | retained = last_lambda & lambda;
20 | ret_occ = retained & ...
21 | gt_occluded(tracks{end}) & ...
22 | ~gt_occluded(tracks{end-1});
23 | fprintf('select purne: removing %d retained occlusions\n',sum(lambda(ret_occ)));
24 | lambda(ret_occ) = 0;
25 | end
26 | % SELECT: B
27 | % how much should we add?
28 | total_ct = .5 .* vidLen(vidName);
29 | b = nthroot(total_ct,batch_count);
30 | cur_ct = clamp(1,round(b.^iter),total_ct);
31 | fprintf('will select %d frames\n',cur_ct);
32 | % add that many
33 | deltas = compute_tsvm_deltas(vidName,model,k_track);
34 | [~,addI] = sort(deltas);
35 | lambda = zeros(vidLen(vidName),1);
36 | lambda(1) = 1; % never drop the first frame
37 | lambda(addI(1:ceil(cur_ct))) = 1;
38 | % SELECT: C
39 | % remove excessive drift
40 | if iter > 1
41 | retained = last_lambda;
42 | for frameIter = (find(retained)-1)'
43 | k_old = tracks{end-1}(frameIter+1,:);
44 | k_new = tracks{end}(frameIter+1,:);
45 | if rect_overlap(k_old,k_new) < .95
46 | fprintf('select_prune: to much drift to retain\n');
47 | obj.lambda(frameIter+1) = 0;
48 | end
49 | end
50 | end
51 |
52 | % learn
53 | model = Model('gen',vidName,[],[],[]);
54 | model = model.train_all(vidName,k_track,lambda);
55 |
56 | % track
57 | [k_track,~,f1,~] = track_dp(vidName,model); % DP-offline
58 | tracks{end+1} = k_track;
59 | f1s = [f1s f1];
60 | end
61 |
62 | % show the f1s.
63 | f1s = f1s
64 | end
65 |
66 |
67 |
--------------------------------------------------------------------------------
/trackers/track_online.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.8.6
2 | % Track Online
3 | function [k_track,f1s] = track_online(vidName)
4 | % DP Track until we find enough new data to learn, then learn
5 | % and track.
6 | model = genModel(vidName);
7 | [~,~,f1s,~,k_track] = track_dp(vidName,model); % DP-online
8 | k_track2 = k_track;
9 |
10 | % wait until we've seen enough to learn...
11 | for frameIter = 0:size(k_track,1)-1
12 | fprintf('track_olol %d of %d\n',frameIter,size(k_track,1));
13 |
14 | % See if we are ready to update w.
15 | [f,e] = log2(frameIter);
16 | powOf2 = f == .5;
17 | if powOf2 && frameIter >= 4
18 | % select
19 | deltas = compute_tsvm_deltas(vidName,model,k_track2(1:frameIter+1,:));
20 | [~,addI] = sort(deltas);
21 | lambda = zeros(vidLen(vidName),1);
22 | lambda(addI(1:ceil(.50.*frameIter))) = 1;
23 |
24 | % learn
25 | fprintf('track_olol: learning\n');
26 | model = Model('gen',vidName,[],[],[]);
27 | model = model.train_all(vidName,k_track2,lambda);
28 |
29 | % track
30 | [~,~,f1,~,k_track2] = track_dp(vidName,model); % DP-online
31 | f1s = [f1s f1];
32 | k_track(frameIter+1:end,:) = k_track2(frameIter+1:end,:);
33 | end
34 | end
35 |
36 | % show the f1s.
37 | f1s = f1s
38 | end
39 |
40 |
--------------------------------------------------------------------------------
/trackers/track_tbd.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012-6-13
2 | % simple track by detection algorithm.
3 | function [track,model,f1] = track_tbd(vidName,model)
4 | matlab_init(vidName);
5 | % init paths, prngs, mex etc. etc.
6 | gts = rectBtoK(gt_load(vidName));
7 | imM = get_frame(vidName,0);
8 | if nargin < 2 || isempty(model)
9 | model = Model('gen',vidName,[],[],[0]);
10 | end
11 | track = [];
12 | NDetStates = 5;
13 | showModel(model.w);
14 | top_detections = model.detect_all(size(gts,1),vidName,NDetStates);
15 |
16 | scorer = track_scorer();
17 | for frameIter = 0:(size(gts,1)-1)
18 | imN = get_frame(vidName,frameIter);
19 | top_dets = [top_detections{frameIter+1}; nan(1,4) -1 1 1];
20 | %keyboard;
21 | top_dets = flipdim(sortrows(top_dets,5),1);
22 | top_det = top_dets(1,:);
23 | showBoxes(imN,top_detections{frameIter+1});
24 | track(end+1,:) = top_det;
25 |
26 | % show the score
27 | scorer = scorer.put(gts(frameIter+1,:),top_det);
28 | f1 = scorer.score();
29 | xlabel(['f1 = ' num2str(f1)]);
30 | drawnow;
31 | end
32 |
33 | [p,r] = plot_resp(rectKtoB(gts),track,vidName);
34 | f1 = f1score(p,r)
35 | end
36 |
--------------------------------------------------------------------------------
/video/clamp.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-13
2 | % restrict a value to a range...
3 | function val = clamp(var_min,val,var_max)
4 | val = max(var_min,val);
5 | val = min(var_max,val);
6 | end
7 |
--------------------------------------------------------------------------------
/video/f1score.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-03-20
2 | function f1 = f1score(prec,recl)
3 | f1 = 2*prec*recl/(prec+recl);
4 | end
5 |
--------------------------------------------------------------------------------
/video/get_frame.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-06
2 | % function to grab a frame from a video
3 | % frame zero is the first frame.
4 | function [im,filename] = get_frame(vidName,frameNum)
5 | % get the frames filename
6 | global G_HOME;
7 | persistent firstFrame lastFrame lastVidName;
8 | if isempty(firstFrame) || ~strcmp(vidName,lastVidName)
9 | [firstFrame,lastFrame] = get_vid_range(vidName);
10 | lastVidName = vidName;
11 | end
12 | frameNum = frameNum + firstFrame;
13 |
14 | % debug
15 | assert(frameNum <= lastFrame);
16 |
17 | % read the image
18 | filename = sprintf('%s%s/imgs/img%.5d.png', ...
19 | datapath(),vidName,frameNum);
20 | im = imrgb(imread(filename));
21 | end
22 |
--------------------------------------------------------------------------------
/video/get_vid_range.m:
--------------------------------------------------------------------------------
1 | % JSS3 - 2012.8.27
2 | % return the first and last frame to use for a labeled video.
3 | function [first,last] = get_vid_range(vidName)
4 | frames_filename = sprintf('%s%s/%s_frames.txt', ...
5 | datapath(),vidName,vidName);
6 | framesData = csvread(frames_filename);
7 | first = framesData(1);
8 | last = framesData(2);
9 | end
10 |
--------------------------------------------------------------------------------
/video/gt_load.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-06
2 | % function to load the gt for a video.
3 | % format should be 1 gt per row
4 | % each row should be [x1 y1 w h]
5 | function gts = gt_load(vidName)
6 | % prep the gt
7 | gt_file = [datapath() vidName '/' vidName ...
8 | '_gt.txt'];
9 | gts = importdata(gt_file);
10 |
11 | % pad handle short gts.
12 | [first,last] = get_vid_range(vidName);
13 | pad = (last - first + 1) - size(gts,1);
14 | gts = [gts; zeros(pad,size(gts,2))];
15 |
16 | % handle Kalal [x1 y1 x2 y2] format files.
17 | if exist(['~/workspace/data/tracking/' vidName '/kalal'],'file')
18 | %'kalal format gt'
19 | gts = rectKtoB(gts);
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/video/gt_occluded.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-03-20
2 | % JSS3 2012-5-14 extended to support multiple inputs.
3 | % Function to tell if a gt matrix is valid
4 | function occluded = gt_occluded(gt)
5 | % only examine the first four elements
6 | gt = gt(:,1:4);
7 |
8 | % check for nan
9 | occluded = zeros(size(gt,1),1);
10 |
11 | % nan => occlusion
12 | occluded = occluded | any(isnan(gt),2);
13 | end
14 |
15 |
--------------------------------------------------------------------------------
/video/gt_valid.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-03-20
2 | % JSS3 2012-5-14 : added support for multiple ground truths
3 | % Function to tell if a gt matrix is valid
4 | function valid = gt_valid(gt)
5 | valid = ones(size(gt,1),1);
6 |
7 | % check for bad size
8 | if(size(gt,2) < 4)
9 | valid = zeros(size(gt,1),1);
10 | return;
11 | end
12 |
13 | % check for all zero
14 | valid = valid & any(gt ~= 0,2);
15 | end
16 |
--------------------------------------------------------------------------------
/video/hashMat.cc:
--------------------------------------------------------------------------------
1 | // JSS3 2012-5-29
2 | // fast hash using OpenSSL
3 |
4 | #include "mex.h"
5 | #include
6 |
7 | typedef unsigned char uchar;
8 |
9 | // hash = hashMat(mat);
10 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
11 | {
12 | // check args
13 | if(nrhs != 1 || nlhs != 1)
14 | mexErrMsgTxt("syntax: hash = hashMat(mat)");
15 |
16 | // get data
17 | // mxGetData
18 | void * data = mxGetData(prhs[0]);
19 | // mxGetNumberOfElements
20 | size_t numel = mxGetNumberOfElements(prhs[0]);
21 | // mxGetElementSize
22 | size_t elSz = mxGetElementSize(prhs[0]);
23 |
24 | // compute hash
25 | uchar hash[MD5_DIGEST_LENGTH+1/*in bytes*/];
26 | MD5((uchar*)data,elSz*numel,(uchar*)hash);
27 | hash[MD5_DIGEST_LENGTH] = 0;
28 |
29 | // extract hash to string
30 | // 1 8-bit byte
31 | // 4 bits per hex char.
32 | char hashString[2*MD5_DIGEST_LENGTH+1];
33 | for(int iter = 0; iter < MD5_DIGEST_LENGTH; iter++)
34 | {
35 | snprintf(hashString+2*iter,3,"%02x",hash[iter]);
36 | //mexPrintf("hash[iter] = %02x\n",hash[iter]);
37 | //mexPrintf("hashString = %s\n",hashString);
38 | }
39 | hashString[2*MD5_DIGEST_LENGTH] = 0;
40 |
41 | // return
42 | plhs[0] = mxCreateString(hashString);
43 | }
44 |
--------------------------------------------------------------------------------
/video/imcropr.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-5-25
2 | % simple crop with replication to maintain size...
3 | function IC = imcropr(I,k_cr)
4 | % validate that the input is of resonable size...
5 | imsz = rect_size(rect_image(I));
6 | bbsz = rect_size(k_cr);
7 | if any(bbsz > 2.*imsz)
8 | warning('failed to crop image due to size error');
9 | % return an invalid crop for something to massive
10 | % (trying to compute the massive crop would result in out
11 | % of memory crashes).
12 | IC = [];
13 | return;
14 | end
15 |
16 | % extract stats
17 | iSize = size(I);
18 | i_h = iSize(1);
19 | i_w = iSize(2);
20 |
21 | % find the padding
22 | pad_t = round(max(0,0-k_cr(2)));
23 | pad_b = round(max(0,k_cr(4)-i_h));
24 | pad_l = round(max(0,0-k_cr(1)));
25 | pad_r = round(max(0,k_cr(2)-i_w));
26 |
27 | % do the crop!
28 | IC = imcrop(I,rectKtoB(k_cr));
29 | IC = padarray(IC,[pad_t pad_l],'replicate','pre');
30 | IC = padarray(IC,[pad_b pad_r],'replicate','post');
31 | end
32 |
--------------------------------------------------------------------------------
/video/imgray.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-11
2 | % color to grayscale.
3 | function im2 = imgray(im)
4 | [H,W,D] = size(im);
5 | if D == 3
6 | im2 = mean(im,3);
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/video/imrgb.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-06
2 | % function to make rgb or grayscale image rgb.
3 | function im = imrgb(im)
4 | [H,W,D] = size(im);
5 | if D == 1
6 | % we need to duplicate channels
7 | im(:,:,2) = im(:,:,1);
8 | im(:,:,3) = im(:,:,1);
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/video/score_track_file.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-5-25
2 | % load a track file and return it's f1 score
3 | function [f1,p,r,displacement,OR_OCC,acc] = score_track_file(vidName,trackFile,interpolate_occlusion)
4 | % default args
5 | if nargin < 3
6 | interpolate_occlusion = 0;
7 | end
8 |
9 | % memoize
10 | memo = [cfg('tmp_dir') 'score_track_file_' ...
11 | vidName '-' ...
12 | hashMat(trackFile) '-' ...
13 | num2str(interpolate_occlusion) '.mat'];
14 | if exist(memo,'file')
15 | load(memo);
16 | return;
17 | end
18 |
19 | % get the track data
20 | if ischar(trackFile)
21 | S = load(trackFile);
22 | if isstruct(S)
23 | % .mat files load struct
24 | k_track = S.track;
25 | else
26 | % .csv files load a mat
27 | k_track = S;
28 | end
29 | else
30 | k_track = trackFile;
31 | end
32 | % do we need to interpolate occlusions?
33 | if nargin > 2 && interpolate_occlusion
34 | fprintf('interpolating occlusion\n');
35 | %keyboard;
36 | k_track = interp_occ(k_track);
37 | end
38 |
39 | % load the ground truth.
40 | k_gts = rectBtoK(gt_load(vidName));
41 |
42 | % check the sizes
43 | if(size(k_track,1) ~= size(k_gts,1))
44 | fprintf('%d ~= %d\n',size(k_track,1),size(k_gts,1));
45 | warning('score_track_file: length mismatch');
46 | end
47 |
48 | % score the track
49 | scorer = track_scorer();
50 | to = min(vidLen(vidName)-1,size(k_track,1)-1);
51 | for frameIter = 0:to
52 | scorer = scorer.put(k_gts(frameIter+1,:),...
53 | k_track(frameIter+1,:));
54 | end
55 | [f1,p,r,displacement,OR_OCC,acc] = scorer.score();
56 |
57 | % cache the results
58 | save(memo,'f1','p','r','displacement','OR_OCC','acc');
59 | end
60 |
--------------------------------------------------------------------------------
/video/score_track_one.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-04-06
2 | % update the counts for the p/r calcuation
3 | function [l, c, g, n] = score_track_one(b_gt,k_box,thresh)
4 | if nargin < 3
5 | thresh = cfg('correct_overlap');
6 | end
7 |
8 | % correctly accepted
9 | c = zeros(size(k_box,1),1);
10 | % ground truth accepted
11 | g = 0;
12 | % accepted by tracker
13 | n = zeros(size(k_box,1),1);
14 | % is the frame labeled?
15 | l = 0;
16 |
17 | % ignore frames without a ground truth
18 | if ~gt_valid(b_gt)
19 | return;
20 | end
21 | l = 1;
22 |
23 | % did the b_gt accept the frame?
24 | if(~gt_occluded(b_gt))
25 | g = 1;
26 | end
27 |
28 | % did the tracker accept the frame?
29 | n = ~gt_occluded(k_box);
30 |
31 | % was the acceptence correct?
32 | overlaps = rect_overlap(k_box,rectBtoK(b_gt));
33 | c = ~gt_occluded(b_gt) & ~gt_occluded(k_box) & overlaps > thresh;
34 | end
35 |
--------------------------------------------------------------------------------
/video/track_scorer.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-5-23
2 | % this is a class to simplify the scoring of tracks in MATLAB
3 | classdef track_scorer
4 | properties (SetAccess = private)
5 | % precision = correctly accepted / number accepted
6 | % recall = correctly accepted / gt accepted
7 | cAccept = 0;
8 | gAccept = 0;
9 | nAccept = 0;
10 | % displacement score info.
11 | agg_displacement = 0;
12 | N = 0;
13 | OR_OCC = 0;
14 | % simple accuracy
15 | total_counted = 0;
16 | total_correct = 0;
17 | end
18 |
19 | % ctor
20 | %function scorer = track_scorer()
21 | %end
22 | methods
23 | function scorer = put(scorer,k_gt,k_loc)
24 | if ~gt_valid(k_gt)
25 | return;
26 | end
27 |
28 | % update f1
29 | [l,c,g,n] = score_track_one(rectKtoB(k_gt),k_loc);
30 | scorer.cAccept = scorer.cAccept + c;
31 | scorer.gAccept = scorer.gAccept + g;
32 | scorer.nAccept = scorer.nAccept + n;
33 |
34 | % update displacement error (only meaning without occ)
35 | if ~gt_occluded(k_gt) && ~gt_occluded(k_loc)
36 | scorer.N = scorer.N + 1;
37 | cen_gt = rect_center(k_gt);
38 | cen_lc = rect_center(k_loc);
39 | newDist = pdist2(cen_gt,cen_lc);
40 | assert(~isnan(newDist));
41 | scorer.agg_displacement = scorer.agg_displacement + ...
42 | newDist;
43 | else
44 | % something signals occlusion.
45 | scorer.OR_OCC = scorer.OR_OCC + 1;
46 | end
47 |
48 | % update total correct
49 | scorer.total_counted = scorer.total_counted + 1;
50 | if gt_occluded(k_gt) && gt_occluded(k_loc)
51 | scorer.total_correct = scorer.total_correct + 1;
52 | elseif ~gt_occluded(k_gt) && ~gt_occluded(k_loc) && ...
53 | rect_overlap(k_gt,k_loc) > cfg('correct_overlap')
54 | scorer.total_correct = scorer.total_correct + 1;
55 | end
56 | end
57 |
58 | function [f1,p,r,displacement,OR_OCC,acc] = score(scorer)
59 | p = scorer.cAccept/scorer.nAccept;
60 | r = scorer.cAccept/scorer.gAccept;
61 | f1 = f1score(p,r);
62 | displacement = scorer.agg_displacement ./ scorer.N;
63 | OR_OCC = scorer.OR_OCC;
64 | acc = scorer.total_correct./scorer.total_counted;
65 | end
66 | end
67 | end
68 |
--------------------------------------------------------------------------------
/video/vidLen.m:
--------------------------------------------------------------------------------
1 | % JSS3 2012-5-18
2 | % Return the length of the named video
3 | function len = vidLen(vidName)
4 | gt = gt_load(vidName);
5 | len = size(gt,1);
6 | end
7 |
--------------------------------------------------------------------------------