├── DukeReID.jpg ├── folderList.m ├── script_loadimage.m ├── compute_AP.m ├── LICENSE_DukeMTMC.txt ├── LICENSE_DukeMTMC4ReID.txt ├── kLFDA ├── LFDA.m ├── ComputeKernelTest.m └── ComputeKernel.m ├── script_test.m └── README.md /DukeReID.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NEU-Gou/DukeReID/HEAD/DukeReID.jpg -------------------------------------------------------------------------------- /folderList.m: -------------------------------------------------------------------------------- 1 | function [srcdir foldernames n] = folderList(path) 2 | % After heavily tested, this file should be moved into my toolbox/matlab 3 | % [srcdir foldernames n] = folderList(path) 4 | 5 | listing = dir(path); 6 | idxvalid = cellfun(@(x) strcmp(x(1),'.'),{listing.name}); 7 | listing = listing(~idxvalid); 8 | % listing = listing(3:end); 9 | srcdir = path; 10 | 11 | n = 0; foldernames = []; 12 | for i = 1 : length(listing) 13 | if listing(i).isdir 14 | n = n + 1; 15 | foldernames = cat(1, foldernames, {listing(i).name}); 16 | end 17 | end -------------------------------------------------------------------------------- /script_loadimage.m: -------------------------------------------------------------------------------- 1 | clc 2 | clear 3 | %% 4 | folder = 'ReID'; 5 | [~,caminfo,] = folderList(folder); 6 | imgs = {}; 7 | personID = []; 8 | camID = []; 9 | impath = {}; 10 | cnt = 1; 11 | 12 | 13 | for c = 1:numel(caminfo) 14 | fprintf('Parsing camera %d...\n',c); 15 | camID_tmp = str2num(caminfo{c}(end)); 16 | [~,persons,~] = folderList(fullfile(folder,caminfo{c})); 17 | for p = 1:numel(persons) 18 | iminfo = dir(fullfile(folder,caminfo{c},persons{p},'*.jpg')); 19 | for i = 1:numel(iminfo) 20 | impath_tmp = fullfile(folder,caminfo{c},persons{p},iminfo(i).name); 21 | tmpim = imread(impath_tmp); 22 | imgs{cnt} = tmpim; 23 | personID(cnt) = str2num(persons{p}); 24 | camID(cnt) = camID_tmp; 25 | impath{cnt} = impath_tmp; 26 | cnt = cnt + 1; 27 | end 28 | end 29 | end 30 | 31 | save('DukeReID_images.mat','imgs','personID','camID','impath','-v7.3'); 32 | -------------------------------------------------------------------------------- /compute_AP.m: -------------------------------------------------------------------------------- 1 | function ap = compute_AP(good_image, index) 2 | % good_image: index for correct match 3 | % index: ranked retrival image index 4 | ngood = length(good_image); 5 | 6 | old_recall = 0; 7 | old_precision = 1.0; 8 | ap = 0; 9 | intersect_size = 0; 10 | j = 0; 11 | good_now = 0; 12 | % ngood = ngood - 1; 13 | % tic 14 | for n = 1:length(index) 15 | flag = 0; 16 | if ~isempty(find(good_image == index(n), 1)) 17 | flag = 1; % good image 18 | good_now = good_now+1; 19 | end 20 | % if ~isempty(find(junk_image == index(n), 1)) 21 | % continue; % junk image 22 | % end 23 | 24 | if flag == 1%good 25 | intersect_size = intersect_size + 1; 26 | end 27 | recall = intersect_size/ngood; 28 | precision = intersect_size/(j + 1); 29 | ap = ap + (recall - old_recall)*((old_precision+precision)/2); 30 | old_recall = recall; 31 | old_precision = precision; 32 | j = j+1; 33 | 34 | if good_now == ngood 35 | % toc 36 | return; 37 | end 38 | end 39 | 40 | end 41 | 42 | 43 | -------------------------------------------------------------------------------- /LICENSE_DukeMTMC.txt: -------------------------------------------------------------------------------- 1 | ATTRIBUTION PROTOCOL 2 | 3 | If you use the DukeMTMC data or any data derived from it, please cite the original work as follows: 4 | 5 | @inproceedings{ristani2016MTMC, 6 | title = {Performance Measures and a Data Set for Multi-Target, Multi-Camera Tracking}, 7 | author = {Ristani, Ergys and Solera, Francesco and Zou, Roger and Cucchiara, Rita and Tomasi, Carlo}, 8 | booktitle = {European Conference on Computer Vision workshop on Benchmarking Multi-Target Tracking}, 9 | year = {2016} 10 | } 11 | 12 | and include this license and attribution protocol within any derivative work. 13 | 14 | If you publish data derived from DukeMTMC, the original dataset creators should first be notified. 15 | Any future dataset derived from DukeMTMC should include "DukeMTMC" in the title, as well as link to the 16 | original project website (http://vision.cs.duke.edu/DukeMTMC/). 17 | 18 | The DukeMTMC dataset is made available under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) license. (https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) 19 | 20 | You are free to: 21 | 22 | Share — copy and redistribute the material in any medium or format 23 | Adapt — remix, transform, and build upon the material 24 | 25 | Under the following terms: 26 | 27 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 28 | 29 | NonCommercial — You may not use the material for commercial purposes. 30 | 31 | ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 32 | 33 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 34 | -------------------------------------------------------------------------------- /LICENSE_DukeMTMC4ReID.txt: -------------------------------------------------------------------------------- 1 | ATTRIBUTION PROTOCOL 2 | 3 | If you use the DukeMTMC4ReID data or any data derived from it, please cite our work as follows: 4 | 5 | @InProceedings{gou2017dukemtmc4reid, 6 | author = {Gou, Mengran and Karanam, Srikrishna and Liu, Wenqian and Camps, Octavia and Radke, Richard J.}, 7 | title = {DukeMTMC4ReID: A Large-Scale Multi-Camera Person Re-Identification Dataset}, 8 | booktitle = {The IEEE Conference on Computer Vision and Pattern Recognition (CVPR) Workshops}, 9 | month = {July}, 10 | year = {2017} 11 | } 12 | 13 | and include this license and attribution protocol within any derivative work. 14 | 15 | 16 | If you use the DukeMTMC data or any data derived from it, please cite the original work as follows: 17 | 18 | @inproceedings{ristani2016MTMC, 19 | title = {Performance Measures and a Data Set for Multi-Target, Multi-Camera Tracking}, 20 | author = {Ristani, Ergys and Solera, Francesco and Zou, Roger and Cucchiara, Rita and Tomasi, Carlo}, 21 | booktitle = {European Conference on Computer Vision workshop on Benchmarking Multi-Target Tracking}, 22 | year = {2016} 23 | } 24 | 25 | and include this license and attribution protocol within any derivative work. 26 | 27 | 28 | The DukeMTMC-VideoReID dataset is derived from DukeMTMC dataset (http://vision.cs.duke.edu/DukeMTMC/). 29 | 30 | The DukeMTMC-VideoReID dataset is made available under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) license. (https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) 31 | 32 | You are free to: 33 | 34 | Share — copy and redistribute the material in any medium or format 35 | Adapt — remix, transform, and build upon the material 36 | 37 | Under the following terms: 38 | 39 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 40 | 41 | NonCommercial — You may not use the material for commercial purposes. 42 | 43 | ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 44 | 45 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 46 | 47 | -------------------------------------------------------------------------------- /kLFDA/LFDA.m: -------------------------------------------------------------------------------- 1 | % implemented according to CVPR2013: Local Fisher Discriminant Analysis 2 | % for Pedestrian Re-identification. 3 | % By Fei Xiong, 4 | % ECE Dept, 5 | % Northeastern University 6 | % 2013-11-04 7 | % INPUT 8 | % X: N-by-d data matrix. Each row is a sample vector. 9 | % id: the identification number for each sample 10 | % option: algorithm options 11 | % beta: the parameter of regularizing S_b 12 | % d: the dimensionality of the projected feature 13 | % eps: the tolerence value. 14 | % Note that the kernel trick is used here. 15 | % OUTPUT 16 | % Method: the structure contains the learned projection matrix and 17 | % algorithm parameters setup. 18 | % V: the eigenvalues 19 | function [Method, V]= LFDA(X, id, option) 20 | 21 | T =[]; 22 | V =[]; 23 | display(['begin LFDA ' option.kernel]); 24 | beta= option.beta; 25 | d = option.d; 26 | eps = option.epsilon; 27 | % compute the kernel matrix 28 | Method = struct('rbf_sigma',0); 29 | 30 | if gpuDeviceCount > 0 % use GPU 31 | X = gpuArray(X); 32 | end 33 | [K, Method] = ComputeKernel(X, option.kernel, Method); 34 | % reset GPU memory if used 35 | if gpuDeviceCount > 0 36 | reset(gpuDevice()); 37 | end 38 | K=double(K); 39 | 40 | [Aff] = LocalScalingAffinity(K, option.LocalScalingNeighbor); 41 | temp = repmat(id.^2, 1, length(id)); 42 | temp = temp + temp' - 2*id*id'; 43 | Aw = zeros(size(temp)); 44 | Aw(temp ==0) =1; 45 | nc = sum(Aw); 46 | Aw = bsxfun(@times, Aw, 1./nc); %equation 10 47 | Aw(temp ==0) = Aff(temp ==0) .* Aw(temp ==0) ;%equation 10 48 | Ab = zeros(size(temp)); 49 | Ab(temp ==0) =1; 50 | Ab= bsxfun(@times, Ab, -1./nc); 51 | Ab= 1/length(id) + Ab; %equation 11 52 | Ab(temp ==0) = Aff(temp ==0) .* Ab(temp ==0) ;%equation 11 53 | 54 | Ew = zeros(size(Aff)); 55 | Eb = Ew; 56 | Ew = diag(sum(Aw)) - Aw; % part of equation 8 Ew = sum(Aw_ij*(ei-ej)*(ei-ej)') 57 | Eb = diag(sum(Ab)) - Ab; % part of equation 9 Eb = sum(Ab_ij*(ei-ej)*(ei-ej)') 58 | 59 | Sw = K*Ew*K; % equation 8 (1/2 can be canceled) 60 | Sb = K*Eb*K; % equation 9 (1/2 can be canceled) 61 | Sw =(1-beta)*Sw + beta*trace(Sw)*eye(size(Sw))/size(Sw,1); 62 | [T, V]= eigs(Sb, Sw, d); 63 | T =T'; 64 | Method.name = 'LFDA'; 65 | Method.P=T; 66 | Method.kernel=option.kernel; 67 | Method.Prob = []; 68 | Method.Dataname = option.dataname; 69 | Method.Ranking = []; 70 | Method.Dist = []; 71 | Method.Trainoption=option; 72 | return; 73 | 74 | % equation 1 and 2 from paper: "Self-Tuning Spectral Clustering" 75 | % INPUT 76 | % K: KernelMatrix 77 | % NN: the index of the nearest neighbors used to scaled the distance. 78 | % OUTPUT 79 | % A: Affinity matrix 80 | function [A] = LocalScalingAffinity(K, NN) 81 | 82 | % compute distance in the kernel space using kernel matrix 83 | temp = repmat(diag(K), 1, size(K,1)); 84 | dis = temp + temp' - 2*K; 85 | 86 | [disK, ~]= sort(dis); 87 | disK = sqrt(disK(NN+1,:)); 88 | disK = disK' * disK; 89 | A = exp(-(dis./disK)); 90 | % For a little bit better result (MAYBE) 91 | % A = exp(-sqrt(dis./disK)); 92 | A = A-diag(diag(A)); 93 | return; -------------------------------------------------------------------------------- /kLFDA/ComputeKernelTest.m: -------------------------------------------------------------------------------- 1 | % Calculate the kernel matrix for train and test set. 2 | % TODO: Replace the ComputeKernel function in ComputeKernel.m 3 | % Input: 4 | % Method: the distance learning algorithm struct. In this function 5 | % only field used "kernel", the name of the kernel function. 6 | % train: The data used to learn the projection matric. Each row is a 7 | % sample vector. Ntr-by-d 8 | % test: The data used to test and calculate the CMC for the 9 | % algorithm. Each row is a sample vector. Nts-by-d 10 | function [K_test] = ComputeKernelTest(train, test, Method) 11 | info = whos('test'); 12 | if ~strfind(info.class,'gpu')%(numel(train))>2e4 && (strcmp(Method.kernel, 'chi2') || strcmp(Method.kernel, 'chi2-rbf')) 13 | % if the input data matrix is too large then use parallel computing 14 | % tool box. 15 | % poolobj = parpool; 16 | 17 | switch Method.kernel 18 | case {'linear'} 19 | K_test = train * test'; 20 | case {'chi2'} 21 | parfor i =1:size(test,1) 22 | dotp = bsxfun(@times, test(i,:), train); 23 | sump = bsxfun(@plus, test(i,:), train); 24 | K_test(:,i) = 2* sum(dotp./(sump+1e-10),2); 25 | end 26 | case {'chi2-rbf'} 27 | sigma = Method.rbf_sigma; 28 | parfor i =1:size(test,1) 29 | subp = bsxfun(@minus, test(i,:), train); 30 | subp = subp.^2; 31 | sump = bsxfun(@plus, test(i,:), train); 32 | K_test(:,i) = sum(subp./(sump+1e-10),2); 33 | end 34 | K_test =exp(-K_test./(2*sigma)); 35 | case {'exp'} 36 | parfor i = 1:size(test,1) 37 | diff = bsxfun(@minus,test(i,:),train); 38 | K_test(:,i) = sqrt(sum(diff.^2,2)); 39 | end 40 | K_test = exp(-K_test/(2*Method.rbf_sigma^2)); 41 | case {'poly'} 42 | K_test = (train*test'+1).^2; 43 | 44 | end 45 | % delete(poolobj) 46 | else 47 | switch Method.kernel 48 | case {'linear'} 49 | K_test = train * test'; 50 | case {'chi2'} 51 | for i =1:size(test,1) 52 | dotp = bsxfun(@times, test(i,:), train); 53 | sump = bsxfun(@plus, test(i,:), train); 54 | K_test(:,i) = 2* sum(dotp./(sump+1e-10),2); 55 | end 56 | case {'chi2-rbf'} 57 | sigma = Method.rbf_sigma; 58 | for i =1:size(test,1) 59 | subp = bsxfun(@minus, test(i,:), train); 60 | subp = subp.^2; 61 | sump = bsxfun(@plus, test(i,:), train); 62 | K_test(:,i) = sum(subp./(sump+1e-10),2); 63 | end 64 | K_test =exp(-K_test./(2*sigma)); 65 | case {'exp'} 66 | for i = 1:size(test,1) 67 | diff = bsxfun(@minus,test(i,:),train); 68 | K_test(:,i) = sqrt(sum(diff.^2,2)); 69 | end 70 | K_test = exp(-K_test/(2*Method.rbf_sigma^2)); 71 | case {'poly'} 72 | K_test = (train*test'+1).^2; 73 | end 74 | end 75 | return; -------------------------------------------------------------------------------- /script_test.m: -------------------------------------------------------------------------------- 1 | % Experiment demo for DukeReID dataset 2 | % Write by Mengran Gou @ RSL, Northeastern U 3 | 4 | %% data parsing 5 | if ~exist('DukeReID_images.mat','file') 6 | run script_loadimage.m 7 | end 8 | 9 | %% setting 10 | % load feature and partition 11 | load('feature_DukeReID_LOMO_6patch.mat'); 12 | load('Partition_DukeReID.mat'); 13 | % set parameter for kLFDA 14 | AlgoOption.dataname = 'DukeReID'; 15 | AlgoOption.epsilon =1e-4; 16 | AlgoOption.npratio =0; % npratio is not required. 17 | AlgoOption.beta =0.01; 18 | AlgoOption.d =40; 19 | AlgoOption.LocalScalingNeighbor =6; % local scaling affinity matrix parameter. 20 | AlgoOption.kernel = 'linear'; 21 | % experiment setting 22 | par = 'mixgal'; %'pairwise';'mixgal' 23 | %% experiments 24 | mAP = []; 25 | szGal = []; 26 | szProb = []; 27 | rank = []; 28 | switch par 29 | case 'mixgal' 30 | parset = 57:64; 31 | case 'pairwise' 32 | parset = 1:56; 33 | otherwise 34 | warning('Invalid partition setting, will run all experiments...') 35 | parset = 1:64; 36 | end 37 | for s = 1:numel(partition) 38 | idx_train = partition(s).idx_train; 39 | idx_test = partition(s).idx_test; 40 | idx_probe = partition(s).idx_probe; 41 | idx_gallery = partition(s).idx_gallery; 42 | idx_pos_pair = partition(s).ix_pos_pair; 43 | idx_neg_pair = partition(s).ix_neg_pair; 44 | 45 | trainFeat = features(idx_train,:); 46 | ID_train = personID(idx_train); 47 | 48 | testFeat = features(idx_test,:); 49 | ID_test = personID(idx_test); 50 | 51 | % training 52 | [algo, ~]= LFDA(trainFeat,ID_train',AlgoOption); 53 | 54 | % testing 55 | K.kernel = algo.kernel; 56 | K.rbf_sigma = algo.rbf_sigma; 57 | testFeat = single(testFeat); 58 | % compute kernel 59 | [Ktest] = ComputeKernelTest(trainFeat, testFeat, K); 60 | testFeatProj = (algo.P*Ktest)'; % projection 61 | for pr = parset % loop over different partitions 62 | dis = []; 63 | probeFeat = testFeatProj(idx_probe(pr,:),:); 64 | probeID = ID_test(idx_probe(pr,:)); 65 | galleryFeat = testFeatProj(idx_gallery(pr,:),:); 66 | galleryID = ID_test(idx_gallery(pr,:)); 67 | dis = pdist2(probeFeat,galleryFeat,'euclidean'); 68 | [disSort,idxSort] = sort(dis,2,'ascend'); 69 | IDsort = galleryID(idxSort); 70 | tmpRank = bsxfun(@eq, IDsort, probeID'); 71 | Res_match{s,pr} = tmpRank; 72 | % compute AP (average precision) 73 | firstOcc = []; 74 | AP = []; 75 | for p = 1:size(tmpRank,1) 76 | tmpR = tmpRank(p,:); 77 | firstOcc(p) = min(find(tmpR)); 78 | AP(p) = compute_AP(find(tmpR),1:numel(tmpR)); 79 | end 80 | tmpRank = hist(firstOcc,1:max(sum(idx_gallery,2))); 81 | mAP = [mAP; mean(AP)]; 82 | szGal = [szGal;numel(galleryID)]; 83 | szProb = [szProb;numel(probeID)]; 84 | tmpRank = cumsum(tmpRank)./sum(idx_probe(pr,:)); 85 | disp(tmpRank([1 5 10 20])*100); 86 | rank = [rank; tmpRank]; 87 | end 88 | end 89 | 90 | metric.mAP = mAP; 91 | metric.szGal = szGal; 92 | metric.szProb = szProb; 93 | metric.rank = rank; 94 | metric.cam_pair = partition.cam_pairs; 95 | rank = bsxfun(@times,rank,szProb); 96 | rank = sum(rank,1)./sum(szProb)*100; 97 | mAP = sum(mAP.*szProb)/sum(szProb)*100; 98 | fprintf('Average accuarcy for all partitions are:\nr1---%.1f\tr5---%.1f\tr10---%.1f\tr20---%.1f\n',... 99 | rank(1),rank(5),rank(10),rank(20)); 100 | fprintf('mAP:%.1f\n',mAP) 101 | 102 | 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [NEW] The DukeMTMC dataset is taken down due to privacy concerns... Will reopen when it's clear. 2 | 3 | [NEW] 4 | Benchmark evalution code-base is released! Please refer to this [repo](https://github.com/RSL-NEU/person-reid-benchmark) for more details. 5 | # DukeMTMC4ReID 6 | DukeMTMC4ReID dataset is new large-scale real-world person re-id dataset based on [DukeMTMC](http://vision.cs.duke.edu/DukeMTMC/). We use a fast state-of-the-art [person detector](https://bitbucket.org/rodrigob/doppia) for accurate detections. After verified by the ground truth, for each identity, we uniformly sample 5 "good" bounding boxes in each available camera, while retaining all the "FP" bounding boxes in the corresponding frames. To summarize, the relevant statistics of the proposed DukeMTMC4ReID dataset are provided below: 7 | * Images corresponding to 1,852 people existing across all the 8 cameras 8 | * 1,413 unique identities with 22,515 bounding boxes that appear in more than one camera (valid identities) 9 | * 439 distractor identities with 2,195 bounding boxes that appear in only one camera, in addition to 21,551 ?FP? bounding boxes from the person detector 10 | * The size of the bounding box varies from 72×34 pixels to 415×188 pixels 11 | 12 | | | Total | cam1 | cam2 | cam3 | cam4 | cam5 | cam6 | cam7 | cam8 | 13 | |:---------------:|:------:|:------:|:-----:|:-----:|:-----:|:-----:|:------:|:-----:|:-----:| 14 | | # bboxes | 46,261 | 10,048 | 4,469 | 5,117 | 2,040 | 2,400 | 10,632 | 4,335 | 7,220 | 15 | | # person bboxes | 24,710 | 4,220 | 4,030 | 1,975 | 1,640 | 2,195 | 3,635 | 2,285 | 4,730 | 16 | | # ``FP'' bboxes | 21,551 | 5,828 | 439 | 3,142 | 400 | 205 | 6,997 | 2,050 | 2,490 | 17 | | # persons | 1,852 | 844 | 806 | 395 | 328 | 439 | 727 | 457 | 946 | 18 | | # valid ids | 1,413 | 828 | 778 | 394 | 322 | 439 | 718 | 457 | 567 | 19 | | # distractors | 439 | 16 | 28 | 1 | 6 | 0 | 9 | 0 | 379 | 20 | | # probe ids | 706 | 403 | 373 | 200 | 168 | 209 | 358 | 243 | 284 | 21 | 22 | More details and benchmark results can be found in this [paper](http://robustsystems.coe.neu.edu/sites/robustsystems.coe.neu.edu/files/systems/papers/MengranGou_CVPRW17.pdf) 23 | ### How to use 24 | 1. Clone or download this repo 25 | 2. ~~Download the dataset from [here](http://robustsystems.coe.neu.edu) and extract it within the same folder of the code~~ 26 | - p0001_c5_f0000051246_1.jpg 27 | bounding box of person 0001 in camera 5 at frame 51246 28 | - partition. 29 | idx_train - index of train samples 30 | idx_test - index of test samples 31 | idx_probe - index of probe samples in test 32 | idx_gallery - index of gallery samples in test 33 | ix_pos_pair - index of pre-generated positive pairs 34 | ix_neg_pair - index of pre-generated negtive pairs 35 | cam_pairs - [probe camera, gallery camera] (0 means all the other cameras) 36 | 37 | 3. Download the pre-computed [feature](http://robustsystems.coe.neu.edu/sites/robustsystems.coe.neu.edu/files/systems/dataset/feature/feature_DukeReID_LOMO_6patch.mat) 38 | 4. run script_test.m to parsing the data and evaluate it with pre-computed feature 39 | 40 | ### References 41 | ``` 42 | @InProceedings{gou2017dukemtmc4reid, 43 | author = {Gou, Mengran and Karanam, Srikrishna and Liu, Wenqian and Camps, Octavia and Radke, Richard J.}, 44 | title = {DukeMTMC4ReID: A Large-Scale Multi-Camera Person Re-Identification Dataset}, 45 | booktitle = {The IEEE Conference on Computer Vision and Pattern Recognition (CVPR) Workshops}, 46 | month = {July}, 47 | year = {2017} 48 | } 49 | ``` 50 | If you use this dataset, please also cite the original DukeMTMC dataset accordingly: 51 | ``` 52 | @inproceedings{ristani2016MTMC, 53 | title = {Performance Measures and a Data Set for Multi-Target, Multi-Camera Tracking}, 54 | author = {Ristani, Ergys and Solera, Francesco and Zou, Roger and Cucchiara, Rita and Tomasi, Carlo}, 55 | booktitle = {European Conference on Computer Vision workshop on Benchmarking Multi-Target Tracking}, 56 | year = {2016} 57 | } 58 | ``` 59 | ### License 60 | Please refer to the license file for [DukeMTMC4ReID](https://github.com/NEU-Gou/DukeReID/blob/master/LICENSE_DukeMTMC4ReID.txt) and [DukeMTMC](https://github.com/NEU-Gou/DukeReID/blob/master/LICENSE_DukeMTMC.txt) 61 | -------------------------------------------------------------------------------- /kLFDA/ComputeKernel.m: -------------------------------------------------------------------------------- 1 | % calculate the kernel matrix. 2 | % By Fei Xiong, 3 | % ECE Dept, 4 | % Northeastern University 5 | % 2013-11-04 6 | % Input: 7 | % Method: the distance learning algorithm struct. In this function 8 | % two field are used. 9 | % rbf_sigma is written while computing the rbf-chi2 kernel 10 | % matrix. 11 | % kernel is the name of the kernel function. 12 | % X: Each row is a sample vector. N-by-d 13 | 14 | 15 | function [K, Method] = ComputeKernel(X, kernel, Method) 16 | info = whos('X'); 17 | if strfind(info.class,'gpu') 18 | fprintf('Using GPU now\n'); 19 | K = gpuArray.zeros(size(X,1),'single'); 20 | else 21 | K = zeros(size(X,1),'single'); 22 | end 23 | Method.rbf_sigma = []; 24 | if ~strfind(info.class,'gpu')%(numel(X))>2e4 && (strcmp(kernel, 'chi2') || strcmp(kernel, 'chi2-rbf')) 25 | 26 | % poolobj = parpool; 27 | switch kernel 28 | case {'linear'}% linear kernel 29 | K = X*X'; 30 | case {'chi2'}% chi2 kernel 31 | parfor i =1:size(X,1) 32 | dotp = bsxfun(@times, X(i,:), X); 33 | sump = bsxfun(@plus, X(i,:), X); 34 | K(i,:) = full(2* sum(dotp./(sump+1e-10),2)); 35 | end 36 | clear subp sump; 37 | case {'chi2-rbf'}% chi2 RBF kernel 38 | parfor i =1:size(X,1) 39 | subp = bsxfun(@minus, X(i,:), X); 40 | subp = subp.^2; 41 | sump = bsxfun(@plus, X(i,:), X); 42 | K(i,:) = full(sum(subp./(sump+eps),2)); 43 | end 44 | temp = triu(ones(size(K))-eye(size(K)))>0; 45 | temp = K(temp(:)); 46 | [temp,~]= sort(temp); 47 | % rbf-chi2 kernel parameter can be set here. For example, the 48 | % first quartile of the distance can be used to normalize the 49 | % distribution of the chi2 distance 50 | % Method.rbf_sigma = 1; %temp(ceil(length(temp)*0.25)); 51 | Method.rbf_sigma = mean(mean(temp)); %temp(ceil(length(temp)*0.25));% following KCCA 52 | K =exp( -K/(2*Method.rbf_sigma)); 53 | clear subp sump; 54 | case {'exp'} 55 | parfor i = 1:size(X,1) 56 | diff = bsxfun(@minus,X(i,:),X); 57 | K(i,:) = sqrt(sum(diff.^2,2)); 58 | end 59 | temp = triu(ones(size(K))-eye(size(K)))>0; 60 | temp = K(temp(:)); 61 | [temp,~]= sort(temp); 62 | Method.rbf_sigma = temp(ceil(length(temp)*0.25)); 63 | K = exp(-K/(2*Method.rbf_sigma^2)); 64 | case {'poly'} 65 | K = (X*X'+1).^2; 66 | end 67 | % delete(poolobj); 68 | else 69 | switch kernel 70 | case {'linear'}% linear kernel 71 | K = X*X'; 72 | case {'chi2'}% chi2 kernel 73 | for i =1:size(X,1) 74 | dotp = bsxfun(@times, X(i,:), X); 75 | sump = bsxfun(@plus, X(i,:), X); 76 | K(i,:) = full(2* sum(dotp./(sump+1e-10),2)); 77 | end 78 | clear subp sump; 79 | case {'chi2-rbf'}% chi2 RBF kernel 80 | for i =1:size(X,1) 81 | subp = bsxfun(@minus, X(i,:), X); 82 | subp = subp.^2; 83 | sump = bsxfun(@plus, X(i,:), X); 84 | K(i,:) = full(sum(subp./(sump+1e-10),2)); 85 | end 86 | temp = triu(ones(size(K))-eye(size(K)))>0; 87 | temp = K(temp(:)); 88 | [temp,~]= sort(temp); 89 | Method.rbf_sigma = mean(mean(temp)); %temp(ceil(length(temp)*0.25));% following KCCA 90 | K =exp( -K/(2*Method.rbf_sigma)); 91 | clear subp sump; 92 | case {'exp'} 93 | for i = 1:size(X,1) 94 | diff = bsxfun(@minus,X(i,:),X); 95 | K(i,:) = sqrt(sum(diff.^2,2)); 96 | end 97 | temp = triu(ones(size(K))-eye(size(K)))>0; 98 | temp = K(temp(:)); 99 | [temp,~]= sort(temp); 100 | Method.rbf_sigma = temp(ceil(length(temp)*0.25)); 101 | K = exp(-K/(2*Method.rbf_sigma^2)); 102 | case {'poly'} 103 | K = (X*X'+1).^2; 104 | end 105 | end 106 | 107 | if strfind(info.class,'gpu') 108 | K = gather(K); 109 | Method.rbf_sigma = gather(Method.rbf_sigma); 110 | end 111 | return; 112 | --------------------------------------------------------------------------------