├── python ├── bench │ ├── __init__.py │ ├── parse_arg.py │ ├── vlb_greedy_matching.pyx │ └── matrixNormBench.py ├── verifiers │ ├── __init__.py │ ├── lmeds.py │ ├── ransac.py │ └── VerificationTemplate.py ├── doc │ ├── VLBenchmark.pdf │ ├── feature.rst │ ├── Makefile │ ├── benchmark.rst │ ├── test_baseline_matching.rst │ ├── dataset.rst │ ├── index.rst │ ├── test_retrieval.rst │ ├── intro.rst │ ├── new_dataset.rst │ └── test_match.rst ├── requirements.txt ├── features │ ├── vlsift_load_matlab.py │ ├── my_surf.py │ ├── cv_mser.py │ ├── cv_fast.py │ ├── cv_orb.py │ ├── np_sift.py │ ├── cv_kaze.py │ ├── cv_brisk.py │ ├── cv_akaze.py │ ├── vlsift_matlab.py │ └── cyvlsift_official.py ├── test │ ├── draw_frame.py │ ├── test_feature_extraction.py │ ├── test_W1BS_Bench.py │ ├── test_epiDist_bench.py │ ├── test_inlierPrec_bench.py │ ├── test_retrieval_bench.py │ ├── test_allVerification_bench.py │ ├── test_epiConstraint_bench.py │ └── test_bench_csv.py ├── conda │ └── environment.yml └── dset │ ├── hpatches_dataset.py │ ├── write_dataset_vggh.py │ ├── W1BS_dataset.py │ ├── write_dataset_W1BS.py │ ├── retrieval_dataset.py │ ├── vgg_dataset.py │ └── write_dataset_hpatches.py ├── .gitignore ├── matlab ├── +utls │ ├── frame_get_orientation.m │ ├── struct2argscell.m │ ├── frame_magnify_scale.m │ ├── listdirs.m │ ├── frame_get_anisotropy.m │ ├── frame2afftf.m │ ├── imread_grayscale.m │ ├── read_vgg_homography.m │ ├── matdet_w.m │ ├── features_not_found.m │ ├── alldist_edges.m │ ├── features_get.m │ ├── afftf2frame.m │ ├── topnframes.m │ ├── covdet_preprocessim.m │ ├── setup_vlfeat.m │ ├── listfiles.m │ ├── patches_save.m │ ├── match_greedy.m │ ├── get_image_size.m │ ├── patches_load.m │ ├── ungzip.m │ ├── match_greedy_2nn.m │ ├── ellipse_in_bbox.m │ ├── setup_matconvnet.m │ ├── frame_dev.m │ ├── randomtf.m │ ├── features_save.m │ ├── textprogressbar_LICENSE.txt │ ├── patches_extract_covdet.m │ ├── ellipse_eigen.m │ ├── frame2ellipse.m │ ├── frame_get_scale.m │ ├── frame_set_scale.m │ ├── patches_extract_interp.m │ ├── warpim_H.m │ ├── sysrun.m │ ├── ellipse2vggformat.m │ ├── parallelise.m │ ├── helpbuilder.m │ ├── features_load.m │ ├── provision.m │ ├── generate_ellblobs.m │ ├── oell_warp.m │ └── ellipse_warp.m ├── +features │ ├── +det │ │ ├── surfdet.m │ │ ├── filedet.m │ │ ├── vlsift.m │ │ ├── vlcovdet.m │ │ ├── ddet.m │ │ ├── matdet.m │ │ ├── tilde.m │ │ ├── lift.m │ │ ├── random.m │ │ ├── vggmser.m │ │ ├── tcdet.m │ │ └── vggaff.m │ ├── +desc │ │ ├── surfdesc.m │ │ ├── p_rootsift.m │ │ ├── p_meanstd.m │ │ ├── p_sift.m │ │ ├── fp_sift.m │ │ └── p_resize.m │ ├── factory.m │ └── +utls │ │ └── surf.m ├── +dset │ ├── +utls │ │ └── getimid.m │ ├── factory.m │ ├── webcam.m │ ├── edgefoci.m │ └── hsequences.m ├── xtest │ ├── suite │ │ ├── test_frames_get_orientation.m │ │ ├── test_detrepthr_benchmark.m │ │ ├── test_dets.m │ │ ├── test_detrep.m │ │ ├── test_detmatch.m │ │ ├── test_descs.m │ │ └── test_desc_benchmark.m │ └── vlb_test.m ├── vlb_setup.m ├── vlb_imagelist.m ├── mex │ └── vlb_greedy_matching.m ├── +legacy │ ├── vgg_frames_read.m │ ├── vgg_frames_read_ext.m │ ├── vgg_features_write.m │ ├── vgg_features_read.m │ ├── vgg_desc_benchmark.m │ └── vgg_frames_benchmark.m ├── vlb_detect.m ├── vlb_extract.m ├── vlb.m ├── +bench │ ├── detrepthr.m │ └── detrep.m ├── vlb_evalfeatures.m ├── vlb_describe.m └── vlb_path.m ├── datasets └── dataset_info │ ├── oxford5k.json │ └── paris6k.json ├── .gitmodules ├── examples ├── descbench.m └── detbench.m └── COPYING /python/bench/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /python/verifiers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /python/doc/VLBenchmark.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lenck/vlb/HEAD/python/doc/VLBenchmark.pdf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | data 2 | vendor 3 | datasets 4 | *.mexa64 5 | *~ 6 | *.o 7 | .build 8 | vlfeat 9 | __pycache__ 10 | -------------------------------------------------------------------------------- /python/bench/parse_arg.py: -------------------------------------------------------------------------------- 1 | def parse_arg(opts, options): 2 | for key in options: 3 | opts[key]=options[key] 4 | -------------------------------------------------------------------------------- /matlab/+utls/frame_get_orientation.m: -------------------------------------------------------------------------------- 1 | function [ ths ] = frame_get_orientation( frms ) 2 | 3 | frms = vl_frame2oell(frms); 4 | ths = atan2(-frms(5, :), frms(6, :)); 5 | 6 | end 7 | -------------------------------------------------------------------------------- /matlab/+utls/struct2argscell.m: -------------------------------------------------------------------------------- 1 | function res = struct2argscell(s) 2 | % Authors: Karel Lenc 3 | 4 | % AUTORIGHTS 5 | 6 | res = [fieldnames(s)';struct2cell(s)']; 7 | res = res(:)'; 8 | end -------------------------------------------------------------------------------- /datasets/dataset_info/oxford5k.json: -------------------------------------------------------------------------------- 1 | { 2 | "Description": "Standard Benchmark", 3 | "url": "http://www.robots.ox.ac.uk/~vgg/data/oxbuildings/", 4 | "Dataset Name": "Oxford Building" 5 | } 6 | -------------------------------------------------------------------------------- /datasets/dataset_info/paris6k.json: -------------------------------------------------------------------------------- 1 | { 2 | "Description": "Standard Benchmark", 3 | "url": "http://www.robots.ox.ac.uk/~vgg/data/parisbuildings/", 4 | "Dataset Name": "Paris Building" 5 | } 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "python/other_benchmarks/wxbs_descriptors_benchmark"] 2 | path = python/other_benchmarks/wxbs_descriptors_benchmark 3 | url = git@github.com:spongezhang/wxbs-descriptors-benchmark.git 4 | -------------------------------------------------------------------------------- /matlab/+utls/frame_magnify_scale.m: -------------------------------------------------------------------------------- 1 | function [ frames ] = frame_magnify_scale( frames, mf ) 2 | 3 | if mf ~= 1 4 | frames = utls.frame_set_scale(frames, utls.frame_get_scale(frames) * mf); 5 | end 6 | 7 | end 8 | 9 | -------------------------------------------------------------------------------- /python/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy==1.13.3 2 | scipy==0.19.1 3 | Cython==0.26.1 4 | matplotlib==2.1.0 5 | cyvlfeat==0.4.6 6 | exifread==2.1.2 7 | hickle==3.3.3 8 | matlab==0.1 9 | nmslib==1.7.3.6 10 | plotly==3.6.1 11 | tqdm==4.31.0 12 | utils==0.9.0 13 | -------------------------------------------------------------------------------- /matlab/+utls/listdirs.m: -------------------------------------------------------------------------------- 1 | function dirs = listdirs(path) 2 | if ~exist(path, 'dir'), error('Dir %s does not exist', path); end; 3 | dirs = dir(path); 4 | is_valid = [dirs.isdir] & arrayfun(@(d) d.name(1)~='.', dirs)'; 5 | dirs = {dirs.name}; 6 | dirs = dirs(is_valid); 7 | end -------------------------------------------------------------------------------- /matlab/+features/+det/surfdet.m: -------------------------------------------------------------------------------- 1 | function [ res ] = surfdet( img, varargin ) 2 | 3 | res.detName = 'surfdet'; 4 | if isempty(img), res.frames = zeros(3, 0); return; end; 5 | 6 | feats = features.utls.surf(img, [], varargin{:}); 7 | res = vl_override(res, feats); 8 | 9 | end 10 | 11 | 12 | -------------------------------------------------------------------------------- /matlab/+utls/frame_get_anisotropy.m: -------------------------------------------------------------------------------- 1 | function [ anis ] = frame_get_anisotropy( frames ) 2 | 3 | tfs = utls.frame2afftf(vl_frame2oell(frames)); 4 | anis = zeros(1, size(frames, 2)); 5 | for fi = 1:size(frames, 2) 6 | s = svd(tfs(1:2,1:2,fi)); 7 | anis(fi) = s(1) ./ s(2); 8 | end 9 | 10 | end 11 | 12 | -------------------------------------------------------------------------------- /matlab/+utls/frame2afftf.m: -------------------------------------------------------------------------------- 1 | function tf = frame2afftf( frame ) 2 | tf = zeros(3, 3, size(frame, 2)); 3 | if size(frame, 1) ~= 6 4 | frame = vl_frame2oell(frame); 5 | end 6 | tf(3, 3, :) = 1; 7 | tf(1:2, 3, :) = frame(1:2, :); 8 | tf(1:2, 1, :) = frame(3:4, :); 9 | tf(1:2, 2, :) = frame(5:6, :); 10 | end 11 | -------------------------------------------------------------------------------- /matlab/+utls/imread_grayscale.m: -------------------------------------------------------------------------------- 1 | function [ im ] = imread_grayscale( varargin ) 2 | %IMREAD_GRAYSCALE Read an image to a grayscale 3 | % IMREAD_GRAYSCALE accepts the same arguments as imread. If an image is 4 | % in RGB, converts to grayscale image. 5 | 6 | im = imread(varargin{:}); 7 | if size(im, 3) == 3, im = rgb2gray(im); end 8 | 9 | -------------------------------------------------------------------------------- /matlab/+features/+det/filedet.m: -------------------------------------------------------------------------------- 1 | function [ res ] = filedet( img, varargin ) 2 | 3 | res.detName = sprintf('FILEDET'); 4 | if isempty(img), res.frames = zeros(4, 0); return; end 5 | 6 | if ischar(img) 7 | imgname = img; 8 | else 9 | imgname = 'binary data'; 10 | end 11 | error('Features for an image do not exist (%s)', imgname); 12 | 13 | end 14 | 15 | -------------------------------------------------------------------------------- /matlab/+utls/read_vgg_homography.m: -------------------------------------------------------------------------------- 1 | function [ tfs ] = read_vgg_homography( path ) 2 | %UNTITLED7 Summary of this function goes here 3 | % Detailed explanation goes here 4 | if ~exist(path, 'file') 5 | error('File %s does not exist.', path); 6 | end 7 | tfs = eye(3); 8 | [tfs(:,1), tfs(:,2), tfs(:,3)] = textread(path, '%f %f %f%*[^\n]'); 9 | 10 | end 11 | 12 | -------------------------------------------------------------------------------- /matlab/+features/+desc/surfdesc.m: -------------------------------------------------------------------------------- 1 | function [ res ] = surfdesc( img, feats, varargin ) 2 | 3 | res.descName = 'surfdesc'; res.describes = 'frames'; 4 | if isempty(img) || isempty(feats.frames) 5 | res.descs = []; res.frames = zeros(3, 0); 6 | return; 7 | end 8 | 9 | res = vl_override(res, features.utls.surf(img, feats, varargin{:})); 10 | 11 | end 12 | 13 | 14 | -------------------------------------------------------------------------------- /matlab/+utls/matdet_w.m: -------------------------------------------------------------------------------- 1 | function [ frames, descs, info ] = matdet_w( fp ) 2 | descs = []; 3 | info = struct(); 4 | frames = double(fp.Location'); 5 | if isprop(fp, 'Scale'), frames = [frames; fp.Scale']; end 6 | if isprop(fp, 'Orientation'), frames = [frames; fp.Orientation']; end 7 | if isprop(fp, 'Metric') 8 | info.peakScores = fp.Metric'; 9 | end 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /matlab/+features/+desc/p_rootsift.m: -------------------------------------------------------------------------------- 1 | function [res] = p_rootsift( patches ) 2 | % Copyright: Karel Lenc and Giorgos Tolias 3 | res = struct('descName', mfilename, 'describes', 'patches'); 4 | 5 | x = features.desc.p_sift(patches); 6 | x = x.descs; 7 | vnr = sum(abs(x)); 8 | x = bsxfun (@rdivide, x, vnr); 9 | x = sqrt(x); 10 | x(isnan(x)) = 0; 11 | res.descs = x; 12 | end 13 | 14 | -------------------------------------------------------------------------------- /matlab/+utls/features_not_found.m: -------------------------------------------------------------------------------- 1 | function features_not_found( path ) 2 | 3 | variants = dir([path, '*']); 4 | variants = variants([variants.isdir]); 5 | variants = {variants.name}; 6 | if ~isempty(variants) 7 | error('Cannot find features in %s. \nDid you mean:\n%s', path, ... 8 | sprintf('\t%s\n', variants{:})); 9 | else 10 | error('Cannot find features in %s.', path); 11 | end 12 | 13 | end 14 | 15 | -------------------------------------------------------------------------------- /matlab/+utls/alldist_edges.m: -------------------------------------------------------------------------------- 1 | function [ edges, dists ] = alldist_edges( data, qdata, varargin ) 2 | %ALLDIST_EDGES Match all features 3 | opts.metric = 'L2'; 4 | opts = vl_argparse(opts, varargin); 5 | 6 | dists = vl_alldist2(single(data), single(qdata), opts.metric); 7 | % Create list of edges in the bipartite graph 8 | [aIdx, bIdx] = ind2sub([size(data, 2), size(qdata, 2)], 1:numel(dists)); 9 | edges = [aIdx; bIdx]; 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /matlab/+features/+desc/p_meanstd.m: -------------------------------------------------------------------------------- 1 | function [ res ] = p_meanstd(patches) 2 | res = struct('descName', mfilename, 'describes', 'patches', 'descs', []); 3 | if isempty(patches), return; end 4 | 5 | patches = single(squeeze(patches)); 6 | meanVal = reshape(mean(mean(patches, 1), 2), 1, []); 7 | patchSz = [size(patches, 1), size(patches, 2)]; 8 | stdVal = std(reshape(single(patches), prod(patchSz(:)), []), 0, 1); 9 | res.descs = [meanVal; stdVal]; 10 | 11 | end -------------------------------------------------------------------------------- /matlab/+utls/features_get.m: -------------------------------------------------------------------------------- 1 | function [feats, featpath] = features_get(imdb, featsname, imname, varargin) 2 | 3 | featsdir = vlb_path('features', imdb, struct('name', featsname)); 4 | if ~isdir(featsdir) 5 | utls.features_not_found(featsdir); 6 | end 7 | featpath = fullfile(featsdir, imname); 8 | feats = utls.features_load(featpath, varargin{:}); 9 | if isempty(feats) 10 | error('Unalbe to find %s features for image %s.', featsname, imname); 11 | end 12 | end -------------------------------------------------------------------------------- /matlab/+utls/afftf2frame.m: -------------------------------------------------------------------------------- 1 | function frm = afftf2frame( tf ) 2 | % Make sure it is an affine transformation 3 | if numel(tf) == 4 4 | frm = [... 5 | reshape(tf(1:2, 1, :), 2, []); ... 6 | reshape(tf(1:2, 2, :), 2, [])]; 7 | else 8 | assert(all(tf(3, 3, :) == 1)); 9 | assert(all(all(tf(3, 1:2, :) == 0))); 10 | frm = [... 11 | reshape(tf(1:2, 3, :), 2, []); ... 12 | reshape(tf(1:2, 1, :), 2, []); ... 13 | reshape(tf(1:2, 2, :), 2, [])]; 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /matlab/+dset/+utls/getimid.m: -------------------------------------------------------------------------------- 1 | function imid_out = getimid(imdb, imid) 2 | if ischar(imid) 3 | [imid_out, status] = str2num(imid); 4 | if ~status 5 | imnames = {imdb.images.name}; 6 | imname = imid; 7 | [found, imid_out] = ismember(imname, imnames); 8 | if ~found, error('Image %s not found.', imname); end 9 | end 10 | else 11 | imid_out = imid; 12 | end 13 | if imid_out > numel(imdb.images) || imid_out < 1 14 | error('Invalid image id %d.', imid_out); 15 | end 16 | end -------------------------------------------------------------------------------- /matlab/+features/+det/vlsift.m: -------------------------------------------------------------------------------- 1 | function [ res ] = vlsift( img, varargin ) 2 | opts.Magnif = 5; 3 | [opts, varargin] = vl_argparse(opts, varargin); 4 | 5 | res.detName = sprintf('vlsift'); 6 | if isempty(img), res.frames = zeros(4, 0); return; end; 7 | img = utls.covdet_preprocessim(img); 8 | 9 | stime = tic; 10 | [res.frames, res.descs] = vl_sift(img, 'Magnif', opts.Magnif, varargin{:}); 11 | res.dettime = toc(stime); 12 | res.scalingFactor = opts.Magnif; 13 | res.args = varargin; 14 | 15 | end 16 | 17 | -------------------------------------------------------------------------------- /matlab/xtest/suite/test_frames_get_orientation.m: -------------------------------------------------------------------------------- 1 | classdef test_frames_get_orientation < matlab.unittest.TestCase 2 | methods (Test) 3 | function getimage(test) 4 | or = linspace(-pi, pi, 36); 5 | or_r = zeros(1, numel(or)); 6 | for oi = 1:numel(or) 7 | fra = [0, 0, 10, or(oi)]'; 8 | fra_a = vl_frame2oell(fra); 9 | or_r(oi) = utls.frame_get_orientation(fra_a); 10 | end 11 | test.verifyLessThan(max(or_r - or), 1e-10); 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /matlab/+utls/topnframes.m: -------------------------------------------------------------------------------- 1 | function [ feats ] = topnframes( feats, n ) 2 | %TOPNFEATS pick only top-N features based on the detresponses 3 | % Detailed explanation goes here 4 | assert(isfield(feats, 'detresponses')); 5 | if isinf(n), return; end 6 | [~, perm] = sort(abs(feats.detresponses), 'descend'); 7 | perm = perm(1:min(n, numel(perm))); 8 | feats.frames = feats.frames(:, perm); 9 | feats.detresponses = feats.detresponses(:, perm); 10 | if isfield(feats, 'descs') 11 | feats.descs = feats.descs(:, perm); 12 | end 13 | end 14 | 15 | -------------------------------------------------------------------------------- /matlab/+utls/covdet_preprocessim.m: -------------------------------------------------------------------------------- 1 | function [ img ] = covdet_preprocessim( img ) 2 | %COVDET_PREPROCESSIM Preprocess image for the VL_COVDET function 3 | % Prepares the image to single and in the [0, 1], single channel 4 | % range, which is expected by VL_COVDET and VL_SIFT (e.g. all 5 | % thresholds are set for these ranges). 6 | % 7 | % See also: vl_covdet, vl_sift 8 | if isa(img, 'uint8'), img = im2single(img); end; 9 | if isa(img, 'double'), img = single(img); end; 10 | if size(img, 3) == 3, img = rgb2gray(img); end; 11 | 12 | end 13 | 14 | -------------------------------------------------------------------------------- /matlab/+utls/setup_vlfeat.m: -------------------------------------------------------------------------------- 1 | function setup_vlfeat() 2 | url = 'http://www.vlfeat.org/download/vlfeat-0.9.20-bin.tar.gz'; 3 | rootDir = fullfile(vlb_path('vendor'), 'vlfeat'); 4 | if ~exist('vl_argparse.m', 'file') 5 | utls.provision(url, rootDir); 6 | run(fullfile(getlatest(rootDir, 'vlfeat'), 'toolbox', 'vl_setup.m')); 7 | end 8 | end 9 | 10 | function out = getlatest(path, name) 11 | sel_dir = dir(fullfile(path, [name '*'])); 12 | sel_dir = sel_dir([sel_dir.isdir]); 13 | sel_dir = sort({sel_dir.name}); 14 | out = fullfile(path, sel_dir{end}); 15 | end -------------------------------------------------------------------------------- /matlab/+utls/listfiles.m: -------------------------------------------------------------------------------- 1 | function files = listfiles(path, varargin) 2 | opts.keepext = true; 3 | opts.fullpath = true; 4 | opts = vl_argparse(opts, varargin); 5 | 6 | files = dir(path); 7 | if isempty(files), files = {}; return; end; 8 | is_valid = ~[files.isdir] & arrayfun(@(d) d.name(1)~='.', files)'; 9 | files = {files.name}; 10 | files = files(is_valid); 11 | if ~opts.keepext 12 | for fi = 1:numel(files), [~, files{fi}, ~] = fileparts(files{fi}); end; 13 | end 14 | if opts.fullpath 15 | files = cellfun(@(a) fullfile(fileparts(path), a), files, 'Uni', false); 16 | end 17 | end -------------------------------------------------------------------------------- /matlab/+utls/patches_save.m: -------------------------------------------------------------------------------- 1 | function patches_save(patches, respath, scalingFactor) 2 | assert(size(patches, 3) == 1 || size(patches, 3) == 3, ... 3 | 'Patches has to be stored along 4th dimension.'); 4 | patchim = vl_imarray(squeeze(patches), 'Layout', [size(patches, 4), 1]); 5 | [~,~,ext] = fileparts(respath); 6 | assert(ismember(ext, {'.png', '.jpeg', '.jpg'})); 7 | try 8 | imwrite(patchim, respath, 'Comment', sprintf('ScalingFactor:%.6f', scalingFactor)); 9 | catch e 10 | fprintf('Cleaning up %s due to error', respath); 11 | if exist(respath, 'file'), delete(respath); end 12 | throw(e); 13 | end 14 | end -------------------------------------------------------------------------------- /python/doc/feature.rst: -------------------------------------------------------------------------------- 1 | features Module 2 | ================== 3 | This module defines basic feature detector and feature descriptor. 4 | 5 | .. automodule:: features.DetectorDescriptorTemplate 6 | :members: 7 | :undoc-members: 8 | :inherited-members: 9 | :show-inheritance: 10 | 11 | 12 | .. automodule:: features.feature_utils 13 | :members: 14 | :undoc-members: 15 | :inherited-members: 16 | :show-inheritance: 17 | 18 | Here is an example of how to make a warpper for cyvlsift 19 | 20 | .. automodule:: features.cyvlsift_official 21 | :members: 22 | :undoc-members: 23 | :inherited-members: 24 | :show-inheritance: 25 | -------------------------------------------------------------------------------- /python/doc/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /matlab/+utls/match_greedy.m: -------------------------------------------------------------------------------- 1 | function [ matches, dists ] = match_greedy(data, qdata, varargin) 2 | %MATCH_1TO1 Match data greedily 3 | [edges, dists] = utls.alldist_edges(data, qdata, varargin{:}); 4 | [dists, perm] = sort(dists(:), 'ascend'); edges = edges(:, perm); 5 | 6 | % Find one-to-one best matches 7 | matches = vlb_greedy_matching(size(data, 2), size(qdata, 2), edges'); 8 | matches = [1:size(data, 2); matches]; 9 | % Remove non-matching edges 10 | matches = matches(:, matches(2, :)~=0); 11 | if nargout > 1 12 | revind(perm) = 1:numel(dists); % Create reverse index 13 | dists = dists(revind(sub2ind([size(data, 2), size(qdata, 2)],... 14 | matches(1, :), matches(2, :)))); 15 | end 16 | -------------------------------------------------------------------------------- /matlab/+utls/get_image_size.m: -------------------------------------------------------------------------------- 1 | function [ imgSize ] = imageSize(imagePath) 2 | %IMAGESIZE Get image size helper 3 | % SIZE = IMAGESIZE(IMAGEPATH) returns size of the image defined by path 4 | % IMAGEPATH. Size is defined as size of Matlab matrix, i.e. as 5 | % [num_rows num_cols num_planes]. 6 | 7 | % Authors: Karel Lenc 8 | 9 | % AUTORIGHTS 10 | info = imfinfo(imagePath); 11 | switch info.ColorType 12 | case 'grayscale' 13 | numPlanes = 1; 14 | case 'truecolor' 15 | numPlanes = 3; 16 | case 'indexed' 17 | numPlanes = 3; 18 | end 19 | %Change size to imgsize to avoid potential conflict with matlab size() 20 | imgSize = [info.Height, info.Width numPlanes]; 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /matlab/+utls/patches_load.m: -------------------------------------------------------------------------------- 1 | function [patches, scalingFactor] = patches_load(impath) 2 | %patches_load Load and cut patch file 3 | 4 | if ~exist(impath, 'file'), error('Patch file %s does not exist.', impath); end; 5 | scalingFactor = nan; 6 | imi = imfinfo(impath); 7 | if ~isempty(imi.Comment) 8 | res = textscan(imi.Comment, 'ScalingFactor:%f'); 9 | if numel(res) == 1, scalingFactor = res{1}; end 10 | end 11 | 12 | patches = imread(impath); 13 | npatches = size(patches, 1) ./ size(patches, 2); 14 | assert(mod(npatches, 1) == 0, 'Invalid patch image height.'); 15 | patches = mat2cell(patches, size(patches, 2)*ones(1, npatches), size(patches, 2)); 16 | patches = permute(patches, [2, 3, 4, 1]); 17 | patches = cell2mat(patches); 18 | -------------------------------------------------------------------------------- /matlab/+features/+desc/p_sift.m: -------------------------------------------------------------------------------- 1 | function [ res ] = p_sift( patches ) 2 | res = struct('descName', mfilename, 'describes', 'patches', 'descs', []); 3 | if isempty(patches), return; end; 4 | 5 | psz = [size(patches, 1), size(patches, 2)]; 6 | frm = [(psz(1) ./ 2 + 0.5) * ones(2, 1) ; psz(1) ./ 2; 0]; 7 | x = []; 8 | for pi = 1:size(patches, 4) 9 | I = single(patches(:, :, 1, pi)); 10 | [Ix, Iy] = vl_grad(I) ; 11 | mod = sqrt(Ix.^2 + Iy.^2) ; 12 | ang = atan2(Iy, Ix) ; 13 | grd = shiftdim(cat(3, mod, ang), 2) ; 14 | d = vl_siftdescriptor(grd, frm, 'magnif', 0.5) ; 15 | if isempty(x) 16 | x = zeros(numel(d), size(patches, 4), 'single'); 17 | end 18 | x(:, pi) = d; 19 | end 20 | res.descs = x; 21 | end 22 | 23 | -------------------------------------------------------------------------------- /matlab/+dset/factory.m: -------------------------------------------------------------------------------- 1 | function [ imdb ] = factory( name, varargin ) 2 | %VLB_DSET Dataset Factory 3 | 4 | dsets = utls.listfiles(fullfile(vlb_path(), 'matlab', '+dset', '*.m'), ... 5 | 'keepext', false, 'fullpath', false); 6 | dsets = setdiff(dsets, 'factory'); 7 | if nargin == 0, imdb = dsets; return; end 8 | if isstruct(name), imdb = name; return; end 9 | 10 | if strcmp(name, 'hpatches-sequences') 11 | name = 'hsequences'; 12 | end 13 | 14 | if ~ismember(name, dsets) 15 | error('Invalid dataset %s. Valid values are: %s', name, strjoin(dsets, ', ')); 16 | end 17 | dsetfun = str2func(['dset.', name]); 18 | imdb = dsetfun(varargin{:}); 19 | if ~isfield(imdb, 'name') 20 | error('Invalid dataset structure %s', name); 21 | end 22 | 23 | end 24 | 25 | -------------------------------------------------------------------------------- /matlab/+utls/ungzip.m: -------------------------------------------------------------------------------- 1 | function ungzip( src, tgt_dir ) 2 | %UNGZIP Unpack raw .gz file (not .tar.gz) 3 | 4 | [~, filename, ext] = fileparts(src); 5 | assert(strcmp(ext, '.gz'), 'Not a .GZ file.'); 6 | assert(~strcmp(filename(end-3:end), '.tar'), 'Invalid use on .tar.gz file.'); 7 | gzTgtPath = fullfile(tgt_dir, [filename, ext]); 8 | if strcmp(src(1:7), 'http://') 9 | websave(gzTgtPath, src); 10 | else 11 | assert(exist(src, 'file') == 2, 'File %s does not exist', src); 12 | copyfile(src, gzTgtPath); 13 | end 14 | 15 | curDir = pwd; 16 | cd(tgt_dir) 17 | [status, ret] = system(sprintf('gunzip %s', gzTgtPath)); 18 | cd(curDir); 19 | if status ~= 0 20 | delete(gzTgtPath); 21 | error('Error unpacking %s: %s', src, ret); 22 | end 23 | 24 | end 25 | 26 | -------------------------------------------------------------------------------- /matlab/+features/+desc/fp_sift.m: -------------------------------------------------------------------------------- 1 | function [ res ] = fp_sift( im, feats, varargin ) 2 | opts.scalingFactor = 5; 3 | opts.extractPatchesFun = @utls.patches_extract_covdet; 4 | opts.topn = inf; 5 | opts = vl_argparse(opts, varargin); 6 | 7 | res = struct('descName', mfilename, 'describes', 'frames', 'descs', [], ... 8 | 'scalingFactor', opts.scalingFactor); 9 | if isempty(im), return; end 10 | feats = utls.topnframes(feats, opts.topn); 11 | res = vl_override(res, feats); 12 | frames = feats.frames; 13 | if isempty(frames), return; end 14 | 15 | patches = opts.extractPatchesFun(im, frames, ... 16 | 'scalingFactor', opts.scalingFactor, varargin{:}); 17 | 18 | res = vl_override(res, features.desc.p_sift(patches)); 19 | res.descName = mfilename; 20 | end 21 | 22 | -------------------------------------------------------------------------------- /matlab/+utls/match_greedy_2nn.m: -------------------------------------------------------------------------------- 1 | function [ matches, dists ] = match_greedy_2nn(data, qdata, varargin) 2 | %MATCH_GREEDY_2NN Match data greedily using the second nearest criterion 3 | dsz = [size(data, 2), size(qdata, 2)]; 4 | [edges, dists] = utls.alldist_edges(data, qdata, varargin{:}); 5 | [dists, perm] = sort(dists(:), 'ascend'); edges = edges(:, perm); 6 | 7 | % Find one-to-one best matches 8 | [matches, secondCl] = vlb_greedy_matching(dsz(1), dsz(2), edges'); 9 | matches = [1:size(data, 2); matches]; 10 | secondCl = [1:size(data, 2); secondCl]; 11 | 12 | % Remove non-matching edges 13 | validMatch = matches(2, :)~=0 & secondCl(2, :) ~= 0; 14 | matches = matches(:, validMatch); 15 | secondCl = secondCl(:, validMatch); 16 | 17 | dists = dists(matches(3, :)) ./ dists(secondCl(3, :)); -------------------------------------------------------------------------------- /matlab/+features/+det/vlcovdet.m: -------------------------------------------------------------------------------- 1 | function [ res ] = vlcovdet( img, varargin ) 2 | 3 | opts.Method = 'Dog'; 4 | opts.Descriptor = 'SIFT'; 5 | opts.PatchRelativeExtent = 5; 6 | [opts, varargin] = vl_argparse(opts, varargin); 7 | 8 | res.detName = sprintf('vlcovdet-det-%s', opts.Method); 9 | if isempty(img), res.frames = zeros(6, 0); return; end; 10 | img = utls.covdet_preprocessim(img); 11 | 12 | stime = tic(); 13 | [res.frames, res.descs, info] = vl_covdet(img, ... 14 | 'Descriptor', opts.Descriptor, ... 15 | 'PatchRelativeExtent', opts.PatchRelativeExtent, ... 16 | 'Method', opts.Method, varargin{:}); 17 | res.dettime = toc(stime) ; 18 | res.detresponses = info.peakScores; 19 | res.scalingFactor = opts.PatchRelativeExtent; 20 | res.args = [{'Method', opts.Method}, varargin]; 21 | end 22 | 23 | -------------------------------------------------------------------------------- /matlab/+utls/ellipse_in_bbox.m: -------------------------------------------------------------------------------- 1 | function sel = ellipse_in_bbox(f, bbox) 2 | %ELLIPSE_IN_BBOX Test whether ellipse is fully in a box. 3 | % SEL = ELLIPSE_IN_BBOX(BBOX, E) Tests whether ellipse E is in a 4 | % box BBOX defined as: 5 | % 6 | % [xmin ymin xmax ymax] 7 | 8 | % Authors: Andrea Vedaldi, Karel Lenc 9 | 10 | % AUTORIGHTS 11 | if numel(bbox) ~= 4 12 | error('Invalid bounding box'); 13 | end 14 | if size(f,1) ~= 5 15 | error('Invalid ellipse frames.'); 16 | end 17 | 18 | if isempty(f) 19 | sel = false; 20 | return; 21 | end 22 | 23 | rx = sqrt(f(3,:)) ; 24 | ry = sqrt(f(5,:)) ; 25 | 26 | sel = bbox(1) < f(1,:) - rx & ... 27 | bbox(2) < f(2,:) - ry & ... 28 | bbox(3) > f(1,:) + rx & ... 29 | bbox(4) > f(2,:) + ry ; 30 | 31 | end -------------------------------------------------------------------------------- /python/features/vlsift_load_matlab.py: -------------------------------------------------------------------------------- 1 | """ 2 | vlsift matlab version python wrapper 3 | Author: Xu Zhang 4 | """ 5 | 6 | import numpy as np 7 | import features.feature_utils 8 | from features.DetectorDescriptorTemplate import DetectorAndDescriptor 9 | 10 | 11 | class vlsift_load_matlab(DetectorAndDescriptor): 12 | def __init__(self, csv_flag=True): 13 | super( 14 | vlsift_load_matlab, 15 | self).__init__( 16 | name='vlsift_load_matlab', 17 | is_detector=True, 18 | is_descriptor=True, 19 | is_both=True, 20 | csv_flag=csv_flag) 21 | 22 | def detect_feature(self, image): 23 | pass 24 | 25 | def extract_descriptor(self, image, feature): 26 | pass 27 | 28 | def extract_all(self, image): 29 | pass 30 | -------------------------------------------------------------------------------- /python/features/my_surf.py: -------------------------------------------------------------------------------- 1 | """ 2 | vlsift matlab version python wrapper 3 | Author: Xu Zhang 4 | """ 5 | from DetectorDescriptorTemplate import DetectorAndDescriptor 6 | 7 | 8 | class my_surf(DetectorAndDescriptor): 9 | def __init__(self, peak_thresh=3.0, Magnif=5.0, csv_flag=True): 10 | super( 11 | my_surf, 12 | self).__init__( 13 | name='my_surf', 14 | is_detector=True, 15 | is_descriptor=True, 16 | is_both=True, 17 | csv_flag=csv_flag) 18 | self.peak_thresh = peak_thresh 19 | self.Magnif = Magnif 20 | 21 | def detect_feature(self, image): 22 | return None 23 | 24 | def extract_descriptor(self, image, feature): 25 | return None 26 | 27 | def extract_all(self, image): 28 | return None, None 29 | -------------------------------------------------------------------------------- /python/doc/benchmark.rst: -------------------------------------------------------------------------------- 1 | bench Module 2 | ================== 3 | This module defines the structure of different benchmarks 4 | 5 | .. automodule:: bench.BenchmarkTemplate 6 | :members: 7 | :undoc-members: 8 | :inherited-members: 9 | :show-inheritance: 10 | 11 | .. automodule:: bench.repBench 12 | :members: 13 | :undoc-members: 14 | :inherited-members: 15 | :show-inheritance: 16 | 17 | .. automodule:: bench.MatchingScoreBench 18 | :members: 19 | :undoc-members: 20 | :inherited-members: 21 | :show-inheritance: 22 | 23 | .. automodule:: bench.W1BSBench 24 | :members: 25 | :undoc-members: 26 | :inherited-members: 27 | :show-inheritance: 28 | 29 | .. automodule:: bench.RetrievalBenchmark 30 | :members: 31 | :undoc-members: 32 | :inherited-members: 33 | :show-inheritance: 34 | 35 | -------------------------------------------------------------------------------- /python/doc/test_baseline_matching.rst: -------------------------------------------------------------------------------- 1 | Test Baseline Benchmark (W1BS) 2 | ========================================================= 3 | This is how to run the baseline matching benchmark. 4 | 5 | .. code-block:: python 6 | 7 | # Define baseline benchmark 8 | bench = bench.W1BSBench.W1BSBench() 9 | 10 | # Define feature 11 | np_sift_py = features.np_sift.np_sift() 12 | 13 | # Define dataset 14 | w1bs = dset.W1BS_dataset.W1BS_Dataset() 15 | 16 | # Do the evaluation 17 | result_py = bench.evaluate(w1bs, np_sift_py, use_cache=True, save_result=True) 18 | 19 | # Make the results from different detectors as a list. 20 | result_list = [result_py] 21 | 22 | # Show the result 23 | bench.Utils.print_result(result_list, 'ap') 24 | 25 | 26 | Full code (test/test_W1BS_Bench.py): 27 | 28 | .. literalinclude:: ../test/test_W1BS_Bench.py 29 | -------------------------------------------------------------------------------- /examples/descbench.m: -------------------------------------------------------------------------------- 1 | % Setup and compile vlb, if run for the first time 2 | run(fullfile(fileparts(mfilename('fullpath')), '..', 'matlab', 'vlb_setup.m')); 3 | if ~exist(['vlb_greedy_matching.', mexext], 'file'), vlb_compile(); end; 4 | 5 | %% Run the experiment 6 | imdb = dset.vggh(); 7 | 8 | dets = vlb('detect', imdb, 'vggaff', 'detArgs', {'detector', 'hesaff'}); 9 | 10 | feats = {}; 11 | feats{end+1} = vlb('describe', imdb, dets, 'vggdesc'); 12 | feats{end+1} = vlb('describe', imdb, dets, 'vggdesc', ... 13 | 'descArgs', {'descriptor', 'gloh'}); 14 | 15 | res = cellfun(@(f) vlb('descmatch', imdb, f), feats, 'Uni', false); 16 | res = vertcat(res{:}); 17 | 18 | %% Show the mAP 19 | display(varfun(@mean, res, 'InputVariables', 'ap',... 20 | 'GroupingVariables', 'features')); 21 | 22 | %% Plot the precision recall curves 23 | figure(1); clf; 24 | vlb('view', 'descmatchpr', imdb, feats, 2); 25 | legend(feats, 'Location', 'SW'); 26 | -------------------------------------------------------------------------------- /matlab/+features/+desc/p_resize.m: -------------------------------------------------------------------------------- 1 | function [ res ] = p_resize(patches, varargin) 2 | opts.numbins = 4; 3 | opts = vl_argparse(opts, varargin); 4 | res = struct('descName', mfilename, 'describes', 'patches', 'args', opts); 5 | 6 | patches = single(squeeze(patches)); 7 | meanVal = reshape(mean(mean(patches, 1), 2), 1, 1, []); 8 | patchSz = [size(patches, 1), size(patches, 2)]; 9 | stdVal = reshape(std(reshape(single(patches), prod(patchSz(:)), []), 0, 1), 1, 1, []); 10 | patches = bsxfun(@rdivide, bsxfun(@minus, patches, meanVal), stdVal); 11 | 12 | x = zeros(opts.numbins^2, size(patches, 3), 'single'); 13 | for pi = 1:size(patches, 3) 14 | patch = imresize(patches(:,:,pi), [opts.numbins, opts.numbins], ... 15 | 'Antialiasing', false); 16 | x(:, pi) = patch(:); 17 | end 18 | % L2 norm 19 | l = sqrt(sum(x.^2, 1)); 20 | x = bsxfun(@rdivide, x, l); 21 | 22 | x(isnan(x)) = 0; 23 | x(isinf(x)) = 0; 24 | res.descs = x; 25 | 26 | end 27 | -------------------------------------------------------------------------------- /matlab/+utls/setup_matconvnet.m: -------------------------------------------------------------------------------- 1 | function setup_matconvnet(varargin) 2 | opts.url = 'https://github.com/vlfeat/matconvnet/archive/master.zip'; 3 | opts.rootDir = fullfile(vlb_path('vendor'), 'matconvnet'); 4 | opts = vl_argparse(opts, varargin); 5 | 6 | if ~exist('vl_nnconv', 'file') 7 | utls.provision(opts.url, opts.rootDir); 8 | run(fullfile(getlatest(opts.rootDir, 'matconvnet'), 'matlab', 'vl_setupnn.m')); 9 | 10 | if ~contains(which('vl_nnconv'), mexext) 11 | fprintf('MatConvNet not compiled. Attempting to run `vl_compilenn` (CPU ONLY, no imreadjpeg).\n'); 12 | fprintf('To compile with a GPU support, see `help vl_compilenn`.'); 13 | vl_compilenn('EnableImreadJpeg', false); 14 | end 15 | end 16 | 17 | end 18 | 19 | function out = getlatest(path, name) 20 | sel_dir = dir(fullfile(path, [name '*'])); 21 | sel_dir = sel_dir([sel_dir.isdir]); 22 | sel_dir = sort({sel_dir.name}); 23 | out = fullfile(path, sel_dir{end}); 24 | end -------------------------------------------------------------------------------- /python/doc/dataset.rst: -------------------------------------------------------------------------------- 1 | dset Module 2 | ================== 3 | This module defines the structure of different datasets 4 | 5 | .. automodule:: dset.dataset 6 | :members: 7 | :undoc-members: 8 | :inherited-members: 9 | :show-inheritance: 10 | 11 | .. automodule:: dset.retrieval_dataset 12 | :members: 13 | :undoc-members: 14 | :inherited-members: 15 | :show-inheritance: 16 | 17 | .. automodule:: dset.vgg_dataset 18 | :members: 19 | :undoc-members: 20 | :inherited-members: 21 | :show-inheritance: 22 | 23 | .. automodule:: dset.oxford5k_dataset 24 | :members: 25 | :undoc-members: 26 | :inherited-members: 27 | :show-inheritance: 28 | 29 | .. automodule:: dset.paris6k_dataset 30 | :members: 31 | :undoc-members: 32 | :inherited-members: 33 | :show-inheritance: 34 | 35 | .. automodule:: dset.W1BS_dataset 36 | :members: 37 | :undoc-members: 38 | :inherited-members: 39 | :show-inheritance: 40 | 41 | 42 | -------------------------------------------------------------------------------- /matlab/+utls/frame_dev.m: -------------------------------------------------------------------------------- 1 | function [ d ] = framedist( fa, fb, ignoreOrientation ) 2 | if nargin < 3, ignoreOrientation = false; end; 3 | assert(size(fa, 1) == size(fb, 1)); 4 | assert(size(fa, 2) == size(fb, 2)); 5 | 6 | useOrient = (size(fa, 1) == 3 || size(fa, 1) == 6) && ~ignoreOrientation; 7 | if useOrient, fun = @dev; else fun = @noor_dev; end 8 | fa = vl_frame2oell(fa); 9 | fb = vl_frame2oell(fb); 10 | 11 | d = zeros(1, size(fa, 2)); 12 | for fi = 1:size(fa, 2) 13 | d(fi) = fun(fa(:, fi), fb(:, fi)); 14 | end 15 | end 16 | 17 | function d = dev(fa, fb) 18 | Aa = reshape(fa(3:6), 2, 2); Ta = fa(1:2); 19 | Ab = reshape(fb(3:6), 2, 2); Tb = fb(1:2); 20 | 21 | Af = Ab \ Aa - eye(2); 22 | d = 0.25 * sum(diag(Af'*Af)) + sum((inv(Ab) * (Ta - Tb)).^2); 23 | end 24 | 25 | function d = noor_dev(fa, fb) 26 | Aa = reshape(fa(3:6), 2, 2); Ta = fa(1:2); 27 | Ab = reshape(fb(3:6), 2, 2); Tb = fb(1:2); 28 | 29 | Af = Ab \ Aa; 30 | s = sum(svd(Af)); 31 | d = 0.25 * (sum(diag(Af'*Af)) + 2 * (1 - s)) + sum((inv(Ab) * (Ta - Tb)).^2); 32 | end 33 | -------------------------------------------------------------------------------- /matlab/vlb_setup.m: -------------------------------------------------------------------------------- 1 | function vlb_setup() 2 | %VLB_SETUP Setup the VLB toolbox. 3 | % VLB_SETUP() function adds the VLB toolbox to MATLAB path. 4 | 5 | % Copyright (C) 2014-16 Andrea Vedaldi, Karel Lenc. 6 | % All rights reserved. 7 | % 8 | % This file is part of the VLFeat library and is made available under 9 | % the terms of the BSD license (see the COPYING file). 10 | 11 | root = vlb_path() ; 12 | pathCell = regexp(path, pathsep, 'split'); 13 | check_and_add(fullfile(root, 'matlab'), pathCell) 14 | check_and_add(fullfile(root, 'matlab', 'mex'), pathCell) 15 | check_and_add(fullfile(root, 'examples'), pathCell) 16 | check_and_add(fullfile(root, 'matlab', 'xtest'), pathCell) 17 | utls.setup_vlfeat(); 18 | end 19 | 20 | function check_and_add(add_folder,all_path) 21 | if isdeployed 22 | return 23 | end 24 | if ispc % Windows is not case-sensitive 25 | onPath = any(strcmpi(add_folder, all_path)); 26 | else 27 | onPath = any(strcmp(add_folder, all_path)); 28 | end 29 | 30 | if ~onPath 31 | addpath(add_folder); 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /python/features/cv_mser.py: -------------------------------------------------------------------------------- 1 | """ 2 | OpenCV MSER Implementation 3 | Author: Alex Butenko 4 | """ 5 | import cv2 6 | import numpy as np 7 | from features.DetectorDescriptorTemplate import DetectorAndDescriptor 8 | import sys 9 | 10 | 11 | class cv_mser(DetectorAndDescriptor): 12 | def __init__(self): 13 | super( 14 | cv_mser, 15 | self).__init__( 16 | name='cv_mser', 17 | is_detector=True, 18 | is_descriptor=False, 19 | is_both=False, 20 | patch_input=False) 21 | self.descriptor = None 22 | 23 | def detect_feature(self, image): 24 | mser = cv2.MSER_create() 25 | features = mser.detect(image, None) 26 | pts = np.array([features[idx].pt for idx in range(len(features))]) 27 | return pts 28 | 29 | def extract_descriptor(self, image, feature): 30 | pass 31 | 32 | def extract_all(self, image): 33 | pass 34 | 35 | def extract_descriptor_from_patch(self, patches): 36 | pass 37 | -------------------------------------------------------------------------------- /python/features/cv_fast.py: -------------------------------------------------------------------------------- 1 | """ 2 | OpenCV FAST Implementation 3 | Author: Alex Butenko 4 | """ 5 | import cv2 6 | import numpy as np 7 | from features.DetectorDescriptorTemplate import DetectorAndDescriptor 8 | import sys 9 | 10 | 11 | class cv_fast(DetectorAndDescriptor): 12 | def __init__(self): 13 | super( 14 | cv_fast, 15 | self).__init__( 16 | name='cv_fast', 17 | is_detector=True, 18 | is_descriptor=False, 19 | is_both=False, 20 | patch_input=True) 21 | self.descriptor = None 22 | 23 | def detect_feature(self, image): 24 | fast = cv2.FastFeatureDetector_create() 25 | features = fast.detect(image,None) 26 | pts = np.array([features[idx].pt for idx in range(len(features))]) 27 | return pts 28 | 29 | def extract_descriptor(self, image, feature): 30 | pass 31 | 32 | def extract_all(self, image): 33 | pass 34 | 35 | def extract_descriptor_from_patch(self, patches): 36 | pass 37 | -------------------------------------------------------------------------------- /matlab/vlb_imagelist.m: -------------------------------------------------------------------------------- 1 | function vlb_imagelist(imdb, feats, varargin) 2 | %VLB_IMAGELIST Export imagelist and target paths to a txt file 3 | % VLB_IMAGELIST imdb featsname 4 | 5 | % Copyright (C) 2016-2017 Karel Lenc 6 | % All rights reserved. 7 | % 8 | % This file is part of the VLFeat library and is made available under 9 | % the terms of the BSD license (see the COPYING file). 10 | 11 | opts.targetDir = vlb_path('imagelists'); 12 | opts = vl_argparse(opts, varargin); 13 | vl_xmkdir(opts.targetDir); 14 | 15 | imdb = dset.factory(imdb); 16 | if isstruct(feats), feats = feats.name; end; 17 | featsname = genvarname(feats); 18 | tgt_path = fullfile(opts.targetDir, sprintf('%s-%s.csv', imdb.name, featsname)); 19 | 20 | out = fopen(tgt_path, 'w'); 21 | for imi = 1:numel(imdb.images) 22 | impath = imdb.images(imi).path; 23 | tgtpath = fullfile(vlb_path('features', imdb, feats), [imdb.images(imi).name]); 24 | fprintf(out, '%s;%s;%s\n', impath, [tgtpath '.frames.csv'], [tgtpath '.descs.csv']); 25 | end 26 | fclose(out); 27 | fprintf('Output exported to %s\n', tgt_path); 28 | 29 | end -------------------------------------------------------------------------------- /matlab/+utls/randomtf.m: -------------------------------------------------------------------------------- 1 | function [ tf, info ] = randomtf( varargin ) 2 | opts.maxTr = 0; 3 | opts.maxAffScRot = 0; 4 | opts.maxRot = 0; 5 | opts.maxScale = 0; 6 | opts.minScale = 0; 7 | opts.maxAnisotropy = 0; 8 | opts.anisotropyShift = 0; 9 | opts.q = RandStream('mt19937ar','Seed', 0); 10 | opts.randfun = @(varargin) 2*rand(varargin{:}) - 1; 11 | opts = vl_argparse(opts, varargin); 12 | 13 | q = opts.q; 14 | 15 | tha = opts.randfun(q, 1) * opts.maxAffScRot; 16 | rota = [cos(tha) -sin(tha) ; sin(tha) cos(tha)]; 17 | 18 | % By default, the second rotation removes the affRotation 19 | thb = opts.randfun(q, 1) * opts.maxRot - tha; 20 | rotb = [cos(thb) -sin(thb) ; sin(thb) cos(thb)]; 21 | 22 | sc = 2.^(opts.randfun(q, 1) * (opts.maxScale - opts.minScale) + opts.minScale); 23 | anis = 2.^(opts.randfun(q, 1) * opts.maxAnisotropy + opts.anisotropyShift); 24 | scg = [sc / sqrt(anis) 0; 0 sc * sqrt(anis)]; 25 | 26 | Tg = opts.randfun(q, 2,1) * opts.maxTr ; 27 | tf = [rotb*scg*rota, Tg; 0 0 1] ; 28 | 29 | if nargout == 2 30 | info = struct('affScRot', tha, 'rot', thb, 'sc', sc, 'anis', anis); 31 | end 32 | 33 | end -------------------------------------------------------------------------------- /python/doc/index.rst: -------------------------------------------------------------------------------- 1 | .. VL Benchmark documentation master file, created by 2 | sphinx-quickstart on Fri Mar 1 23:51:26 2019. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to VL Benchmark's documentation! 7 | ======================================== 8 | .. only: not latex 9 | 10 | Contents: 11 | 12 | .. toctree:: 13 | :caption: Introduction 14 | :maxdepth: 1 15 | 16 | intro 17 | 18 | .. toctree:: 19 | :caption: How to write test code 20 | :maxdepth: 1 21 | 22 | test_match 23 | test_retrieval 24 | test_baseline_matching 25 | 26 | .. toctree:: 27 | :caption: How to create your own feature, dataset and benchmark 28 | :maxdepth: 1 29 | 30 | new_feature 31 | new_dataset 32 | 33 | 34 | .. toctree:: 35 | :caption: The Modules 36 | :maxdepth: 2 37 | 38 | feature 39 | dataset 40 | benchmark 41 | 42 | 43 | Indices and tables 44 | ====================================== 45 | 46 | * :ref:`genindex` 47 | * :ref:`modindex` 48 | * :ref:`search` 49 | -------------------------------------------------------------------------------- /matlab/+utls/features_save.m: -------------------------------------------------------------------------------- 1 | function features_save( path, features, varargin ) 2 | %FEATURES_SAVE Save a features structure at the specified path 3 | opts.skipFields = {}; 4 | opts = vl_argparse(opts, varargin); 5 | 6 | fields = setdiff(fieldnames(features), opts.skipFields); 7 | [respath, imname] = fileparts(path); 8 | 9 | try 10 | for fi = 1:numel(fields) 11 | field = fields{fi}; 12 | tgtpath = fullfile(respath, [imname, '.', field]); 13 | data = features.(field); 14 | switch class(data) 15 | case {'double', 'single', 'uint8'} 16 | dlmwrite([tgtpath, '.csv'], data', ';'); 17 | case {'char'} 18 | fd = fopen([tgtpath, '.txt'], 'w'); 19 | fprintf(fd, '%s', data); 20 | fclose(fd); 21 | otherwise 22 | save([tgtpath, '.mat'], '-v7.3', 'data'); 23 | end 24 | end 25 | catch e 26 | fprintf('Cleaning up %s due to error', path); 27 | for fi = 1:numel(fields) 28 | field = fields{fi}; 29 | tgtpath = fullfile(respath, [imname, '.', field]); 30 | if exist(tgtpath, 'file') 31 | delete(tgtpath); 32 | end 33 | end 34 | throw(e); 35 | end 36 | 37 | end 38 | 39 | -------------------------------------------------------------------------------- /python/doc/test_retrieval.rst: -------------------------------------------------------------------------------- 1 | Test Retrieval Benchmark 2 | ====================================================== 3 | This is how to run the retrieval benchmark 4 | 5 | .. code-block:: python 6 | 7 | # Define retrieval benchmark 8 | retrieval_bench = bench.RetrievalBenchmark.RetrievalBenchmark() 9 | 10 | # Define feature 11 | vlsift_py = features.cyvlsift_official.cyvlsift_official() 12 | 13 | # Define dataset 14 | paris6k = dset.paris6k_dataset.paris6k_Dataset() 15 | 16 | # Do the evaluation 17 | map_result_py = retrieval_bench.evaluate( 18 | paris6k, vlsift_py, use_cache=True, save_result=True) 19 | 20 | # Make the results from different detectors as a list. 21 | # (Only one here, but you can add more) 22 | map_result = [map_result_py] 23 | 24 | # Show the result 25 | for result_term in map_result[0]['result_term_list']: 26 | bench.Utils.print_retrieval_result(map_result, 'm' + result_term) 27 | bench.Utils.save_retrieval_result(map_result, 'm' + result_term) 28 | 29 | 30 | Full code (test/test_retrieval_bench.py): 31 | 32 | .. literalinclude:: ../test/test_retrieval_bench.py 33 | -------------------------------------------------------------------------------- /matlab/+utls/textprogressbar_LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /python/test/draw_frame.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # =========================================================== 4 | # File Name: draw_frame.py 5 | # Author: Xu Zhang, Columbia University 6 | # Creation Date: 01-25-2019 7 | # Last Modified: Sat Feb 9 11:09:58 2019 8 | # 9 | # Usage: python draw_frame.py 10 | # Description: Draw frame of the feature 11 | # 12 | # Copyright (C) 2018 Xu Zhang 13 | # All rights reserved. 14 | # 15 | # This file is made available under 16 | # the terms of the BSD license (see the COPYING file). 17 | # =========================================================== 18 | 19 | import sys 20 | 21 | sys.path.insert(0, '/Users/Xu/program/Image_Genealogy/code/vlb/python/dset/') 22 | sys.path.insert( 23 | 0, '/Users/Xu/program/Image_Genealogy/code/vlb/python/features/') 24 | sys.path.insert(0, '/Users/Xu/program/Image_Genealogy/code/vlb/python/bench/') 25 | 26 | import Utils 27 | import vlsift_matlab 28 | import vlsift 29 | import vgg_dataset 30 | 31 | 32 | if __name__ == "__main__": 33 | 34 | a = vgg_dataset.vggh_Dataset() 35 | vlsift_matlab = vlsift_matlab.vlsift_matlab() 36 | Utils.draw_feature(a, 'bikes', '1', vlsift_matlab) 37 | -------------------------------------------------------------------------------- /python/doc/intro.rst: -------------------------------------------------------------------------------- 1 | About This Project 2 | ============================ 3 | 4 | A framework for local feature evaluation. 5 | Reimplementation of the VLBenchmarks project. 6 | 7 | MATLAB implementation: `Karel Lenc `_ 8 | 9 | Python implementation: `Xu Zhang `_ 10 | 11 | Python Interface 12 | ------------------------- 13 | 14 | Requirement 15 | ^^^^^^^^^^^^^^^^^^^^^^^^ 16 | 17 | We recommend to use conda to install all the requirements all at once. 18 | 19 | 20 | ``conda env create -f ./python/conda/environment.yml`` 21 | 22 | 23 | Test the code 24 | ^^^^^^^^^^^^^^^^^^^^^^^^^ 25 | 26 | Test repeatability benchmark 27 | 28 | >>> python ./python/test/test_rep_bench.py 29 | 30 | 31 | Test matching score benchmark 32 | 33 | >>> python ./python/test/test_ms_bench.py 34 | 35 | 36 | Test image retrieval benchmark 37 | 38 | >>> python ./python/test/test_retrieval_bench.py 39 | 40 | 41 | Test wide baseline matching benchmark 42 | 43 | >>> python ./python/test/test_W1BS_Bench.py 44 | 45 | Test feature extraction 46 | 47 | >>> python ./python/test/test_feature_extraction.py 48 | 49 | Test draw feature 50 | 51 | >>> python ./python/test/draw_frame.py 52 | -------------------------------------------------------------------------------- /matlab/+utls/patches_extract_covdet.m: -------------------------------------------------------------------------------- 1 | function [ patches, varargin ] = patches_extract_covdet( ima, fms, varargin ) 2 | %EXTRACT_PATCHES_COVDET Extract patches using VL_COVDET 3 | opts.patchResolution = 32; 4 | opts.baseScale = 0.6; 5 | opts.patchRelativeSmoothing = 0.1; 6 | opts.doubleImage = true; 7 | opts.scalingFactor = 1; 8 | [opts, varargin] = vl_argparse(opts, varargin); 9 | args = utls.struct2argscell(opts); 10 | args = args(1:end-2); 11 | 12 | if isempty(ima) || isempty(fms),patches = []; return; end; 13 | is_uint = isa(ima, 'uint8'); 14 | ima = utls.covdet_preprocessim(ima); 15 | try 16 | [~, patches] = vl_covdet(ima, 'frames', fms, 'Descriptor', 'patch', ... 17 | 'PatchRelativeExtent', opts.scalingFactor, args{:}); 18 | catch 19 | warning('vlb:oldvlfeat', 'Old version of VL_COVDET without baseScale, using fallback method.'); 20 | warning('off', 'vlb:oldvlfeat'); 21 | [patches, varargin] = utls.patches_extract_interp(ima, fms, ... 22 | 'scalingFactor', opts.scalingFactor, args{:}); 23 | end 24 | patchesSz = [opts.patchResolution*2 + 1, opts.patchResolution*2 + 1, ... 25 | 1, size(fms,2)]; 26 | patches = reshape(patches, patchesSz); 27 | 28 | if is_uint, patches = uint8(patches * 255); end 29 | 30 | end 31 | 32 | -------------------------------------------------------------------------------- /matlab/+utls/ellipse_eigen.m: -------------------------------------------------------------------------------- 1 | function [eigval, eigvec] = ellipse_eigen(frames) 2 | % ELLIPSE_EIGEN Computes the eigenvalues an eigenvectors for an ellipse 3 | % [EIGVAL, EIGVEC] = ELLIPSE_EIGEN(FRAMES) calculates the eigenvalues 4 | % EIGVAL and eigenvectors EIGVEC of the elliptical frames 5 | % FRAMES. The covariance of an ellipse is given by 6 | % 7 | % S = [FRAMES(3) FRAMES(4)] 8 | % [FRAMES(4) FRAMES(5)] 9 | % 10 | % then EIGVAL contains the eigenvalues of this matrix and EIGVEC the 11 | % corresponding eigenvectors (stacked), such that 12 | % 13 | % S * reshape(eigvec,2,2) = reshape(eigvec,2,2) * diag(eigval). 14 | % 15 | % If FRAMES contains more than one elliptical frame, then EIGVEC 16 | % and EIGVAL have one column per frame. 17 | 18 | % Copyright (C) 2011-16 Andrea Vedaldi, Karel Lenc 19 | % All rights reserved. 20 | % 21 | % This file is part of the VLFeat library and is made available under 22 | % the terms of the BSD license (see the COPYING file). 23 | 24 | numFrames = size(frames,2); 25 | eigval = zeros(2,numFrames); 26 | eigvec = zeros(4,numFrames); 27 | 28 | for i=1:numFrames 29 | [V, D] = eig(reshape(frames([3 4 4 5],i),2,2)) ; 30 | eigvec(:,i) = V(:) ; 31 | eigval(:,i) = D([1 4]) ; 32 | end 33 | -------------------------------------------------------------------------------- /python/test/test_feature_extraction.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # =========================================================== 4 | # File Name: test_feature_extraction.py 5 | # Author: Xu Zhang, Columbia University 6 | # Creation Date: 01-25-2019 7 | # Last Modified: Sat Feb 9 11:13:09 2019 8 | # 9 | # Usage: python test_feature_extraction.py 10 | # Description: Test feature extraction 11 | # 12 | # Copyright (C) 2018 Xu Zhang 13 | # All rights reserved. 14 | # 15 | # This file is made available under 16 | # the terms of the BSD license (see the COPYING file). 17 | # =========================================================== 18 | 19 | import sys 20 | 21 | sys.path.insert(0, '/Users/Xu/program/Image_Genealogy/code/vlb/python/dset/') 22 | sys.path.insert( 23 | 0, '/Users/Xu/program/Image_Genealogy/code/vlb/python/features/') 24 | import feature_utils 25 | import vlsift_matlab 26 | import vlsift 27 | import vgg_dataset 28 | 29 | 30 | if __name__ == "__main__": 31 | 32 | a = vgg_dataset.vggh_Dataset() 33 | image = a.get_image('graf', '1') 34 | #vlsift_all = vlsift.vlsift() 35 | vlsift_all = vlsift_matlab.vlsift_matlab() 36 | feature, descriptor = vlsift_all.extract_all(image) 37 | print(feature.shape, descriptor.shape) 38 | -------------------------------------------------------------------------------- /matlab/+features/+det/ddet.m: -------------------------------------------------------------------------------- 1 | function res = ddet(img, varargin) 2 | 3 | opts.url = 'https://codeload.github.com/lenck/ddet/zip/master'; 4 | opts.rootDir = fullfile(vlb_path('vendor'), 'ddet'); 5 | [opts, varargin] = vl_argparse(opts, varargin); 6 | opts.binDir = fullfile(opts.rootDir, 'ddet-master'); 7 | opts.netsDir = fullfile(opts.binDir, 'nets'); 8 | opts.netsUrl = fullfile(opts.binDir, 'nets', 'nets.url'); 9 | [opts, varargin] = vl_argparse(opts, varargin); 10 | opts.net = fullfile(opts.netsDir, 'detnet_s2.mat'); 11 | opts.thr = 4; 12 | opts = vl_argparse(opts, varargin); 13 | 14 | [~,netname,~] = fileparts(opts.net); 15 | res.detName = sprintf('ddet-%s', netname); res.args = opts; 16 | if isempty(img), res.frames = zeros(5, 0); return; end; 17 | 18 | utls.setup_matconvnet(); 19 | utls.provision(opts.url, opts.rootDir, 'forceExt', '.zip'); 20 | utls.provision(opts.netsUrl, opts.netsDir); 21 | if ~exist('DDet.m', 'file') 22 | addpath(opts.binDir); 23 | vlb_setup(); 24 | delete(fullfile(opts.binDir, '+utls', 'provision.m')); 25 | end 26 | net = dagnn.DagNN.loadobj(load(opts.net)); 27 | stime = tic; 28 | det = DDet(net, 'thr', opts.thr); 29 | res.dettime = toc(stime); 30 | 31 | [frames, ~, info] = det.detect(img); 32 | res.frames = frames; 33 | res.peakScores = info.peakScores; 34 | 35 | end -------------------------------------------------------------------------------- /matlab/xtest/suite/test_detrepthr_benchmark.m: -------------------------------------------------------------------------------- 1 | classdef test_detrepthr_benchmark < matlab.unittest.TestCase 2 | 3 | properties (TestParameter) 4 | detector = {@features.det.vlcovdet}; 5 | dataset = {dset.vggh}; 6 | taskid = {1, 6, 11}; 7 | end 8 | 9 | methods (Test) 10 | function repeatability(test, detector, dataset, taskid) 11 | [~,ima_id] = ismember(dataset.tasks(taskid).ima, {dataset.images.name}); 12 | [~,imb_id] = ismember(dataset.tasks(taskid).imb, {dataset.images.name}); 13 | 14 | ima_p = dataset.images(ima_id).path; 15 | fa = detector(single(utls.imread_grayscale(ima_p))); 16 | 17 | imb_p = dataset.images(imb_id).path; 18 | fb = detector(single(utls.imread_grayscale(imb_p))); 19 | 20 | g = dataset.tasks(taskid); 21 | matchFrames = @(fa, fb) geom.ellipse_overlap_H(g, fa, fb, ... 22 | 'maxOverlapError', 0.5); 23 | 24 | res = bench.detrepthr(matchFrames, fa, fb); 25 | test.verifyLessThanOrEqual(res.repeatability, 1); 26 | if 0 27 | figure(1); 28 | subplot(1,2,1); hold on; 29 | plot(res.numDets, res.repeatability); 30 | drawnow; 31 | subplot(1,2,2); hold on; 32 | plot(res.numMatches, res.repeatability); 33 | drawnow; 34 | end 35 | end 36 | end 37 | 38 | end 39 | -------------------------------------------------------------------------------- /matlab/+utls/frame2ellipse.m: -------------------------------------------------------------------------------- 1 | function g = frame2ellipse(f) 2 | % FRAME2ELLIPSE converts frames to ellpises 3 | % ELL = FRAME2ELLIPSE(F) converts the specified frames F to unoriented 4 | % ellipses ELL. If the frame is already an ellipse does not do anything 5 | % and in case of an oriented ellipse converts into unoriented. 6 | 7 | % Copyright (C) 2011-16 Andrea Vedaldi, Karel Lenc 8 | % All rights reserved. 9 | % 10 | % This file is part of the VLFeat library and is made available under 11 | % the terms of the BSD license (see the COPYING file). 12 | 13 | if isempty(f) 14 | g=[]; 15 | return; 16 | end 17 | 18 | switch size(f, 1) 19 | case 2 20 | g(1:2,:) = f(1:2,:); % center 21 | g([3 5],:) = ones(2, size(f, 2)) ; 22 | case 2+1 % Disc 23 | g(1:2,:) = f(1:2,:); % center 24 | g([3 5],:) = [1;1] * (f(3,:) .* f(3,:)) ; 25 | 26 | case 2+2 % Oriented disc 27 | g(1:2,:) = f(1:2,:); % center 28 | g([3 5],:) = [1;1] * (f(3,:) .* f(3,:)) ; 29 | 30 | case 2+3 % Ellipse (unoriented) 31 | g = f ; 32 | 33 | case 2+4 % Oriented ellipse - remove orientation 34 | g(1:2,:) = f(1:2,:); % center 35 | for k=1:size(f,2) 36 | A = reshape(f(3:6,k)',2,2)'; 37 | E = A' * A; 38 | g(3:5,k) = [E(1,1) E(1,2) E(2,2)]'; 39 | end 40 | 41 | otherwise 42 | error('Unrecognized frame format') ; 43 | end 44 | -------------------------------------------------------------------------------- /python/conda/environment.yml: -------------------------------------------------------------------------------- 1 | name: vlb 2 | channels: 3 | - anaconda 4 | - conda-forge 5 | - menpo 6 | - pytorch 7 | - defaults 8 | dependencies: 9 | - freetype 10 | - libgcc 11 | - libgfortran 12 | - bzip2 13 | - ca-certificates 14 | - dbus 15 | - expat 16 | - gettext 17 | - gst-plugins-base 18 | - gstreamer 19 | - jasper 20 | - jpeg 21 | - libffi 22 | - libpng 23 | - libtiff 24 | - libxcb 25 | - ncurses 26 | - openblas 27 | - openssl 28 | - pcre 29 | - pytz 30 | - readline 31 | - sqlite 32 | - tqdm 33 | - xorg-libxau 34 | - xorg-libxdmcp 35 | - xz 36 | - zlib 37 | - asn1crypto 38 | - backports_abc 39 | - blas 40 | - certifi 41 | - cffi 42 | - chardet 43 | - cryptography 44 | - cryptography-vectors 45 | - cycler 46 | - cython 47 | - decorator 48 | - fontconfig 49 | - glib 50 | - hdf5 51 | - icu 52 | - idna 53 | - intel-openmp 54 | - ipython_genutils 55 | - jsonschema 56 | - jupyter_core 57 | - libgfortran-ng 58 | - libiconv 59 | - libxml2 60 | - matplotlib 61 | - mkl 62 | - nbformat 63 | - numpy 64 | - olefile 65 | - opencv 66 | - pillow 67 | - pip 68 | - plotly 69 | - pycparser 70 | - pyopenssl 71 | - pyparsing 72 | - pyqt 73 | - pysocks 74 | - python 75 | - qt 76 | - requests 77 | - retrying 78 | - scikit-learn 79 | - scipy 80 | - setuptools 81 | - sip 82 | - six 83 | - tk 84 | - tornado 85 | - traitlets 86 | - urllib3 87 | - wheel 88 | - cyvlfeat 89 | - pytorch 90 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2017, Karel Lenc 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 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the 12 | distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /matlab/+utls/frame_get_scale.m: -------------------------------------------------------------------------------- 1 | function scales = frame_get_scale(frames) 2 | % GETFRAMESSCALE Return scales of a frame 3 | % SCALE = GETFRAMESCALE(FRAME) When FRAME is a column vector of 4 | % 2 < size(F,1) < 7 SCALE is scale (scalar) of the frame. 5 | % 6 | % SCALES = GETFRAMESCALE(FRAMES) When FRAMES is a matrix of 7 | % 2 < size(F,1) < 7 SCALES is a row vector of 8 | % size(SCALES,2) = size(FRAMES,2) with frame scales. 9 | % 10 | % For elliptic frames the scale is computed as square root of the 11 | % determinant of the affine transformation. This can be expressed as 12 | % square root of the ratio between the ellipse area and unit circle. 13 | 14 | % Authors: Karel Lenc 15 | 16 | % AUTORIGHTS 17 | import localFeatures.helpers.*; 18 | if isstruct(frames) 19 | frames = frames.frames; 20 | end 21 | 22 | if isempty(frames) 23 | scales = []; 24 | return; 25 | end 26 | 27 | switch size(frames,1) 28 | case {3,4} 29 | scales = frames(3,:); 30 | case 5 31 | det = prod(frames([3 5],:)) - frames(4,:).^2; 32 | if det >= 0 33 | scales = sqrt(sqrt(det)); 34 | else 35 | error('Invalid ellipse matrix.'); 36 | end 37 | case 6 38 | det = prod(frames([3 6],:)) - prod(frames([4 5],:)); 39 | if det > 0 40 | scales = sqrt(det); 41 | else 42 | error('Invalid affine transformation.'); 43 | end 44 | otherwise 45 | error('Invalid frame'); 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /matlab/+utls/frame_set_scale.m: -------------------------------------------------------------------------------- 1 | function frames = frame_set_scale(frames, scales) 2 | 3 | % Authors: Karel Lenc 4 | 5 | % AUTORIGHTS 6 | import localFeatures.helpers.*; 7 | 8 | feats = []; 9 | if isstruct(frames) 10 | feats = frames; 11 | frames = frames.frames; 12 | end 13 | 14 | if isempty(frames) 15 | frames = []; 16 | return; 17 | end 18 | 19 | if size(frames,2) ~= numel(scales) 20 | error('Number of frames and scales must be the same'); 21 | end 22 | 23 | switch size(frames,1) 24 | case {3,4} 25 | frames(3,:) = scales; 26 | case 5 27 | det = prod(frames([3 5],:)) - frames(4,:).^2; 28 | if det >= 0 29 | % new det should be scales^4 and multiplying matrix by a will change 30 | % determinant with a^2... 31 | ratio = scales.^2/sqrt(det); 32 | frames(3:5,:) = frames(3:5,:).*ratio; 33 | else 34 | error('Invalid ellipse matrix.'); 35 | end 36 | case 6 37 | det = prod(frames([3 6],:)) - prod(frames([4 5],:)); 38 | if det > 0 39 | % new det should be scales^2 and multiplying matrix by a will change 40 | % determinant with a^2... 41 | ratio = scales/sqrt(det); 42 | frames(3:6,:) = frames(3:6,:).*ratio; 43 | else 44 | error('Invalid affine transformation.'); 45 | end 46 | otherwise 47 | error('Invalid frame'); 48 | end 49 | 50 | if ~isempty(feats) 51 | feats.frames = frames; 52 | frames = feats; 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /python/features/cv_orb.py: -------------------------------------------------------------------------------- 1 | """ 2 | OpenCV ORB Implementation 3 | Author: Alex Butenko 4 | """ 5 | import cv2 6 | import numpy as np 7 | from features.DetectorDescriptorTemplate import DetectorAndDescriptor 8 | import sys 9 | 10 | 11 | class cv_orb(DetectorAndDescriptor): 12 | def __init__(self): 13 | super( 14 | cv_orb, 15 | self).__init__( 16 | name='cv_orb', 17 | is_detector=True, 18 | is_descriptor=True, 19 | is_both=True, 20 | patch_input=True) 21 | self.descriptor = None 22 | 23 | def detect_feature(self, image): 24 | orb = cv2.ORB_create() 25 | features = orb.detect(image,None) 26 | pts = np.array([features[idx].pt for idx in range(len(features))]) 27 | return pts 28 | 29 | def extract_descriptor(self, image, feature): 30 | orb = cv2.ORB_create() 31 | features = orb.detect(image,None) 32 | _ , descriptors = orb.compute(image, features) 33 | return descriptors 34 | 35 | def extract_all(self, image): 36 | orb = cv2.ORB_create() 37 | features = orb.detect(image,None) 38 | features, descriptors = orb.compute(image, features) 39 | pts = np.array([features[idx].pt for idx in range(len(features))]) 40 | return (pts, descriptors) 41 | 42 | def extract_descriptor_from_patch(self, patches): 43 | pass 44 | -------------------------------------------------------------------------------- /python/features/np_sift.py: -------------------------------------------------------------------------------- 1 | from features.numpy_sift import SIFTDescriptor 2 | 3 | import numpy as np 4 | import features.feature_utils 5 | from features.DetectorDescriptorTemplate import DetectorAndDescriptor 6 | 7 | class np_sift(DetectorAndDescriptor): 8 | def __init__(self, peak_thresh=10.0): 9 | super( 10 | np_sift, 11 | self).__init__( 12 | name='np_sift', 13 | is_detector=True, 14 | is_descriptor=True, 15 | is_both=True, 16 | patch_input=True) 17 | self.peak_thresh = peak_thresh 18 | self.descriptor = None 19 | 20 | def detect_feature(self, image): 21 | pass 22 | 23 | def extract_descriptor(self, image, feature): 24 | pass 25 | 26 | def extract_all(self, image): 27 | pass 28 | 29 | def extract_descriptor_from_patch(self, patches): 30 | patch_num = patches.shape[0] 31 | patches.shape[1] 32 | w = patches.shape[2] 33 | if self.descriptor is None or self.descriptor.patchSize != w: 34 | self.descriptor = SIFTDescriptor(w) 35 | descriptors = np.zeros((patch_num, 128)) 36 | for i in range(patch_num): 37 | patch = features.feature_utils.all_to_gray(patches[i, :, :, :]) 38 | patch = patch[:, :, 0] 39 | descriptors[i, :] = self.descriptor.describe(patch).flatten() 40 | return descriptors 41 | -------------------------------------------------------------------------------- /python/features/cv_kaze.py: -------------------------------------------------------------------------------- 1 | """ 2 | OpenCV KAZE Implementation 3 | Author: Alex Butenko 4 | """ 5 | import cv2 6 | import numpy as np 7 | from features.DetectorDescriptorTemplate import DetectorAndDescriptor 8 | import sys 9 | 10 | 11 | class cv_kaze(DetectorAndDescriptor): 12 | def __init__(self): 13 | super( 14 | cv_kaze, 15 | self).__init__( 16 | name='cv_kaze', 17 | is_detector=True, 18 | is_descriptor=True, 19 | is_both=True, 20 | patch_input=True) 21 | self.descriptor = None 22 | 23 | def detect_feature(self, image): 24 | kaze = cv2.KAZE_create() 25 | features = kaze.detect(image,None) 26 | pts = np.array([features[idx].pt for idx in range(len(features))]) 27 | return pts 28 | 29 | def extract_descriptor(self, image, feature): 30 | kaze = cv2.KAZE_create() 31 | features = kaze.detect(image,None) 32 | _ , descriptors = kaze.compute(image, features) 33 | return descriptors 34 | 35 | def extract_all(self, image): 36 | kaze = cv2.KAZE_create() 37 | features = kaze.detect(image,None) 38 | features , descriptors = kaze.compute(image, features) 39 | pts = np.array([features[idx].pt for idx in range(len(features))]) 40 | return (pts, descriptors) 41 | 42 | def extract_descriptor_from_patch(self, patches): 43 | pass 44 | -------------------------------------------------------------------------------- /python/features/cv_brisk.py: -------------------------------------------------------------------------------- 1 | """ 2 | OpenCV BRISK Implementation 3 | Author: Alex Butenko 4 | """ 5 | import cv2 6 | import numpy as np 7 | from features.DetectorDescriptorTemplate import DetectorAndDescriptor 8 | import sys 9 | 10 | class cv_brisk(DetectorAndDescriptor): 11 | def __init__(self): 12 | super( 13 | cv_brisk, 14 | self).__init__( 15 | name='cv_brisk', 16 | is_detector=True, 17 | is_descriptor=True, 18 | is_both=True, 19 | patch_input=True) 20 | self.descriptor = None 21 | 22 | def detect_feature(self, image): 23 | brisk = cv2.BRISK_create() 24 | features = brisk.detect(image,None) 25 | pts = np.array([features[idx].pt for idx in range(len(features))]) 26 | return pts 27 | 28 | def extract_descriptor(self, image, feature): 29 | brisk = cv2.BRISK_create() 30 | features = brisk.detect(image,None) 31 | _ , descriptors = brisk.compute(image, features) 32 | return descriptors 33 | 34 | def extract_all(self, image): 35 | brisk = cv2.BRISK_create() 36 | features = brisk.detect(image,None) 37 | features , descriptors = brisk.compute(image, features) 38 | pts = np.array([features[idx].pt for idx in range(len(features))]) 39 | return (pts, descriptors) 40 | 41 | def extract_descriptor_from_patch(self, patches): 42 | pass 43 | -------------------------------------------------------------------------------- /matlab/mex/vlb_greedy_matching.m: -------------------------------------------------------------------------------- 1 | function vlb_greedy_matching() 2 | % VLB_GREEDY_MATCHING Compute greedy bipartite matching 3 | % M = VLB_GREEDY_MATCHING(NUM_A_NODES,NUM_B_NODES,EDGES) 4 | % Calculates bipartite matching between two sets of nodes 5 | % A = {1,...,NUM_A_NODES} and B = {1,...,NUM_B_NODES} based on 6 | % the sorted list of edges EDGES. 7 | % 8 | % EDGES array has got two columns where each row [a b] defines 9 | % edge between node a \in A and b \in B. 10 | % 11 | % Algorithm basically goes sequentially through the EDGES and 12 | % matches all vertices which has not been matched yet. Therefore 13 | % the ranked list of EDGES represents edge weighting. 14 | % 15 | % M is of size [2, NUM_A_NODES]. The first row contains the index of a 16 | % matched B node (\int [1, NUM_B_NODES]) and the second row contains the 17 | % index of the edge from EDGES which was used to create this match. 18 | % 19 | % [M, SC] = VLB_GREEDY_MATCHING(NUM_A_NODES,NUM_B_NODES,EDGES) returns 20 | % the array SC of same size as M. First row of SC contains the index of 21 | % second closest B_NODE and second row the edge used to create the second 22 | % closest match. 23 | 24 | % Copyright (C) 2011-16 Karel Lenc 25 | % All rights reserved. 26 | % 27 | % This file is part of the VLFeat library and is made available under 28 | % the terms of the BSD license (see the COPYING file). 29 | 30 | error('Mex files not compiled. Please run `vlb_compile`.'); 31 | -------------------------------------------------------------------------------- /python/features/cv_akaze.py: -------------------------------------------------------------------------------- 1 | """ 2 | OpenCV AKAZE Implementation 3 | Author: Alex Butenko 4 | """ 5 | import cv2 6 | import numpy as np 7 | from features.DetectorDescriptorTemplate import DetectorAndDescriptor 8 | import sys 9 | 10 | 11 | class cv_akaze(DetectorAndDescriptor): 12 | def __init__(self): 13 | super( 14 | cv_akaze, 15 | self).__init__( 16 | name='cv_akaze', 17 | is_detector=True, 18 | is_descriptor=True, 19 | is_both=True, 20 | patch_input=True) 21 | self.descriptor = None 22 | 23 | def detect_feature(self, image): 24 | akaze = cv2.AKAZE_create() 25 | features = akaze.detect(image,None) 26 | pts = np.array([features[idx].pt for idx in range(len(features))]) 27 | return pts 28 | 29 | def extract_descriptor(self, image, feature): 30 | akaze = cv2.AKAZE_create() 31 | features = akaze.detect(image,None) 32 | _ , descriptors = akaze.compute(image, features) 33 | return descriptors 34 | 35 | def extract_all(self, image): 36 | akaze = cv2.AKAZE_create() 37 | features = akaze.detect(image,None) 38 | features , descriptors = akaze.compute(image, features) 39 | pts = np.array([features[idx].pt for idx in range(len(features))]) 40 | return (pts, descriptors) 41 | 42 | def extract_descriptor_from_patch(self, patches): 43 | pass 44 | -------------------------------------------------------------------------------- /matlab/xtest/suite/test_dets.m: -------------------------------------------------------------------------------- 1 | classdef test_dets < matlab.unittest.TestCase 2 | properties (TestParameter) 3 | detector = utls.listfiles(fullfile(vlb_path(), 'matlab', '+features', '+det', '*.m'), 'keepext', false, 'fullpath', false); 4 | image = {... 5 | rand(0, 0, 1), ... 6 | rand(50, 50, 1), ... 7 | rand(50, 50, 3), ... 8 | rand(50, 50, 3, 'single'), ... 9 | vl_impattern('roofs1'), ... 10 | im2uint8(vl_impattern('roofs2'))}; 11 | end 12 | 13 | methods (Test) 14 | function testdet(test, detector, image) 15 | % Try if this works 16 | det = features.factory('det', detector); 17 | % Create the functor from scratch 18 | det_fun = str2func(['features.det.', detector]); 19 | test.verifyEqual(nargout(det_fun), 1); 20 | [det_info] = det_fun([]); 21 | test.verifyTrue(isfield(det_info, 'detName')); 22 | imsize = size(image); 23 | feats = det_fun(image); 24 | test.verifyTrue(isfield(feats, 'frames')); 25 | frames = feats.frames; 26 | test.verifyGreaterThanOrEqual(size(frames, 1), 2); 27 | test.verifyLessThanOrEqual(size(frames, 1), 6); 28 | if ~isempty(frames) 29 | test.verifyGreaterThan(frames(1:2,:), 0); 30 | % Frames in IMAGE coordinates, not Matlab matrix coords 31 | test.verifyLessThan(frames(2,:), imsize(1)+1); 32 | test.verifyLessThan(frames(1,:), imsize(2)+1); 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /matlab/+utls/patches_extract_interp.m: -------------------------------------------------------------------------------- 1 | function [ patches, varargin ] = patches_extract_interp( ima, fms, varargin ) 2 | %EXTRACT_PATCHES_COVDET Extract patches using VL_COVDET 3 | 4 | % TODO test that it gives same output as vl_covdet 5 | 6 | opts.patchResolution = 32; 7 | opts.scalingFactor = 1; 8 | opts.method = 'linear'; 9 | if nargout == 1 10 | opts = vl_argparse(opts, varargin); 11 | else 12 | [opts, varargin] = vl_argparse(opts, varargin); 13 | end 14 | fms = vl_frame2oell(fms); 15 | 16 | is_uint = isa(ima, 'uint8'); 17 | if is_uint, ima = single(ima) ./ 255; end 18 | if size(ima, 3) == 3, ima = rgb2gray(ima); end; 19 | 20 | outsz = opts.patchResolution*2 + 1; 21 | patches = zeros(outsz, outsz, 1, size(fms, 2), 'like', ima); 22 | s = linspace(-1, 1, outsz); 23 | [R_n, C_n] = ndgrid(s, s); 24 | P_n = [C_n(:), R_n(:)]'; 25 | 26 | for pi = 1:size(fms, 2) 27 | H = utls.frame2afftf(utls.frame_magnify_scale(fms(:, pi), opts.scalingFactor)); 28 | P_i = p2e(H*e2p(P_n)) + 1; 29 | % 'Query' rows and columns 30 | R_i = reshape(P_i(2,:), outsz, outsz); 31 | C_i = reshape(P_i(1,:), outsz, outsz); 32 | patches(:,:,pi) = interp2(ima, C_i, R_i, opts.method); 33 | end 34 | 35 | if is_uint, patches = uint8(patches * 255); end 36 | 37 | end 38 | 39 | function [ pts ] = e2p( pts ) 40 | pts = [pts;ones(1,size(pts,2))]; 41 | end 42 | 43 | function [ pts ] = p2e( pts ) 44 | pts = pts./repmat(pts(size(pts,1),:),size(pts,1),1); 45 | pts = pts(1:size(pts,1)-1,:); 46 | end 47 | 48 | -------------------------------------------------------------------------------- /python/test/test_W1BS_Bench.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # =========================================================== 4 | # File Name: test_W1BS_Bench.py 5 | # Author: Xu Zhang, Columbia University 6 | # Creation Date: 01-25-2019 7 | # Last Modified: Sun Mar 3 22:43:21 2019 8 | # 9 | # Usage: python test_W1BS_Bench.py 10 | # Description: Test baseline matching benchmark 11 | # 12 | # Copyright (C) 2018 Xu Zhang 13 | # All rights reserved. 14 | # 15 | # This file is made available under 16 | # the terms of the BSD license (see the COPYING file). 17 | # =========================================================== 18 | 19 | import sys 20 | import os 21 | 22 | cwd = os.getcwd() 23 | sys.path.insert(0, '{}/python/'.format(cwd)) 24 | 25 | import bench.Utils 26 | import bench.W1BSBench 27 | import features.np_sift 28 | import dset.W1BS_dataset 29 | 30 | 31 | if __name__ == "__main__": 32 | 33 | # Define baseline benchmark 34 | w1bs_bench = bench.W1BSBench.W1BSBench() 35 | 36 | # Define feature 37 | np_sift_py = features.np_sift.np_sift() 38 | 39 | # Define dataset 40 | w1bs = dset.W1BS_dataset.W1BS_Dataset() 41 | 42 | # Do the evaluation 43 | result_py = w1bs_bench.evaluate(w1bs, np_sift_py, use_cache=True, save_result=True) 44 | 45 | # Make the results from different detectors as a list. 46 | result_list = [result_py] 47 | 48 | # Show the result 49 | bench.Utils.print_result(result_list, 'ap') 50 | -------------------------------------------------------------------------------- /matlab/+utls/warpim_H.m: -------------------------------------------------------------------------------- 1 | function [wfrm, refb, refa] = warpim_H(ima, H, varargin) 2 | opts.warp_method = 'imwarp'; 3 | opts.invert = false; 4 | opts = vl_argparse(opts, varargin); 5 | 6 | refa = zb_imref(size(ima)); 7 | switch opts.warp_method 8 | case 'interp' 9 | refb = zb_imref(size(ima)); 10 | [R_n, C_n] = ndgrid(1:size(ima, 1), 1:size(ima, 2)); 11 | P_n = [C_n(:), R_n(:)]'; 12 | if opts.invert 13 | P_i = p2e(H\e2p(P_n)); 14 | else 15 | P_i = p2e(H*e2p(P_n)); 16 | end 17 | 18 | % 'Query' rows and columns 19 | R_i = reshape(P_i(2,:), size(ima, 1), size(ima, 2)); 20 | C_i = reshape(P_i(1,:), size(ima, 1), size(ima, 2)); 21 | 22 | wfrm = cell(1, 1, size(ima, 3)); 23 | for ci = 1:size(ima, 3) 24 | wfrm{ci} = interp2(double(ima(:,:,ci)), C_i, R_i); 25 | end 26 | wfrm = uint8(cell2mat(wfrm)); 27 | case 'imwarp' 28 | tf = projective2d(H'); 29 | if ~opts.invert 30 | tf = tf.invert(); 31 | end 32 | [wfrm, refb] = imwarp(ima, refa, tf); 33 | otherwise 34 | error('Unsupported warp method %s.', opts.warp_method); 35 | end 36 | end 37 | 38 | function [ ra ] = zb_imref( imsz ) 39 | %Get an image reference frame for zero based coordinates. 40 | 41 | ra = imref2d([imsz(1), imsz(2)], [-0.5, imsz(2)-0.5], ... 42 | [-0.5, imsz(1)-0.5]); 43 | end 44 | 45 | function [ pts ] = e2p( pts ) 46 | pts = [pts;ones(1,size(pts,2))]; 47 | end 48 | 49 | function [ pts ] = p2e( pts ) 50 | pts = pts./repmat(pts(size(pts,1),:),size(pts,1),1); 51 | pts = pts(1:size(pts,1)-1,:); 52 | end 53 | -------------------------------------------------------------------------------- /matlab/+legacy/vgg_frames_read.m: -------------------------------------------------------------------------------- 1 | function frames = vgg_frames_read(framesFile) 2 | % VGG_FRAMES_READ Read file exported by some of the older frame detectors. 3 | % FRAMES = VGG_FRAMES_READ(FRAME_FILE_PATH) Reads FRAMES from a file 4 | % defined by FRAME_FILE_PATH 5 | % 6 | % Format is: 7 | % # HEADER 8 | % 1.0 # Descriptor length, ignored 9 | % 128 # Number of points 10 | % # List on N points 11 | % x y a b c # T = [X, Y] - location of interest points 12 | % # M = [a,b;b,c] {x + T: x' M x = 1} affine shape 13 | % 14 | % vl_ubscread cannot be used because some older detectors produce files 15 | % which contain length of the descriptors = 1 which the vl_ubcread function 16 | % is not able to handle. 17 | 18 | % Copyright (C) 2011-16 Karel Lenc 19 | % All rights reserved. 20 | % 21 | % This file is part of the VLFeat library and is made available under 22 | % the terms of the BSD license (see the COPYING file). 23 | 24 | fid = fopen(framesFile, 'r'); 25 | if fid==-1, error('Could not read file: %s\n', framesFile); end 26 | [header, count] = fscanf(fid, '%f', 2); 27 | if count ~= 2 28 | fclose(fid); 29 | error('Invalid frames format.'); 30 | end 31 | numPoints = header(2); 32 | [frames, count] = fscanf(fid,'%f', [5, numPoints]); 33 | fclose(fid); 34 | if count ~= 5 * numPoints, error('Invalid frames format.'); end 35 | % Transform the frame properly 36 | frames(1:2,:) = frames(1:2,:) + 1; 37 | C = frames(3:5, :); 38 | den = C(1,:) .* C(3,:) - C(2,:) .* C(2,:) ; 39 | S = [C(3,:) ; -C(2,:) ; C(1,:)] ./ den([1 1 1], :) ; 40 | frames(3:5,:) = S; 41 | end -------------------------------------------------------------------------------- /matlab/+utls/sysrun.m: -------------------------------------------------------------------------------- 1 | function [ out, info ] = sysrun( cmd, varargin ) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | opts.gpu = []; 5 | [opts, varargin] = vl_argparse(opts, varargin); 6 | opts.unset_ld = isempty(opts.gpu); % Set true if segfaults, has to be false for CUDA 7 | opts.runDir = pwd(); 8 | opts.verbose = false; 9 | opts.env = struct(); 10 | opts = vl_argparse(opts, varargin); 11 | 12 | if ~isempty(opts.gpu) 13 | opts.gpu = arrayfun(@num2str, opts.gpu - 1, 'Uni', false); 14 | opts.gpu = strjoin(opts.gpu, ','); 15 | end 16 | 17 | env.CUDA_DEVICE_ORDER = 'PCI_BUS_ID'; 18 | env.CUDA_VISIBLE_DEVICES = opts.gpu; 19 | env = vl_override(env, opts.env); 20 | envstr = envstring(env); 21 | 22 | addcmd = ''; 23 | if opts.unset_ld, addcmd = '--unset=LD_LIBRARY_PATH '; end 24 | fullcmd = sprintf('env %s %s %s', addcmd, envstr, cmd); 25 | info.fullcmd = fullcmd; 26 | 27 | actpath = pwd; 28 | try 29 | cd(opts.runDir); 30 | if opts.verbose 31 | fprintf('Running:\n%s\n', fullcmd); 32 | stime = tic; 33 | [ret, out] = system(fullcmd, '-echo'); 34 | info.time = toc(stime); 35 | else 36 | tic; 37 | [ret, out] = system(fullcmd); 38 | info.time = toc; 39 | end 40 | catch e 41 | cd(actpath); 42 | throw(e); 43 | end 44 | cd(actpath); 45 | if ret ~= 0 46 | error('Error running %s.\n%s', fullcmd, out); 47 | end 48 | 49 | end 50 | 51 | function str = envstring(env) 52 | flds = fieldnames(env); 53 | str = ''; 54 | for fi = 1:numel(flds) 55 | str = [str flds{fi}, '=', env.(flds{fi}), ' ']; 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /matlab/+utls/ellipse2vggformat.m: -------------------------------------------------------------------------------- 1 | function vggEll = ellipse2vggformat(ell, eigVal, eigVec) 2 | % ELLIPSE2VGGFORMAT Transforms the ellipse into mexComputeEllipseOverlap function 3 | % VGG_ELL = ellipse2vggformat(F, EIG, EIGVEC) Converts ellipse frame F with 4 | % eigen values EIG and eigen vectors EIGVEC of the frame ellipse 5 | % matrix (see `help ellipseEigen`) to KM frame defined as: 6 | % 7 | % VGG_ELL(1:5,.) = F(1:5,.) 8 | % VGG_ELL(6:7,.) = sqrt(EIG(:,.)) % Size of the ellipse axes 9 | % VGG_ELL(8:9,.) Size of the ellipse bounding box (allinged to image 10 | % coordinates) half-axis. 11 | 12 | % Copyright (C) 2011-16 Andrea Vedaldi, Karel Lenc 13 | % All rights reserved. 14 | % 15 | % This file is part of the VLFeat library and is made available under 16 | % the terms of the BSD license (see the COPYING file). 17 | 18 | vggEll = zeros(5+4,size(ell,2)); 19 | 20 | if isempty(ell) 21 | return; 22 | end 23 | 24 | vggEll(1:2,:) = ell(1:2,:); 25 | v1byLambda1 = bsxfun(@rdivide,eigVec(1:2,:),eps+eigVal(1,:)); 26 | v2byLambda2 = bsxfun(@rdivide,eigVec(3:4,:),eps+eigVal(2,:)); 27 | 28 | A1 = sum([v1byLambda1(1,:);v2byLambda2(1,:)].*[eigVec(1,:);eigVec(3,:)],1); 29 | A2 = sum([v1byLambda1(2,:);v2byLambda2(2,:)].*[eigVec(1,:);eigVec(3,:)],1); 30 | A4 = sum([v1byLambda1(2,:);v2byLambda2(2,:)].*[eigVec(2,:);eigVec(4,:)],1); 31 | 32 | vggEll(3,:) = A1; 33 | vggEll(4,:) = A2; 34 | vggEll(5,:) = A4; 35 | 36 | vggEll(6,:) = sqrt(eigVal(2,:)); 37 | vggEll(7,:) = sqrt(eigVal(1,:)); 38 | 39 | % TODO wrong bbox, see repeatability 219 40 | vggEll([8 9],:) = sqrt(ell([3 5],:)); 41 | -------------------------------------------------------------------------------- /matlab/+utls/parallelise.m: -------------------------------------------------------------------------------- 1 | function [ idxs ] = parallelise( varargin ) 2 | % PARALLELISE Return the scalar product of all arguments indexes 3 | % Eventually, if SGE_TASK_ID and SGE_TASK_LAST are set, selects only a 4 | % subset of the tasks. 5 | nel_num = cellfun(@numel, varargin); 6 | nel = cellfun(@(a) 1:numel(a), varargin, 'Uni', false); 7 | idxs = cell(1, numel(varargin)); 8 | [idxs{:}] = ndgrid(nel{end:-1:1}); 9 | assert(numel(idxs{1}) == prod(nel_num)); 10 | idxs = cellfun(@(a) reshape(a, [], 1), idxs, 'Uni', false); 11 | idxs = cell2mat(idxs(end:-1:1)); 12 | 13 | if isempty(getenv('SGE_TASK_FIRST')), setenv('SGE_TASK_FIRST', '1'); end; 14 | if ~isempty(getenv('SGE_TASK_ID')) && ~isempty(getenv('SGE_TASK_LAST')) ... 15 | && ~isempty(getenv('SGE_TASK_FIRST')) 16 | task_last = str2double(getenv('SGE_TASK_LAST')); 17 | task_first = str2double(getenv('SGE_TASK_FIRST')); 18 | % Make sure it's one-indexed 19 | task_id = str2double(getenv('SGE_TASK_ID')) - task_first + 1; 20 | num_tasks = task_last - task_first + 1; 21 | task_sz = ceil(size(idxs, 1) / num_tasks); 22 | tasks_sel = (task_id - 1)*task_sz + 1 : min(size(idxs, 1), task_id*task_sz); 23 | fprintf('SGE JOB: %d:%d:%d [%d tasks %d/worker] : Sel [%d ... %d]\n', ... 24 | task_first, task_id, task_last, ... 25 | size(idxs, 1), task_sz, ... 26 | min(tasks_sel), max(tasks_sel)); 27 | % Shuffle indexes with a fixed seed so that the tasks are evenly distributed 28 | s = RandStream('mt19937ar', 'Seed', 0); 29 | idxs = idxs(randperm(s, size(idxs, 1)), :); 30 | idxs = idxs(tasks_sel, :); 31 | end 32 | 33 | end 34 | 35 | -------------------------------------------------------------------------------- /matlab/+utls/helpbuilder.m: -------------------------------------------------------------------------------- 1 | function helpbuilder(cmds, cmd, varargin) 2 | opts.name = 'vlb'; 3 | opts = vl_argparse(opts, varargin); 4 | fname = opts.name; 5 | if isdeployed(), opts.name = sprintf('run_%s.sh', opts.name); end; 6 | if isempty(cmd) || strcmp(cmd, 'help') 7 | fprintf('Usage: `%s COMMAND ...\n', opts.name); 8 | printhelp(fname); 9 | if usejava('desktop') 10 | fprintf('Valid commands:\n\t'); 11 | cmd_names = fieldnames(cmds); 12 | for ci = 1:(numel(cmd_names)) 13 | fprintf('%s ', ... 14 | opts.name, cmd_names{ci}, cmd_names{ci}); 15 | end 16 | fprintf('\n'); 17 | else 18 | fprintf('Valid commands: %s\n\n', strjoin(fieldnames(cmds), ', ')); 19 | end 20 | else 21 | if isfield(cmds, cmd) 22 | fprintf('Help for %s command `%s`:\n', opts.name, cmd); 23 | if isempty(cmds.(cmd).help) 24 | func = func2str(cmds.(cmd).fun); 25 | printhelp(func); 26 | else 27 | cmds.(cmd).help(cmd); 28 | end 29 | else 30 | error('Invalid command. Run %s help for list of valid commands', opts.name); 31 | end 32 | end 33 | end 34 | 35 | function printhelp(func) 36 | if isdeployed 37 | parsehelp(func); 38 | else 39 | help(func); 40 | end 41 | end 42 | 43 | function parsehelp(fun) 44 | fun_path = fullfile(de_path(), [fun, '.m']); 45 | fun_src = fileread(fun_path); 46 | help_end = strfind(fun_src, '% Copyright') - 1; 47 | fun_src = fun_src(1:help_end); 48 | fun_src = splitlines(fun_src); 49 | fun_src = cellfun(@(a) a(2:end), fun_src(2:end), 'Uni', false); 50 | help_str = strjoin(fun_src, newline); 51 | fprintf(help_str); 52 | end -------------------------------------------------------------------------------- /matlab/+utls/features_load.m: -------------------------------------------------------------------------------- 1 | function features = features_load( path, varargin ) 2 | %FEATURES_Load Load a features structure at the specified path 3 | opts.checkonly = false; 4 | opts.compulsoryFields = {}; 5 | opts = vl_argparse(opts, varargin); 6 | 7 | features = struct(); 8 | files = dir([path, '.*.*']); 9 | if isempty(files), features = []; return; end 10 | % Check whether all required fields are present 11 | if ~isempty(opts.compulsoryFields) 12 | [~, imname] = fileparts(path); 13 | compulsoryFnames = cellfun(@(cf) [imname, '.', cf], ... 14 | opts.compulsoryFields, 'Uni', false); 15 | if any(~ismember(compulsoryFnames, {files.name})) 16 | features = []; return; 17 | end 18 | end 19 | 20 | for fi = 1:numel(files) 21 | [~, fname, ext] = fileparts(files(fi).name); 22 | fname = strsplit(fname, '.'); 23 | assert(numel(fname) == 2, 'Invalid features file name %s', files(fi).name); 24 | field = fname{2}; 25 | fpath = [path, '.', field, ext]; 26 | if opts.checkonly 27 | features.(field) = nan; 28 | else 29 | fp = dir(fpath); 30 | if fp.bytes == 0 31 | features.(field) = []; 32 | continue; 33 | end 34 | switch ext 35 | case '.csv' 36 | features.(field) = dlmread(fpath, ';')'; 37 | case '.txt' 38 | fd = fopen(fpath, 'r'); 39 | data = textscan(fd, '%s'); 40 | features.(field) = data{1}{1}; 41 | fclose(fd); 42 | case '.mat' 43 | data = load(fpath); 44 | features.(field) = data.data; 45 | case '.oxf' % Oxford frames format (1.\nNFEATS\nx y a b c\n) 46 | features.(field) = legacy.vgg_frames_read(fpath); 47 | end 48 | end 49 | end 50 | 51 | end 52 | 53 | -------------------------------------------------------------------------------- /python/verifiers/lmeds.py: -------------------------------------------------------------------------------- 1 | 2 | import cv2 3 | 4 | from verifiers.VerificationTemplate import VerificationTemplate 5 | 6 | class LMEDS(VerificationTemplate): 7 | 8 | def __init__(self): 9 | super( 10 | LMEDS, 11 | self).__init__( 12 | name='LMEDS', 13 | estimates_essential=True, 14 | estimates_fundamental=True) 15 | 16 | def estimate_essential_matrix(self, pts1, pts2): 17 | """ 18 | Estimate the Essential matrix between 2 images from a set of putative keypoint matches 19 | (kpt1s[i], kpts2[i]) are a corresponding matche from image 1 and 2 in normalized coordinates 20 | 21 | :param kpts1: Keypoints for image 1 22 | :type kpts1: np.array (Nx2) 23 | :param kpts2: Keypoints from image 2 24 | :type kpts2: np.array (Nx2) 25 | :returns: E (the 3x3 Essential matrix) 26 | :rtype: np.array(3x3) 27 | """ 28 | E, _ = cv2.findEssentialMat(pts1, pts2, method=cv2.LMEDS) 29 | return E 30 | 31 | def estimate_fundamental_matrix(self, pts1, pts2): 32 | """ 33 | Estimate the Fundamental matrix between 2 images from a set of putative keypoint matches. 34 | (kpt1s[i], kpts2[i]) are a corresponding matche from image 1 and 2 in camera coordinates 35 | 36 | :param kpts1: Keypoints for image 1 37 | :type kpts1: np.array (Nx2) 38 | :param kpts2: Keypoints from image 2 39 | :type kpts2: np.array (Nx2) 40 | :returns: E (the 3x3 Essential matrix) 41 | :rtype: np.array(3x3) 42 | """ 43 | F, _ = cv2.findFundamentalMat(pts1, pts2, method=cv2.LMEDS) 44 | return F 45 | -------------------------------------------------------------------------------- /python/verifiers/ransac.py: -------------------------------------------------------------------------------- 1 | 2 | import cv2 3 | 4 | from verifiers.VerificationTemplate import VerificationTemplate 5 | 6 | class RANSAC(VerificationTemplate): 7 | 8 | def __init__(self): 9 | super( 10 | RANSAC, 11 | self).__init__( 12 | name='RANSAC', 13 | estimates_essential=True, 14 | estimates_fundamental=True) 15 | 16 | def estimate_essential_matrix(self, kpts1, kpts2): 17 | """ 18 | Estimate the Essential matrix between 2 images from a set of putative keypoint matches 19 | (kpt1s[i], kpts2[i]) are a corresponding matche from image 1 and 2 in normalized coordinates 20 | 21 | :param kpts1: Keypoints for image 1 22 | :type kpts1: np.array (Nx2) 23 | :param kpts2: Keypoints from image 2 24 | :type kpts2: np.array (Nx2) 25 | :returns: E (the 3x3 Essential matrix) 26 | :rtype: np.array(3x3) 27 | """ 28 | E, _ = cv2.findEssentialMat(kpts1, kpts2, method=cv2.RANSAC) 29 | return E 30 | 31 | def estimate_fundamental_matrix(self, kpts1, kpts2): 32 | """ 33 | Estimate the Fundamental matrix between 2 images from a set of putative keypoint matches 34 | (pt1s[i], pts2[i]) are a corresponding matche from image 1 and 2 in pixel coordinates 35 | 36 | :param kpts1: Keypoints for image 1 37 | :type kpts1: np.array (Nx2) 38 | :param kpts2: Keypoints from image 2 39 | :type kpts2: np.array (Nx2) 40 | :returns: F (the 3x3 Essential matrix) 41 | :rtype: np.array(3x3) 42 | """ 43 | F, _ = cv2.findFundamentalMat(kpts1, kpts2, method=cv2.RANSAC) 44 | return F 45 | -------------------------------------------------------------------------------- /matlab/xtest/suite/test_detrep.m: -------------------------------------------------------------------------------- 1 | classdef test_detrep < matlab.unittest.TestCase 2 | 3 | properties (TestParameter) 4 | detector = {@features.det.vlsift}; 5 | dataset = {dset.vggh}; 6 | taskid = {1, 6, 11}; 7 | end 8 | 9 | methods (Test) 10 | function kmequal(test, detector, dataset, taskid) 11 | task = dataset.tasks(taskid); 12 | ima_p = dataset.images(task.ima_id).path; 13 | fa = detector(single(utls.imread_grayscale(ima_p))); 14 | imb_p = dataset.images(task.imb_id).path; 15 | fb = detector(single(utls.imread_grayscale(imb_p))); 16 | fa.descs = []; fb.descs = []; 17 | 18 | matchFrames = @(fa, fb) geom.ellipse_overlap_H(task, fa, fb, ... 19 | 'maxOverlapError', 0.5); 20 | 21 | res = bench.detrep(matchFrames, fa, fb); 22 | [rep_vgg, nm_vgg] = legacy.vgg_frames_benchmark(task, ... 23 | ima_p, fa, imb_p, fb, 'maxOverlapError', 0.5); 24 | test.verifyEqual(res.repeatability, rep_vgg, 'AbsTol', 1e-3); 25 | test.verifyEqual(res.numCorresp, nm_vgg, 'AbsTol', 1); 26 | end 27 | 28 | function emptyoutput(test) 29 | imdb = dset.vggh(); 30 | task = imdb.tasks(1); 31 | fa = features.det.random(rand(task.ima_size)); 32 | fb = features.det.vlsift(rand(task.imb_size)); 33 | matchFrames = @(fa, fb) geom.ellipse_overlap_H(task, fa, fb, ... 34 | 'maxOverlapError', 0.5); 35 | [res, info] = bench.detrep(matchFrames, fa, fb); 36 | fa.frames = []; fa.descs = []; fb.frames = []; fb.descs = []; 37 | [res_e, info_e] = bench.detrep(matchFrames, fa, fb); 38 | test.verifyEqual(fieldnames(res), fieldnames(res_e)); 39 | test.verifyEqual(fieldnames(info), fieldnames(info_e)); 40 | end 41 | end 42 | 43 | end 44 | -------------------------------------------------------------------------------- /matlab/+legacy/vgg_frames_read_ext.m: -------------------------------------------------------------------------------- 1 | function [out] = vgg_frames_read_ext(framesFile) 2 | % VGG_FRAMES_READ Read file exported by some of the older frame detectors. 3 | % FRAMES = VGG_FRAMES_READ_EXT(FRAME_FILE_PATH) Reads FRAMES from a file 4 | % defined by FRAME_FILE_PATH, probably ad-hoc extended format of KM code. 5 | % 6 | % Format is: 7 | % # HEADER 8 | % 1.0 # Descriptor length, ignored 9 | % 128 # Number of points 10 | % # List on N points, each point 12 values... 11 | % x y R S ? T ? ? a11 a12 a21 a22 # P = [X, Y] - location of interest points 12 | % # M = [a,b;b,c] {x + T: x' M x = 1} affine shape 13 | % 14 | % vl_ubscread cannot be used because some older detectors produce files 15 | % which contain length of the descriptors = 1 which the vl_ubcread function 16 | % is not able to handle. 17 | 18 | % Copyright (C) 2011-16 Karel Lenc 19 | % All rights reserved. 20 | % 21 | % This file is part of the VLFeat library and is made available under 22 | % the terms of the BSD license (see the COPYING file). 23 | 24 | fid = fopen(framesFile, 'r'); 25 | if fid==-1, error('Could not read file: %s\n', framesFile); end 26 | [header, count] = fscanf(fid, '%f', 2); 27 | if count ~= 2 28 | fclose(fid); 29 | error('Invalid frames format.'); 30 | end 31 | numPoints = header(2); 32 | [data, count] = fscanf(fid,'%f', [12, numPoints]); 33 | fclose(fid); 34 | if count ~= 12 * numPoints, error('Invalid frames format.'); end 35 | % Transform the frame properly 36 | % X Y CORNERNESS SCALE/3 ANGLE TYPE LAP EXTR M11 M12 M21 M22 37 | frames = zeros(6, numPoints); 38 | frames(1:2,:) = data(1:2,:) + 1; 39 | frames(3:6,:) = bsxfun(@times, data(9:12, :), data(4, :)) .* 3; 40 | out.frames = utls.frame2ellipse(frames); 41 | 42 | out.detresponses = data(3, :); 43 | out.type = data(6, :); 44 | end -------------------------------------------------------------------------------- /matlab/xtest/suite/test_detmatch.m: -------------------------------------------------------------------------------- 1 | classdef test_detmatch < matlab.unittest.TestCase 2 | 3 | properties (TestParameter) 4 | detector = {@features.det.vlsift}; 5 | dataset = {dset.vggh}; 6 | taskid = {1, 6, 11}; 7 | end 8 | 9 | methods (Test) 10 | function kmequal(test, detector, dataset, taskid) 11 | task = dataset.tasks(taskid); 12 | ima_p = dataset.images(task.ima_id).path; 13 | fa = detector(single(utls.imread_grayscale(ima_p))); 14 | imb_p = dataset.images(task.imb_id).path; 15 | fb = detector(single(utls.imread_grayscale(imb_p))); 16 | 17 | matchFrames = @(fa, fb, varargin) geom.ellipse_overlap_H(task, fa, fb, ... 18 | 'maxOverlapError', 0.4, varargin{:}); 19 | 20 | res = bench.detmatch(matchFrames, fa, fb); 21 | [~, ~, ms_vgg, nm_vgg] = ... 22 | legacy.vgg_frames_benchmark( task, ima_p, fa, ... 23 | imb_p, fb, 'maxOverlapError', 0.4); 24 | test.verifyEqual(res.matchingScore, ms_vgg, 'RelTol', 0.01); 25 | test.verifyEqual(res.numMatches, nm_vgg, 'RelTol', 0.01); 26 | end 27 | 28 | function emptyoutput(test) 29 | imdb = dset.vggh(); 30 | task = imdb.tasks(1); 31 | fa = features.det.vlsift(rand(task.ima_size)); 32 | fb = features.det.vlsift(rand(task.imb_size)); 33 | matchFrames = @(fa, fb, varargin) geom.ellipse_overlap_H(task, fa, fb, ... 34 | 'maxOverlapError', 0.4, varargin{:}); 35 | [res, info] = bench.detmatch(matchFrames, fa, fb); 36 | fa.frames = []; fa.descs = []; fb.frames = []; fb.descs = []; 37 | [res_e, info_e] = bench.detmatch(matchFrames, fa, fb); 38 | test.verifyEqual(fieldnames(res), fieldnames(res_e)); 39 | test.verifyEqual(fieldnames(info), fieldnames(info_e)); 40 | end 41 | end 42 | 43 | end 44 | -------------------------------------------------------------------------------- /python/dset/hpatches_dataset.py: -------------------------------------------------------------------------------- 1 | from dset.dataset import SequenceDataset 2 | import urllib 3 | import tarfile 4 | import os 5 | import sys 6 | 7 | if sys.version_info[0] >= 3: 8 | from urllib.request import urlretrieve 9 | else: 10 | from urllib import urlretrieve 11 | 12 | 13 | class HPatches_Dataset(SequenceDataset): 14 | 15 | def __init__(self,root_dir = './datasets/', download_flag = False): 16 | super(HPatches_Dataset,self).__init__(name = 'HPatches', root_dir = root_dir, download_flag = download_flag) 17 | 18 | def download(self): 19 | try: 20 | os.stat(self.root_dir) 21 | except: 22 | os.mkdir(self.root_dir) 23 | 24 | try: 25 | os.stat('{}{}'.format(self.root_dir,self.name)) 26 | except: 27 | os.mkdir('{}{}'.format(self.root_dir,self.name)) 28 | 29 | download_url = "{}".format(self.url) 30 | download_filename = "{}/{}.tar.gz".format(self.root_dir, self.name) 31 | try: 32 | print("Downloading HPatches from {}".format(download_url)) 33 | urlretrieve(download_url, download_filename) 34 | tar = tarfile.open(download_filename) 35 | dd = tar.getnames()[0] 36 | tar.extractall('{}'.format(self.root_dir)) 37 | tar.close() 38 | os.remove(download_filename) 39 | os.rmdir("{}{}".format(self.root_dir, self.name)) 40 | os.rename("{}{}".format(self.root_dir, dd), "{}{}".format(self.root_dir, self.name)) 41 | except Exception as e: 42 | print(str(e)) 43 | print('Cannot download from {}.'.format(download_url)) 44 | 45 | def read_image_data(self): 46 | self.read_image_data_vggh() 47 | 48 | def read_link_data(self): 49 | self.read_link_data_vggh() 50 | -------------------------------------------------------------------------------- /matlab/+features/factory.m: -------------------------------------------------------------------------------- 1 | function [ res, varargin ] = factory( type, name, varargin ) 2 | %FACTORY Construct a features structure 3 | 4 | % feature name preference: 5 | % - 'detName' argumnt 6 | % - function's second output 7 | % - function name 8 | assert(ismember(type, {'det', 'desc', 'detdesc'})); 9 | opts.([type, 'Name']) = ''; 10 | opts.([type, 'Args']) = {}; 11 | opts.rootpackage = 'features'; 12 | [opts, varargin] = vl_argparse(opts, varargin); 13 | funargs = opts.([type, 'Args']); 14 | 15 | if isstruct(name) 16 | res = name; 17 | res.type = type; 18 | assert(isfield(res, 'name') && isfield(res, 'fun'), ... 19 | 'Invalid algorithm structure, must contain `name` and `fun`.'); 20 | return; 21 | end 22 | switch class(name) 23 | case 'char' 24 | fname = [opts.rootpackage '.', type, '.' strtrim(name)]; 25 | fun = str2func(fname); 26 | case 'function_handle' 27 | fun = name; 28 | otherwise 29 | error('Invalid detdesc'); 30 | end 31 | try 32 | nout = nargout(fun); 33 | catch 34 | error('Invalid %s: %s - Function not found', type, fname); 35 | end 36 | assert(nout >= 1, 'Feature wrapper does not return meta information.'); 37 | func_nargin = nargin(fun); 38 | if func_nargin < 0, func_nargin = abs(func_nargin) - 1; end 39 | switch func_nargin 40 | case 1 41 | f = fun([], funargs{:}); 42 | res.fun = @(a) fun(a, funargs{:}); 43 | case 2 44 | f = fun([], [], funargs{:}); 45 | res.fun = @(a, b) fun(a, b, funargs{:}); 46 | end 47 | assert(isfield(f, [type, 'Name']), ... 48 | 'Feature wrapper does not return meta information.'); 49 | res.name = f.([type, 'Name']); 50 | if ~isempty(opts.([type, 'Name'])) 51 | res.name = opts.([type, 'Name']); 52 | end 53 | if isfield(f, 'describes'), res.describes = f.describes; end; 54 | res.args = opts.([type, 'Args']); 55 | res.type = type; 56 | 57 | end 58 | -------------------------------------------------------------------------------- /matlab/xtest/vlb_test.m: -------------------------------------------------------------------------------- 1 | function vlb_test(varargin) 2 | %VLB_TEST Run MatConvNet test suite 3 | % VLB_TEST('option', value, ...) takes the following options: 4 | % 5 | % `command`:: 'nn' 6 | % Run only tests which name starts with the specified substring. 7 | % E.g. `vl_testnn('command', 'nnloss') would run only the nnloss tests. 8 | % 9 | % `break`:: false 10 | % Stop tests in case of error. 11 | % 12 | % `tapFile`:: '' 13 | % Output the test results to a file. If a specified file does 14 | % exist it is overwritten. 15 | % 16 | % This function uses the Matlab unit testing framework which was 17 | % introduced in Matlab R2013a (v8.1). 18 | 19 | % Copyright (C) 2015-16 Andrea Vedaldi, Karel Lenc. 20 | % All rights reserved. 21 | % 22 | % This file is part of the VLFeat library and is made available under 23 | % the terms of the BSD license (see the COPYING file). 24 | vlb_setup(); 25 | 26 | opts.command = 'test' ; 27 | opts.break = false ; 28 | opts.tapFile = ''; 29 | opts = vl_argparse(opts, varargin) ; 30 | 31 | import matlab.unittest.constraints.* ; 32 | import matlab.unittest.selectors.* ; 33 | import matlab.unittest.plugins.TAPPlugin; 34 | import matlab.unittest.plugins.ToFile; 35 | 36 | % Choose which tests to run 37 | sel = HasName(StartsWithSubstring(opts.command)) ; 38 | 39 | % Run tests 40 | root = fileparts(mfilename('fullpath')) ; 41 | suite = matlab.unittest.TestSuite.fromFolder(fullfile(root, 'suite'), sel) ; 42 | runner = matlab.unittest.TestRunner.withTextOutput('Verbosity', 3); 43 | if opts.break 44 | runner.addPlugin(matlab.unittest.plugins.StopOnFailuresPlugin) ; 45 | end 46 | if ~isempty(opts.tapFile) 47 | if exist(opts.tapFile, 'file') 48 | delete(opts.tapFile); 49 | end 50 | runner.addPlugin(TAPPlugin.producingOriginalFormat(ToFile(opts.tapFile))); 51 | end 52 | result = runner.run(suite); 53 | display(result) 54 | -------------------------------------------------------------------------------- /matlab/+features/+det/matdet.m: -------------------------------------------------------------------------------- 1 | function [ res ] = matdet( img, varargin ) 2 | %MATDET Summary of this function goes here 3 | % Detailed explanation goes here 4 | opts.detector = 'fast'; 5 | opts.defScale = 3; 6 | [opts, varargin] = vl_argparse(opts, varargin); 7 | 8 | dets = struct(); 9 | dets.fast = @detectFASTFeatures; 10 | dets.surf = @detectSURFFeatures; 11 | dets.brisk = @detectBRISKFeatures; 12 | dets.mser = @detectMSERFeatures; 13 | dets.harris = @detectHarrisFeatures; 14 | 15 | if ~isfield(dets, opts.detector) 16 | error('Invalid detector. Valid options are: %s', strjoin(fieldnames(dets))); 17 | end 18 | fun = dets.(opts.detector); 19 | res.detName = sprintf('matdet-%s', opts.detector); 20 | if isempty(img), res.frames = zeros(6, 0); return; end 21 | if size(img, 3) > 1, img = rgb2gray(img); end 22 | 23 | stime = tic; 24 | fp = fun(img, varargin{:}); 25 | res.dettime = toc(stime); 26 | 27 | res.frames = double(fp.Location'); 28 | if isprop(fp, 'Scale') 29 | res.frames = [res.frames; fp.Scale']; 30 | else 31 | res.frames = [res.frames; opts.defScale*ones(1, size(res.frames, 2))]; 32 | end 33 | if isprop(fp, 'Orientation'), res.frames = [res.frames; fp.Orientation']; end 34 | if isprop(fp, 'Metric') 35 | res.detresponses = fp.Metric'; 36 | assert(numel(res.detresponses) == size(res.frames, 2)); 37 | end 38 | if isprop(fp, 'Axes') % MSER 39 | res.frames = [double(fp.Location'); zeros(4, numel(fp.Orientation))]; 40 | for fi = 1:numel(fp.Orientation) 41 | aff = [fp.Axes(fi, 1)./2, 0; 0, fp.Axes(fi, 2)./2]; 42 | ang = fp.Orientation(fi); 43 | aff = [cos(ang), sin(ang); -sin(ang), cos(ang)] * aff; 44 | res.frames(3:6, fi) = utls.afftf2frame(aff); 45 | end 46 | 47 | if 0 % Debug code 48 | clf; 49 | imshow(img); hold on; 50 | plot(fp); 51 | vl_plotframe(res.frames, 'LineWidth', 1, 'Color', 'k'); 52 | end 53 | end 54 | 55 | end 56 | -------------------------------------------------------------------------------- /python/verifiers/VerificationTemplate.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | class VerificationTemplate(): 5 | """Basic Template for Verification Algorithm 6 | 7 | Attributes 8 | ---------- 9 | 10 | name: str 11 | Name of the method 12 | estimates_essential: boolean, optional 13 | Does the algorithm estimate the essential matrix 14 | estimates_fundamental: boolean, optional 15 | Does the algorithm estimate the fundamental matrix 16 | 17 | """ 18 | 19 | def __init__(self, name, estimates_essential=False, estimates_fundamental=False): 20 | 21 | self.name = name 22 | self.estimates_essential = estimates_essential 23 | self.estimates_fundamental = estimates_fundamental 24 | 25 | def estimate_essential_matrix(self, kpts1, kpts2): 26 | """ 27 | Estimate the Essential matrix between 2 images from a set of putative keypoint matches 28 | (kpt1s[i], kpts2[i]) are a corresponding matche from image 1 and 2 in normalized coordinates 29 | 30 | :param kpts1: Keypoints for image 1 31 | :type kpts1: np.array (Nx2) 32 | :param kpts2: Keypoints from image 2 33 | :type kpts2: np.array (Nx2) 34 | :returns: E (the 3x3 Essential matrix) 35 | :rtype: np.array(3x3) 36 | """ 37 | pass 38 | 39 | def estimate_fundamental_matrix(self, kpts1, kpts2): 40 | """ 41 | Estimate the Fundamental matrix between 2 images from a set of putative keypoint matches. 42 | (kpt1s[i], kpts2[i]) are a corresponding matche from image 1 and 2 in camera coordinates 43 | 44 | :param kpts1: Keypoints for image 1 45 | :type kpts1: np.array (Nx2) 46 | :param kpts2: Keypoints from image 2 47 | :type kpts2: np.array (Nx2) 48 | :returns: E (the 3x3 Essential matrix) 49 | :rtype: np.array(3x3) 50 | """ 51 | pass 52 | -------------------------------------------------------------------------------- /matlab/+features/+det/tilde.m: -------------------------------------------------------------------------------- 1 | function res = tilde(img, varargin) 2 | 3 | opts.url = 'https://github.com/cvlab-epfl/TILDE/archive/master.zip'; 4 | opts.rootDir = fullfile(vlb_path('vendor'), 'tilde'); 5 | [opts, varargin] = vl_argparse(opts, varargin); 6 | opts.srcDir = fullfile(opts.rootDir, 'TILDE-master', 'matlab', 'src'); 7 | opts.filtersDir = fullfile(opts.rootDir, 'TILDE-master', 'matlab', 'filters'); 8 | [opts, varargin] = vl_argparse(opts, varargin); 9 | opts.fullPathFilter = fullfile(opts.filtersDir, 'BestFilters_2percents/Original/MexicoMed.mat'); 10 | opts.fixed_scale = 10; 11 | opts = vl_argparse(opts, varargin); 12 | 13 | global sRoot; 14 | global bSetupPathFin; 15 | res.detName = 'tilde'; res.args = opts; res.frames = zeros(5, 0); 16 | if isempty(img), return; end 17 | 18 | imsz = [size(img, 1), size(img, 2)]; 19 | if any(imsz < 105) 20 | padding = ceil(max(105 - imsz, 0) ./ 2); 21 | img = padarray(img, [padding, 0], 'replicate'); 22 | end 23 | 24 | utls.provision(opts.url, opts.rootDir, 'forceExt', '.zip'); 25 | 26 | if ~exist('ApplyLearnedELLFilter', 'file') 27 | addpath(fullfile(opts.srcDir, 'Utils')); 28 | addpath(fullfile(opts.srcDir, 'Utils/tools_nonmax/')); 29 | addpath(fullfile(opts.srcDir, 'Utils/tools_evaluate/')); 30 | addpath(fullfile(opts.srcDir, 'Utils/tools_filtering/')); 31 | addpath(fullfile(opts.srcDir, '../external/dollarToolbox/')); 32 | 33 | sRoot = fileparts(opts.srcDir); 34 | setup_path; 35 | end 36 | 37 | stime = tic; 38 | [ binary_res, score ] = ApplyLearnedELLFilter(img, -inf, opts.fullPathFilter, false ); 39 | idx = find(binary_res); 40 | [I, J] = ind2sub(size(binary_res), idx); 41 | features = [J I zeros(size(I,1),3) repmat(opts.fixed_scale, size(I,1), 1)]'; 42 | features = mergeScoreImg2Keypoints(features, score); 43 | res.dettime = toc(stime); 44 | 45 | res.detresponses = features(5, :); 46 | res.frames = [features(1:2, :); features(end, :)]; 47 | end -------------------------------------------------------------------------------- /matlab/xtest/suite/test_descs.m: -------------------------------------------------------------------------------- 1 | classdef test_descs < matlab.unittest.TestCase 2 | properties (TestParameter) 3 | descriptor = utls.listfiles(fullfile(vlb_path(), 'matlab', '+features', '+desc', '*.m'), 'keepext', false, 'fullpath', false); 4 | image = {rand(0, 0, 1), rand(50, 50, 1), rand(50, 50, 3), rand(50, 50, 3, 'single'), vl_impattern('roofs1'), im2uint8(vl_impattern('roofs2'))}; 5 | frameType = {'disc', 'oriented_disc'}; 6 | end 7 | 8 | methods (Test) 9 | function testdesc(test, descriptor, image, frameType) 10 | desc_info = features.factory('desc', descriptor); 11 | desc_fun = desc_info.fun; 12 | test.verifyTrue(isfield(desc_info, 'name') == 1); 13 | test.verifyTrue(isfield(desc_info, 'describes') == 1); 14 | test.verifyTrue(ismember(desc_info.describes, {'patches', 'frames'})); 15 | imsize = size(image); 16 | infeats = features.det.random(image, 'frameType', frameType); 17 | switch desc_info.describes 18 | case 'frames' 19 | feats = desc_fun(image, infeats); 20 | % Test if the returned frames are valid 21 | test.verifyTrue(isfield(feats, 'frames') == 1); 22 | test.verifyTrue(isfield(feats, 'descs') == 1); 23 | test.verifyEqual(size(feats.descs, 2), size(feats.frames, 2)); 24 | frames = feats.frames; 25 | if ~isempty(frames) 26 | test.verifyGreaterThan(frames(1:2,:), 0); 27 | % Frames in IMAGE coordinates, not Matlab matrix coords 28 | test.verifyLessThan(frames(2,:), imsize(1)+1); 29 | test.verifyLessThan(frames(1,:), imsize(2)+1); 30 | end 31 | case 'patches' 32 | patches = utls.patches_extract_covdet(image, infeats.frames); 33 | feats = desc_fun(patches); 34 | end 35 | test.verifyTrue(isfield(feats, 'descs') == 1); 36 | test.verifyGreaterThanOrEqual(size(feats.descs, 1), 0); 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /python/features/vlsift_matlab.py: -------------------------------------------------------------------------------- 1 | """ 2 | vlsift matlab version python wrapper 3 | Author: Xu Zhang 4 | """ 5 | 6 | import numpy as np 7 | import cv2 8 | import feature_utils 9 | import matlab 10 | import matlab.engine 11 | from DetectorDescriptorTemplate import DetectorAndDescriptor 12 | 13 | eng = matlab.engine.start_matlab() 14 | eng.addpath(r'./matlab/', nargout=0) 15 | 16 | 17 | class vlsift_matlab(DetectorAndDescriptor): 18 | def __init__(self, peak_thresh=3.0, Magnif=5.0): 19 | super( 20 | vlsift_matlab, 21 | self).__init__( 22 | name='vlsift_matlab', 23 | is_detector=True, 24 | is_descriptor=True, 25 | is_both=True) 26 | self.peak_thresh = peak_thresh 27 | self.Magnif = Magnif 28 | 29 | def detect_feature(self, image): 30 | image = feature_utils.all_to_gray(image) 31 | image = image / 255.0 32 | feature, descriptor = eng.vl_sift(matlab.single(image.tolist( 33 | )), 'Magnif', self.Magnif, nargout=2) # , peak_thresh=self.peak_thresh 34 | feature = np.transpose(np.array(feature)) 35 | return feature 36 | 37 | def extract_descriptor(self, image, feature): 38 | image = feature_utils.all_to_gray(image) 39 | image = image / 255.0 40 | feature, descriptor = eng.vl_sift(matlab.single(image.tolist( 41 | )), 'Magnif', self.Magnif, nargout=2) # , peak_thresh=self.peak_thresh 42 | descriptor = np.transpose(np.array(descriptor)) 43 | return descriptor 44 | 45 | def extract_all(self, image): 46 | image = feature_utils.all_to_gray(image) 47 | image = image / 255.0 48 | feature, descriptor = eng.vl_sift(matlab.single(image.tolist( 49 | )), 'Magnif', self.Magnif, nargout=2) # peak_thresh=self.peak_thresh, 50 | feature = np.transpose(np.array(feature)) 51 | descriptor = np.transpose(np.array(descriptor)) 52 | # pdb.set_trace() 53 | return feature, descriptor 54 | -------------------------------------------------------------------------------- /python/bench/vlb_greedy_matching.pyx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #-*- coding: utf-8 -*- 3 | #=========================================================== 4 | # File Name: vlb_greedy_matching.py 5 | # Author: Xu Zhang, Columbia University 6 | # Creation Date: 01-26-2019 7 | # Last Modified: Sat Jan 26 22:40:12 2019 8 | # 9 | # Description: A cython implementation of vlb_greedy_matching 10 | # 11 | # Copyright (C) 2018 Xu Zhang 12 | # All rights reserved. 13 | # 14 | # This file is made available under 15 | # the terms of the BSD license (see the COPYING file). 16 | #=========================================================== 17 | 18 | import numpy as np 19 | cimport numpy as np 20 | 21 | def vlb_greedy_matching(int numNodesA, int numNodesB, np.ndarray[np.int_t, ndim=2] edge_array): 22 | cdef np.ndarray[np.int_t, ndim=2] matches = np.zeros((numNodesA,2), dtype = np.int)-1 23 | cdef np.ndarray[np.int_t, ndim=2] second_closest = np.zeros((numNodesA,2), dtype = np.int)-1 24 | 25 | cdef np.ndarray[np.int_t, ndim=1] nodeAAvail = np.ones((numNodesA,), dtype = np.int) 26 | cdef np.ndarray[np.int_t, ndim=1] nodeBAvail = np.ones((numNodesB,), dtype = np.int) 27 | 28 | cdef int matchedNodes 29 | cdef int maxNumMatches 30 | cdef int i, aIdx, bIdx 31 | maxNumMatches = numNodesA if numNodesA < numNodesB else numNodesB 32 | matchedNodes = 0 33 | 34 | for i in range(edge_array.shape[0]): 35 | aIdx = edge_array[i,0] 36 | bIdx = edge_array[i,1] 37 | 38 | if nodeAAvail[aIdx] and nodeBAvail[bIdx]: 39 | matches[aIdx,0] = bIdx 40 | matches[aIdx,1] = i 41 | nodeAAvail[aIdx] = 0 42 | nodeBAvail[bIdx] = 0 43 | matchedNodes += 1 44 | 45 | if not nodeAAvail[aIdx] and second_closest[aIdx,0]==-1: 46 | second_closest[aIdx,0] = bIdx 47 | second_closest[aIdx,1] = i 48 | 49 | if matchedNodes>=maxNumMatches: 50 | break 51 | 52 | return matches, second_closest 53 | 54 | -------------------------------------------------------------------------------- /matlab/+utls/provision.m: -------------------------------------------------------------------------------- 1 | function downloaded = provision( url, tgt_dir, varargin ) 2 | p = inputParser; 3 | addParameter(p, 'doneName', '.download.done', @isstr); 4 | addParameter(p, 'override', false, @islogical); 5 | addParameter(p, 'forceExt', '', @isstr); 6 | parse(p, varargin{:}); opts = p.Results; 7 | 8 | if exist(url, 'file'), url = fileread(url); end; 9 | url = strtrim(url); 10 | downloaded = false; 11 | done_file = fullfile(tgt_dir, opts.doneName); 12 | if ~exist(tgt_dir, 'dir'), mkdir(tgt_dir); end 13 | if exist(done_file, 'file') && ~opts.override, return; end; 14 | unpack(url, tgt_dir, opts); 15 | downloaded = true; 16 | create_done(done_file); 17 | end 18 | 19 | function create_done(done_file) 20 | f = fopen(done_file, 'w'); fclose(f); 21 | fprintf('To reprovision, delete %s.\n', done_file); 22 | end 23 | 24 | function unpack(url, tgt_dir, opts) 25 | [~,filename,ext] = fileparts(url); 26 | if opts.forceExt, ext = opts.forceExt; end 27 | tgt_file = fullfile(tgt_dir, [filename, ext]); 28 | fprintf(isdeployed+1, ... 29 | 'Downloading %s -> %s, this may take a while...\n',... 30 | url, tgt_file); 31 | 32 | download(url, tgt_file); 33 | 34 | fprintf(isdeployed+1, ... 35 | 'Unpacking %s -> %s, this may take a while...\n',... 36 | tgt_file, tgt_dir); 37 | switch ext 38 | case {'.tar', '.gz'} 39 | untar(url, tgt_dir); 40 | case '.zip' 41 | unzip(url, tgt_dir); 42 | otherwise 43 | error('Unknown archive %s', ext); 44 | end 45 | end 46 | 47 | 48 | function outfile = download(url, target_file) 49 | wgetCommand = 'wget %s -O %s'; % Command for downloading archives 50 | 51 | [distDir, ~, ~] = fileparts(target_file); 52 | vl_xmkdir(distDir); 53 | 54 | % test if wget works 55 | [status, ~] = system('wget --help'); 56 | if status ~= 0 57 | warning('WGET not found, using MATLAB.'); 58 | outfile = websave(target_file, url); 59 | return; 60 | end 61 | 62 | wgetC = sprintf(wgetCommand, url, target_file); 63 | 64 | [status, msg] = system(wgetC,'-echo'); 65 | if status ~= 0 66 | error('Error downloading: %s',msg); 67 | end 68 | end -------------------------------------------------------------------------------- /matlab/+features/+utls/surf.m: -------------------------------------------------------------------------------- 1 | function [ res ] = surf( img, feats, varargin ) 2 | %UNTITLED Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | 6 | % Authors: Karel Lenc 7 | 8 | % AUTORIGHTS 9 | opts.rootDir = fullfile(vlb_path('vendor'), 'surf'); 10 | opts.binPath = fullfile(opts.rootDir,'SURF-V1.0.9','surf.ln'); 11 | opts.url = 'http://www.vision.ee.ethz.ch/~surf/SURF-V1.0.9.tar.gz'; 12 | [opts, varargin] = vl_argparse(opts, varargin); 13 | res.args = opts; 14 | 15 | utls.provision(opts.url, opts.rootDir); 16 | 17 | surfopts = struct(... 18 | 'thres', 1000,... % blob response threshold 19 | 'ms', 3,... % custom lobe size 20 | 'ss', 2,... % initial sampling step 21 | 'oc', 4,... % number of octaves 22 | 'u', [],... % U-SURF (not rotation invariant) 23 | 'e',[],... % extended descriptor (SURF-128) 24 | 'in', 4); % descriptor size 25 | surfopts = vl_argparse(surfopts, varargin); 26 | 27 | 28 | tmpName = tempname; 29 | imagePath = [tmpName '.pgm']; imwrite(img, imagePath); 30 | outFeaturesFile = [tmpName '.surf']; 31 | args = buildArgs(surfopts, imagePath, outFeaturesFile); 32 | if ~isempty(feats) 33 | framesPath = [tmpName '.frames']; 34 | legacy.vgg_features_write(framesPath, feats.frames, []); 35 | args = [args ' -p1 ', framesPath]; 36 | end 37 | cmd = [opts.binPath ' ' args]; 38 | [~, info] = utls.sysrun(cmd); 39 | [res.frames, res.descs] = legacy.vgg_features_read(outFeaturesFile,'FloatDesc',true); 40 | res.time = info.time; 41 | delete(outFeaturesFile); 42 | delete(imagePath); 43 | if ~isempty(feats), delete(framesPath); end; 44 | end 45 | 46 | function args = buildArgs(opts, imagePath, outFile) 47 | % -nl - do not write the hessian keypoint type 48 | args = sprintf('-nl -i "%s" -o "%s"', imagePath, outFile); 49 | fields = fieldnames(opts); 50 | for i = 1:numel(fields) 51 | val = opts.(fields{i}); 52 | if ~isempty(val) 53 | if ismember(fields{i},{'u','e'}) 54 | if val, args = [args,' -',fields{i}]; end 55 | else 56 | args = [args,' -',fields{i},' ', num2str(val)]; 57 | end 58 | end 59 | end 60 | end -------------------------------------------------------------------------------- /matlab/+utls/generate_ellblobs.m: -------------------------------------------------------------------------------- 1 | function [ img ] = generate_ellblobs(varargin) 2 | %GENELLIPTICBLOBS Generate testing image with multi-variant Gauss. blobs 3 | % IMG = GENELLIPTICBLOBS('OptionName',OptionValue,...) Generates image IMG 4 | % with generated multivariate Gaussian blobs according to the settings. 5 | % There is generated 'NumDeformations' x 'NumDeformations' blobs which are 6 | % filling the whole image, with size 'Width' x 'Height' (with a certain 7 | % border). 8 | % The size of the blobs is determined in order to fit into the image. 9 | % Output image is of type double and values are in interval [0;1]. 10 | % 11 | % Available options: 12 | % 13 | % Width:: 500 14 | % Output image width 15 | % 16 | % Height:: 500 17 | % Output image height 18 | % 19 | % NumDeformations:: 3 20 | % Number of blobs in a column with decreasing scale. 21 | % 22 | % MaxDeformation:: 1/3 23 | % Maximal blob deformation. 24 | 25 | % Copyright (C) 2011-16 Karel Lenc, Andrea Vedaldi 26 | % All rights reserved. 27 | % 28 | % This file is part of the VLFeat library and is made available under 29 | % the terms of the BSD license (see the COPYING file). 30 | 31 | opts.width = 500; 32 | opts.height = 500; 33 | opts.numDeformations = 3; 34 | opts.maxDeformation = 1/3; 35 | opts = vl_argparse(opts, varargin); 36 | 37 | img = zeros(opts.height,opts.width) ; 38 | border = 4; % Border size in the blobSpacing 39 | blobSpacing = opts.width/opts.numDeformations/6; 40 | xSigmas = linspace(border*blobSpacing,opts.width-border*blobSpacing,... 41 | opts.numDeformations); 42 | ySigmas = linspace(border*blobSpacing,opts.height-border*blobSpacing,... 43 | opts.numDeformations); 44 | deformations = linspace(1,opts.maxDeformation,opts.numDeformations); 45 | [x,y]=meshgrid(1:opts.width,1:opts.height) ; 46 | 47 | for i=1:opts.numDeformations 48 | for j=1:opts.numDeformations 49 | dx = (x - xSigmas(j)) / (blobSpacing*deformations(i)) ; 50 | dy = (y - ySigmas(i)) / (blobSpacing*deformations(i)*deformations(j)) ; 51 | d2 = dx.*dx + dy.*dy ; 52 | img = img + exp(-0.5*d2) ; 53 | end 54 | end 55 | 56 | end 57 | 58 | -------------------------------------------------------------------------------- /matlab/vlb_detect.m: -------------------------------------------------------------------------------- 1 | function [dest_feats_name, feats] = vlb_detect(imdb, detector, varargin) 2 | %VLB_DETECT Compute features using a given detector 3 | % VLB_DETECT imdb detector 4 | 5 | % Copyright (C) 2016-2017 Karel Lenc 6 | % All rights reserved. 7 | % 8 | % This file is part of the VLFeat library and is made available under 9 | % the terms of the BSD license (see the COPYING file). 10 | 11 | import features.*; 12 | 13 | opts.override = false; 14 | opts.imids = []; 15 | opts.catchErrs = false; 16 | opts.storeFeatures = true; 17 | [opts, varargin] = vl_argparse(opts, varargin); 18 | 19 | imdb = dset.factory(imdb); 20 | if isempty(opts.imids), opts.imids = 1:numel(imdb.images); end 21 | detector = features.factory('det', detector, varargin{:}); 22 | 23 | impaths = {imdb.images(opts.imids).path}; 24 | imnames = {imdb.images(opts.imids).name}; 25 | dest_dir = vlb_path('features', imdb, detector); 26 | dest_feats_name = detector.name; 27 | vl_xmkdir(dest_dir); 28 | 29 | fprintf('Running detector `%s` for %d images of dset `%s`.\n', ... 30 | detector.name, numel(impaths), imdb.name); 31 | fprintf('Resulting features are going to be stored in:\n%s.\n', dest_dir); 32 | status = utls.textprogressbar(numel(impaths), 'startmsg', ... 33 | sprintf('Computing %s ', detector.name), 'updatestep', 1); 34 | all_feats = cell(1, numel(impaths)); 35 | for si = 1:numel(impaths) 36 | impath = impaths{si}; 37 | imname = imnames{si}; 38 | feats_path = fullfile(dest_dir, imname); 39 | feats = utls.features_load(feats_path, 'checkonly', nargout <= 1, ... 40 | 'compulsoryFields', {'frames.csv'}); 41 | if ~isempty(feats) && ~opts.override 42 | status(si); continue; 43 | end 44 | im = imread(impath); 45 | if opts.catchErrs 46 | try 47 | feats = detector.fun(im); 48 | catch e 49 | feats = struct('failed', true, 'impath', impath, 'error', e); 50 | continue; 51 | end 52 | else 53 | feats = detector.fun(im); 54 | end 55 | if opts.storeFeatures 56 | utls.features_save(feats_path, feats); 57 | end 58 | if nargout > 1, all_feats{si} = feats; end 59 | status(si); 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /python/test/test_epiDist_bench.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # =========================================================== 4 | # File Name: tests_epiDist_bench.py 5 | # Author: Alex Butenko, Georiga Institute of Technology 6 | # Creation Date: 06-01-2019 7 | # Last Modified: Sat Jun 1 21:46:25 2019 8 | # 9 | # Description: Test epipolar distance benchmark 10 | # 11 | # Copyright (C) 2019 Alex Butenko 12 | # All rights reserved. 13 | # 14 | # This file is made available under 15 | # the terms of the BSD license (see the COPYING file). 16 | # =========================================================== 17 | 18 | 19 | import os 20 | import sys 21 | cwd = os.getcwd() 22 | sys.path.insert(0, '{}/python/'.format(cwd)) 23 | 24 | import bench.Utils 25 | import bench.epiDistanceBench 26 | import verifiers.ransac 27 | import verifiers.lmeds 28 | import dset.verification_dataset 29 | 30 | 31 | if __name__ == "__main__": 32 | 33 | # Define epiConstraintBench benchmark 34 | epiDistanceBench = bench.epiDistanceBench.epiDistanceBench() 35 | 36 | # Define feature 37 | ransac = verifiers.ransac.RANSAC() 38 | lmeds = verifiers.lmeds.LMEDS() 39 | 40 | # Define dataset 41 | dataset = dset.verification_dataset.verification_dataset() 42 | 43 | # Do the evaluation 44 | rep_result_r = epiDistanceBench.evaluate( 45 | dataset, ransac, use_cache=False, save_result=True) 46 | 47 | rep_result_l = epiDistanceBench.evaluate( 48 | dataset, lmeds, use_cache=False, save_result=True) 49 | 50 | rep_result = [rep_result_r, rep_result_l] 51 | 52 | # Show the result 53 | for result_term in rep_result[0]['result_term_list']: 54 | bench.Utils.print_result(rep_result, result_term) 55 | bench.Utils.save_result(rep_result, result_term) 56 | 57 | # TODO add show_sequence flag 58 | for sequence in dataset.sequence_name_list: 59 | for result_term in rep_result[0]['result_term_list']: 60 | bench.Utils.print_sequence_result(rep_result, sequence, result_term) 61 | bench.Utils.save_sequence_result(rep_result, sequence, result_term) 62 | -------------------------------------------------------------------------------- /matlab/+utls/oell_warp.m: -------------------------------------------------------------------------------- 1 | function [ tfframes ] = oell_warp( frames, tf, varargin ) 2 | % WARPFRAME Warp a local feature frame with a homogprahy 3 | % WF = WARPFRAME(F, H) Warps frames F by homography H to generate warped 4 | % frames WF. 5 | % In case of a full Homography, an affine transformation at the frame 6 | % location is estimated using the second order Taylor polynom. 7 | % 8 | % The Taylor expansion code - copyright K. Mikolajczyk. 9 | 10 | opts.method = 'pre'; 11 | opts.ignoreLocation = false; 12 | opts = vl_argparse(opts, varargin, 'nonrecursive'); 13 | 14 | method = opts.method; 15 | assert(all(size(tf) == [3, 3])); 16 | frames = vl_frame2oell(frames); 17 | ftf = utls.frame2afftf(frames); 18 | tfs = zeros(size(ftf), 'like', ftf); 19 | tfs(3, 3, :) = 1; 20 | 21 | linearize = tf(3, 3) ~= 1 || any(tf(3, 1:2) ~= 0); 22 | for i = 1:size(frames, 2) 23 | H = tf; 24 | if linearize % Linearise the affine transformation at feature point 25 | x = ftf(1, 3, i); y = ftf(2, 3, i); 26 | % H linearisation, originally from K. Mikolajczyk 27 | h11=H(1); h12=H(4); h13=H(7); 28 | h21=H(2); h22=H(5); h23=H(8); 29 | h31=H(3); h32=H(6); h33=H(9); 30 | fxdx=h11/(h31*x+h32*y+h33)-(h11*x+h12*y+h13)*h31/(h31*x+h32*y+h33)^2; 31 | fxdy=h12/(h31*x+h32*y+h33)-(h11*x+h12*y+h13)*h32/(h31*x+h32*y+h33)^2; 32 | fydx=h21/(h31*x+h32*y+h33)-(h21*x+h22*y+h23)*h31/(h31*x+h32*y+h33)^2; 33 | fydy=h22/(h31*x+h32*y+h33)-(h21*x+h22*y+h23)*h32/(h31*x+h32*y+h33)^2; 34 | Aff=[fxdx fxdy;fydx fydy]; 35 | switch method 36 | case 'pre' 37 | C=H*[x;y;1]; C=C./C(3); 38 | tfs(1:2, 1:2, i) = Aff * ftf(1:2,1:2,i); 39 | case 'post' 40 | C=H*[0;0;1]; C=C./C(3); 41 | tfs(1:2, 1:2, i) = ftf(1:2,1:2,i) * Aff; 42 | end 43 | if ~opts.ignoreLocation, tfs(1:2, 3, i) = C(1:2); end 44 | else 45 | switch method 46 | case 'pre' 47 | tfs(:,:, i) = H * ftf(:,:,i); 48 | case 'post' 49 | tfs(:,:, i) = ftf(:,:,i) * H; 50 | end 51 | if opts.ignoreLocation, tfs(1:2,3, i) = ftf(1:2,3,i); end 52 | end 53 | end 54 | tfframes = utls.afftf2frame(tfs); 55 | 56 | end 57 | 58 | -------------------------------------------------------------------------------- /matlab/+features/+det/lift.m: -------------------------------------------------------------------------------- 1 | function res = lift(img, varargin) 2 | % Dependecies in Python: see vendor/lift/depdendecies.txt + opencv-python 3 | 4 | opts.url = 'https://github.com/cvlab-epfl/LIFT/archive/master.zip'; 5 | opts.rootDir = fullfile(vlb_path('vendor'), 'lift'); 6 | [opts, varargin] = vl_argparse(opts, varargin); 7 | opts.binDir = fullfile(opts.rootDir, 'LIFT-master'); 8 | [opts, varargin] = vl_argparse(opts, varargin); 9 | opts.pythonDir = fullfile(opts.binDir, 'python-code'); 10 | opts.ccodeDir = fullfile(opts.binDir, 'c-code'); 11 | opts.confPath = fullfile(opts.binDir, '/models/configs/picc-finetune-nopair.config'); 12 | opts.modelPath = fullfile(opts.binDir, '/models/picc-best/'); 13 | opts.numKeypoints = 2000; 14 | opts.pythoncmd = 'python3'; 15 | [opts, varargin] = vl_argparse(opts, varargin); 16 | 17 | res.detName = 'lift'; res.args = opts; res.frames = zeros(5, 0); 18 | if isempty(img), return; end 19 | 20 | utls.provision(opts.url, opts.rootDir, 'forceExt', '.zip'); 21 | 22 | name = tempname; 23 | imname = [name, '.png']; 24 | imwrite(img, imname); 25 | featsname = [name, '.txt']; 26 | 27 | cmd = sprintf('%s compute_detector.py "%s" "%s" "%s" 0 1 0 "%s" %d', ... 28 | opts.pythoncmd, ... 29 | opts.confPath, imname, featsname, opts.modelPath, opts.numKeypoints); 30 | [~, info] = utls.sysrun(cmd, 'runDir', opts.pythonDir, varargin{:}); 31 | res = frames_read(featsname); 32 | res.dettime = info.time; 33 | delete(imname); 34 | delete(featsname); 35 | end 36 | 37 | 38 | function [out] = frames_read(framesFile) 39 | fid = fopen(framesFile, 'r'); 40 | if fid==-1, error('Could not read file: %s\n', framesFile); end 41 | [header, count] = fscanf(fid, '%f', 2); 42 | if count ~= 2 43 | fclose(fid); 44 | error('Invalid frames format.'); 45 | end 46 | numPoints = header(2); 47 | [data, count] = fscanf(fid,'%f', [13, numPoints]); 48 | fclose(fid); 49 | if count ~= 13 * numPoints, error('Invalid frames format.'); end 50 | % Transform the frame properly 51 | % X Y CORNERNESS SCALE/3 ANGLE TYPE LAP EXTR M11 M12 M21 M22 52 | out.frames = zeros(4, numPoints); 53 | out.frames(1:2,:) = data(1:2,:) + 1; 54 | out.frames(3:4,:) = data(3:4, :); 55 | out.detresponses = data(5, :); 56 | end -------------------------------------------------------------------------------- /python/test/test_inlierPrec_bench.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # =========================================================== 4 | # File Name: test_inlierPrec_bench.py 5 | # Author: Alex Butenko, Georgia Institute of Technology 6 | # Creation Date: 06-01-2019 7 | # Last Modified: Sat Jun 1 00:03:28 2019 8 | # 9 | # Description:test inlier benchmarks for geometric verification 10 | # 11 | # Copyright (C) 2018 Alex Butenko 12 | # All rights reserved. 13 | # 14 | # This file is made available under 15 | # the terms of the BSD license (see the COPYING file). 16 | # =========================================================== 17 | 18 | import os 19 | import sys 20 | cwd = os.getcwd() 21 | sys.path.insert(0, '{}/python/'.format(cwd)) 22 | 23 | import bench.Utils 24 | import bench.inlierPrecisionBench 25 | import verifiers.ransac 26 | import verifiers.learnedCoores 27 | import verifiers.lmeds 28 | import verifiers.mlesac 29 | import dset.verification_dataset 30 | 31 | 32 | if __name__ == "__main__": 33 | 34 | # Define epiConstraintBench benchmark 35 | inlierPrecisionBench = bench.inlierPrecisionBench.inlierPrecisionBench() 36 | 37 | # Define feature 38 | # ransac = verifiers.ransac.RANSAC() 39 | # lmeds = verifiers.lmeds.LMEDS() 40 | # lc = verifiers.learnedCoores.learnedCoores() 41 | mlesac = verifiers.mlesac.MLESAC() 42 | 43 | # Define dataset 44 | dataset = dset.verification_dataset.verification_dataset(['reichstag']) 45 | 46 | # Do the evaluation 47 | rep_result_r = inlierPrecisionBench.evaluate( 48 | dataset, mlesac, use_cache=False, save_result=True) 49 | 50 | rep_result = [rep_result_r] 51 | # Show the result 52 | for result_term in rep_result[0]['result_term_list']: 53 | bench.Utils.print_result(rep_result, result_term) 54 | bench.Utils.save_result(rep_result, result_term) 55 | 56 | #Show result for different sequences 57 | for sequence in dataset.sequences: 58 | for result_term in rep_result[0]['result_term_list']: 59 | bench.Utils.print_sequence_result(rep_result, sequence, result_term) 60 | bench.Utils.save_sequence_result(rep_result, sequence, result_term) 61 | -------------------------------------------------------------------------------- /python/dset/write_dataset_vggh.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | sequence_name_list = ['bikes','trees','graf','wall','boat','bark','leuven','ubc'] 4 | description_list = ['Increasing blur','Increasing blur','Viewpoint angle','Viewpoint angle','Scale changes','Scale changes','Decreasing light','JPEG compression'] 5 | label_list = [ 6 | [1, 2, 3, 4, 5, 6], 7 | [1, 2, 3, 4, 5, 6], 8 | [0, 20, 30, 40, 50, 60], 9 | [0, 20, 30, 40, 50, 60], 10 | [1, 1.12, 1.38, 1.9, 2.35, 2.8], 11 | [1, 1.2, 1.8, 2.5, 3, 4], 12 | [1, 2, 3, 4, 5, 6], 13 | [0, 60, 80, 90, 95, 98]] 14 | 15 | json_data = {} 16 | json_data['Dataset Name'] = 'VGG Affine' 17 | json_data['Description'] = 'Standard Benchmark' 18 | json_data['url'] = 'http://www.robots.ox.ac.uk/~vgg/research/affine/det_eval_files/' 19 | json_data['Sequence Number'] = len(sequence_name_list) 20 | json_data['Sequence Name List'] = sequence_name_list 21 | json_data['Sequences'] = [] 22 | 23 | for idx, sequence_name in enumerate(sequence_name_list): 24 | sequence = {} 25 | sequence['Name'] = sequence_name 26 | sequence['Description'] = sequence_name 27 | sequence['Label'] = description_list[idx] 28 | sequence['Images'] = [] 29 | sequence['Image Number'] = 6 30 | 31 | for image_idx, image_label in enumerate(label_list[idx]): 32 | image = {} 33 | if sequence_name == 'boat': 34 | image['file'] = '{}/img{}.pgm'.format(sequence_name,image_idx+1) 35 | else: 36 | image['file'] = '{}/img{}.ppm'.format(sequence_name,image_idx+1) 37 | 38 | image['id'] = str(image_idx+1) 39 | image['label'] = str(image_label) 40 | sequence['Images'].append(image) 41 | 42 | sequence['Link Number'] = 5 43 | sequence['Links'] = [] 44 | for i in range(1,6): 45 | link = {} 46 | link['source'] = str(1) 47 | link['target'] = str(i+1) 48 | link['file'] = '{}/H1to{}p'.format(sequence_name, i+1) 49 | sequence['Links'].append(link) 50 | json_data['Sequences'].append(sequence) 51 | 52 | with open('./datasets/dataset_info/{}.json'.format('vggh'),'w') as json_file: 53 | json.dump(json_data, json_file, indent=2) 54 | -------------------------------------------------------------------------------- /matlab/+legacy/vgg_features_write.m: -------------------------------------------------------------------------------- 1 | function vgg_features_write(file, frames, descriptors, varargin) 2 | % VGG_FEATURES_WRITE Write image features to a file 3 | % VGG_FEATURES_WRITE(FILE_PATH, FRAMES, DESCRIPTORS) Write FRAMES and DESCRIPTORS 4 | % to a file specified by FILE_PATH. 5 | % 6 | % Features are written in a Oxford format: 7 | % 8 | % \n 9 | % \n 10 | % 11 | % \n 12 | % ... 13 | 14 | % Copyright (C) 2011-16 Karel Lenc, Andrea Vedaldi 15 | % All rights reserved. 16 | % 17 | % This file is part of the VLFeat library and is made available under 18 | % the terms of the BSD license (see the COPYING file). 19 | 20 | numFrames = size(frames,2); 21 | descrLen = size(descriptors,1); 22 | descriptors = double(descriptors); % It does not like uint8 descs. 23 | if numFrames == 0, return; end 24 | 25 | g = fopen(file, 'w'); 26 | if g == -1 27 | error(['Could not open file ''', file, '''.']) ; 28 | end 29 | 30 | framesDim = size(frames, 1); 31 | if framesDim < 3 || framesDim > 6 32 | error('Invalid frames format, dimensionality of a frame must be <3,6>'); 33 | end 34 | 35 | if descrLen > 0 && size(descriptors,2) ~= numFrames 36 | error('Number of frames and associated descriptors must agree.'); 37 | end 38 | 39 | % Write header 40 | fprintf(g,'%d\n%d\n', descrLen, numFrames); 41 | % Record format: x, y, a, b, c such that x' [a b ; b c] x = 1 42 | frames = utls.frame2ellipse(frames); 43 | frames(1:2,:) = frames(1:2,:) - 1 ; % change from matlab origin 44 | frames(3:5,:) = inv2x2(frames(3:5,:)) ; % Inverse the shape matrix 45 | if descrLen == 0 46 | fprintf(g,'%g %g %g %g %g\n',frames); 47 | else 48 | for i=1:size(frames,2) 49 | fprintf(g,'%g ', frames(:,i)'); 50 | fprintf(g,'%g ', descriptors(:,i)'); 51 | fprintf(g,'\n'); 52 | end 53 | end 54 | fclose(g) ; 55 | end 56 | 57 | 58 | % -------------------------------------------------------------------- 59 | function S = inv2x2(C) 60 | % -------------------------------------------------------------------- 61 | den = C(1,:) .* C(3,:) - C(2,:) .* C(2,:) ; 62 | S = [C(3,:) ; -C(2,:) ; C(1,:)] ./ den([1 1 1], :) ; 63 | end 64 | -------------------------------------------------------------------------------- /matlab/+utls/ellipse_warp.m: -------------------------------------------------------------------------------- 1 | function well = ellipse_warp(H, ell, varargin) 2 | % ELLIPSE_WARP Warp elliptical frame through homography 3 | % WELL = ELLIPSE_WARP(H, ELL) warps the ellptical frame(s) ELL by 4 | % using the homography matrix H. The homography is assumed to be 5 | % expressed relative to a coordinate system with orgin in (0,0), 6 | % while the frames ELL are in MATLAB image coordinate system with 7 | % origin in (1,1). 8 | 9 | % Copyright (C) 2011-16 Andrea Vedaldi, Kristina Mikolajczyk 10 | % All rights reserved. 11 | % 12 | % This file is part of the VLFeat library and is made available under 13 | % the terms of the BSD license (see the COPYING file). 14 | 15 | % take out MATLAB 1,1 origin 16 | ell(1:2,:) = ell(1:2,:) - 1 ; 17 | 18 | import helpers.*; 19 | opts.method = 'standard'; 20 | opts = vl_argparse(opts, varargin); 21 | 22 | well = zeros(size(ell)); 23 | 24 | for i=1:size(ell,2) 25 | switch opts.method 26 | case 'standard' 27 | S = [ell(3,i) ell(4,i) 0 ; ell(4,i) ell(5,i) 0 ; 0 0 -1] ; 28 | T = [1 0 ell(1,i) ; 0 1 ell(2,i) ; 0 0 1] ; 29 | 30 | M = H * T * S * T' * H' ; 31 | M = - M / M(3,3) ; 32 | 33 | t_ = - M(1:2,3) ; 34 | S_ = M(1:2,1:2) + t_*t_' ; 35 | 36 | well(:,i) = [t_ ; S_([1;2;4])] ; 37 | 38 | case 'linearise' 39 | % Kristian Mikolajczyk's Solution 40 | Mi1=[ell(3,i) ell(4,i);ell(4,i) ell(5,i)]; 41 | x = ell(1,i); y = ell(2,i); 42 | h11=H(1); h12=H(4); h13=H(7); 43 | h21=H(2); h22=H(5); h23=H(8); 44 | h31=H(3); h32=H(6); h33=H(9); 45 | fxdx=h11/(h31*x+h32*y+h33)-(h11*x+h12*y+h13)*h31/(h31*x+h32*y+h33)^2; 46 | fxdy=h12/(h31*x+h32*y+h33)-(h11*x+h12*y+h13)*h32/(h31*x+h32*y+h33)^2; 47 | fydx=h21/(h31*x+h32*y+h33)-(h21*x+h22*y+h23)*h31/(h31*x+h32*y+h33)^2; 48 | fydy=h22/(h31*x+h32*y+h33)-(h21*x+h22*y+h23)*h32/(h31*x+h32*y+h33)^2; 49 | Aff=[fxdx fxdy;fydx fydy]; 50 | 51 | %project to image 2 52 | l1=[ell(1,i),ell(2,i),1]; 53 | l1_2=H*l1'; 54 | l1_2=l1_2/l1_2(3); 55 | well(1,i)=l1_2(1); 56 | well(2,i)=l1_2(2); 57 | BMB=Aff*Mi1*Aff'; 58 | well(3:5,i)=[BMB(1);BMB(2); BMB(4)]; 59 | 60 | otherwise 61 | error('Invalid method.'); 62 | end 63 | end 64 | % put back MATLAB 1,1 origin 65 | well(1:2,:) = well(1:2,:) + 1 ; 66 | end -------------------------------------------------------------------------------- /matlab/+legacy/vgg_features_read.m: -------------------------------------------------------------------------------- 1 | function [frames, descriptors] = vgg_features_read(featuresFile, varargin) 2 | %VGG_FEATURES_READ Read file exported by some of the older frame detectors. 3 | % FRAMES = VGG_FEATURES_READ(FRAME_FILE_PATH) Reads FRAMES from a file 4 | % defined by FRAME_FILE_PATH 5 | % 6 | % vl_ubcread cannot be used because some older detectors produce files 7 | % which contain length of the descriptors = 1 which the vl_ubcread function 8 | % is not able to handle. 9 | % 10 | % Function accepts the following options: 11 | % 'FloatDesc' :: 12 | % Feature file contains floating point descriptors. 13 | % 14 | 15 | % Copyright (C) 2011-16 Karel Lenc, Andrea Vedaldi 16 | % All rights reserved. 17 | % 18 | % This file is part of the VLFeat library and is made available under 19 | % the terms of the BSD license (see the COPYING file). 20 | 21 | opts.floatDesc = false; 22 | opts = vl_argparse(opts, varargin); 23 | 24 | fid = fopen(featuresFile, 'r'); 25 | if fid==-1, error('Could not read file: %s\n', featuresFile); end 26 | [header,count] = fscanf(fid,'%f',2); 27 | if count~= 2, error('Invalid frames file: %s\n', featuresFile); end 28 | descrLen = header(1); 29 | numFeatures = header(2); 30 | frames = zeros(5,numFeatures); 31 | if descrLen == 0 || descrLen == 1 32 | [frames,count] = fscanf(fid,'%f',[5 numFeatures]); 33 | if count~=5*numFeatures, 34 | error('Invalid frames file %s\n',featuresFile); 35 | end 36 | else 37 | descriptors = zeros(descrLen,numFeatures); 38 | for k = 1:numFeatures 39 | [frames(:,k), count] = fscanf(fid, '%f', [1 5]); 40 | if count ~= 5 41 | error('Invalid keypoint file (parsing keypoint %d, frame part)',k); 42 | end 43 | if opts.floatDesc 44 | [descriptors(:,k), count] = fscanf(fid, '%f', [1 descrLen]); 45 | else 46 | [descriptors(:,k), count] = fscanf(fid, '%d', [1 descrLen]); 47 | end 48 | if count ~= descrLen 49 | error('Invalid keypoint file (parsing keypoint %d, descriptor part)',k); 50 | end 51 | end 52 | end 53 | % Transform the frame properly 54 | frames(1:2,:) = frames(1:2,:) + 1; 55 | C = frames(3:5,:); 56 | den = C(1,:) .* C(3,:) - C(2,:) .* C(2,:) ; 57 | S = [C(3,:) ; -C(2,:) ; C(1,:)] ./ den([1 1 1], :) ; 58 | frames(3:5,:) = S; 59 | fclose(fid); 60 | end -------------------------------------------------------------------------------- /python/test/test_retrieval_bench.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # =========================================================== 4 | # File Name: test_retrieval_bench.py 5 | # Author: Xu Zhang, Columbia University 6 | # Creation Date: 01-25-2019 7 | # Last Modified: Sun Mar 3 17:58:13 2019 8 | # 9 | # Usage: python test_retrieval_bench.py 10 | # Description: Test retrieval benchmark 11 | # 12 | # Copyright (C) 2018 Xu Zhang 13 | # All rights reserved. 14 | # 15 | # This file is made available under 16 | # the terms of the BSD license (see the COPYING file). 17 | # =========================================================== 18 | 19 | import os 20 | import sys 21 | 22 | cwd = os.getcwd() 23 | sys.path.insert(0, '{}/python/'.format(cwd)) 24 | 25 | import bench.RetrievalBenchmark 26 | import features.cyvlsift_official 27 | import dset.oxford5k_dataset 28 | import dset.paris6k_dataset 29 | import bench.Utils 30 | 31 | if __name__ == "__main__": 32 | 33 | # Define retrieval benchmark 34 | retrieval_bench = bench.RetrievalBenchmark.RetrievalBenchmark() 35 | 36 | # Define feature 37 | vlsift_py = features.cyvlsift_official.cyvlsift_official() 38 | 39 | # Define dataset 40 | paris6k = dset.paris6k_dataset.paris6k_Dataset() 41 | 42 | # Do the test 43 | map_result_py = retrieval_bench.evaluate( 44 | paris6k, vlsift_py, use_cache=True, save_result=True) 45 | 46 | # Make the results from different detectors as a list. 47 | # (Only one here, but you can add more) 48 | map_result = [map_result_py] 49 | 50 | # Show the result 51 | for result_term in map_result[0]['result_term_list']: 52 | bench.Utils.print_retrieval_result(map_result, 'm' + result_term) 53 | bench.Utils.save_retrieval_result(map_result, 'm' + result_term) 54 | 55 | 56 | # Another dataset 57 | oxford5k = dset.oxford5k_dataset.oxford5k_Dataset() 58 | map_result_py = retrieval_bench.evaluate( 59 | oxford5k, vlsift_py, use_cache=True, save_result=True) 60 | map_result = [map_result_py] 61 | for result_term in map_result[0]['result_term_list']: 62 | bench.Utils.print_retrieval_result(map_result, 'm' + result_term) 63 | bench.Utils.save_retrieval_result(map_result, 'm' + result_term) 64 | -------------------------------------------------------------------------------- /python/dset/W1BS_dataset.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #-*- coding: utf-8 -*- 3 | #=========================================================== 4 | # File Name: vgg_dataset.py 5 | # Author: Xu Zhang, Columbia University 6 | # Creation Date: 09-26-2017 7 | # Last Modified: Sun Mar 3 16:56:28 2019 8 | # 9 | # Description: W1BS dataset 10 | # 11 | # Copyright (C) 2018 Xu Zhang 12 | # All rights reserved. 13 | # 14 | # This file is made available under 15 | # the terms of the BSD license (see the COPYING file). 16 | #=========================================================== 17 | 18 | from dset.dataset import SequenceDataset 19 | import urllib 20 | import tarfile 21 | import os 22 | import sys 23 | 24 | if sys.version_info[0] >= 3: 25 | from urllib.request import urlretrieve 26 | else: 27 | from urllib import urlretrieve 28 | 29 | 30 | class W1BS_Dataset(SequenceDataset): 31 | """ 32 | W1BS dataset for baseline matching 33 | """ 34 | def __init__(self,root_dir = './datasets/', download_flag = False): 35 | super(W1BS_Dataset,self).__init__(name = 'W1BS', root_dir = root_dir, download_flag = download_flag) 36 | 37 | def download(self): 38 | """ 39 | Download data 40 | """ 41 | try: 42 | os.stat(self.root_dir) 43 | except: 44 | os.mkdir(self.root_dir) 45 | 46 | try: 47 | os.stat('{}{}'.format(self.root_dir,self.name)) 48 | except: 49 | os.mkdir('{}{}'.format(self.root_dir,self.name)) 50 | 51 | download_url = "{}".format(self.url) 52 | download_filename = "{}{}/{}.tar.gz".format(self.root_dir, self.name, self.name) 53 | try: 54 | urlretrieve(download_url,download_filename) 55 | tar = tarfile.open(download_filename) 56 | tar.extractall('{}'.format(self.root_dir)) 57 | tar.close() 58 | os.remove(download_filename) 59 | except Exception as e: 60 | print(str(e)) 61 | print('Cannot download from {}.'.format(download_url)) 62 | 63 | def read_image_data(self): 64 | """ 65 | Load image data 66 | """ 67 | self.read_image_data_vggh() 68 | 69 | def read_link_data(self): 70 | """ 71 | Load link data 72 | """ 73 | self.read_link_data_vggh() 74 | -------------------------------------------------------------------------------- /matlab/+features/+det/random.m: -------------------------------------------------------------------------------- 1 | function [ res ] = random( img, varargin ) 2 | %RANDOM Summary of this function goes here 3 | % Detailed explanation goes here 4 | opts.featuresDensity = 2e-3; 5 | opts.numFeatures = nan; 6 | opts.frameType = 'disc'; 7 | opts.maxScale = 50; 8 | opts.minScale = 0.1; 9 | opts.maxAffScRot = 2*pi; 10 | opts.maxRot = 2*pi; 11 | opts.maxAnisotropy = 2; 12 | opts.anisotropyShift = 0; 13 | opts.seed = mean(double(img(:))); 14 | opts = vl_argparse(opts, varargin); 15 | res.detName = sprintf('random-%s', opts.frameType); res.args = opts; 16 | if isempty(img), res.frames = zeros(5, 0); return; end 17 | 18 | stime = tic; 19 | q = RandStream('mt19937ar','Seed', opts.seed); 20 | 21 | imgSize = size(img); 22 | imageArea = imgSize(1) * imgSize(2); 23 | if isnan(opts.numFeatures) 24 | numFeatures = round(imageArea * opts.featuresDensity); 25 | else 26 | numFeatures = opts.numFeatures; 27 | end 28 | locations = rand(q, 2, numFeatures); 29 | scales = abs(randn(q, 1, numFeatures))*(opts.maxScale - opts.minScale)./3 + opts.minScale; 30 | scales = min(scales, opts.maxScale); 31 | 32 | minLoc = [scales; scales]; 33 | maxLoc = [bsxfun(@plus, -scales, imgSize(2)); bsxfun(@plus, -scales, imgSize(1))]; 34 | locations(1,:) = locations(1,:) .* (maxLoc(1,:) - minLoc(1,:)) + minLoc(1, :); 35 | locations(2,:) = locations(2,:) .* (maxLoc(2,:) - minLoc(2,:)) + minLoc(2, :); 36 | 37 | res.frames = [locations; scales(1,:)]; 38 | 39 | switch opts.frameType 40 | case {'disc', 'oriented_disc'} 41 | if strcmp(opts.frameType, 'oriented_disc') 42 | angles = rand(1, numFeatures) * 2*pi; 43 | res.frames = [res.frames; angles]; 44 | end 45 | case {'ellipse', 'oriented_ellipse'} 46 | res.frames = vl_frame2oell(res.frames); 47 | for fi = 1:numFeatures 48 | A = utls.randomtf('minScale', 0, 'maxScale', 0, ... 49 | 'maxRot', opts.maxRot, 'maxAnisotropy', opts.maxAnisotropy, ... 50 | 'maxAffScRot', opts.maxAffScRot, 'q', q); 51 | 52 | Af = utls.frame2afftf(res.frames(:, fi)) * A; 53 | res.frames(:, fi) = utls.afftf2frame(Af); 54 | end 55 | if ~strcmp(opts.frameType, 'oriented_ellipse') 56 | res.frames = utls.frame2ellipse(res.frames); 57 | end 58 | otherwise 59 | error('Invalid frame type'); 60 | end 61 | res.detresponses = rand(1, numFeatures); 62 | res.dettime = toc(stime); 63 | end 64 | 65 | -------------------------------------------------------------------------------- /matlab/+features/+det/vggmser.m: -------------------------------------------------------------------------------- 1 | function [ res ] = vggmser( img, varargin ) 2 | %VGG_MSER Detect frames using the MSER detector 3 | % FRAMES = VGG_MSER(IMG) Computes the MSER features using the 4 | % implementation by [1]. 5 | % 6 | % Function supports the following options: 7 | % ES:: [binary default, 1.0] 8 | % Scale of the ellipse 9 | % 10 | % PER:: [binary default, 0.01] 11 | % Maximum relative area 12 | % 13 | % MS:: [binary default, 30] 14 | % Minimum size of output region 15 | % 16 | % MM:: [binary default, 10] 17 | % Minimum margin 18 | % 19 | % REFERENCES 20 | % [1] J. Matas, O. Chum, M. Urban and T. Pajdla. Robust wide-baseline 21 | % stereo from maximally stable extremal regions. BMVC, 384-393, 2002. 22 | 23 | % Copyright (C) 2011-16 Karel Lenc 24 | % All rights reserved. 25 | % 26 | % This file is part of the VLFeat library and is made available under 27 | % the terms of the BSD license (see the COPYING file). 28 | 29 | opts.es = 1; 30 | opts.per = -1; 31 | opts.ms = -1; 32 | opts.mm = -1; 33 | opts = vl_argparse(opts, varargin); 34 | res.detName = 'vggmser'; res.args = opts; 35 | if isempty(img), res.frames = zeros(5, 0); return; end; 36 | 37 | % Constants 38 | BIN_DIR = fullfile(vlb_path('vendor'), 'vgg_mser'); 39 | switch(computer) 40 | case {'GLNX86','GLNXA64'} 41 | BIN_PATH = fullfile(BIN_DIR, 'mser.ln'); 42 | case {'PCWIN','PCWIN64'} 43 | BIN_PATH = fullfile(BIN_DIR, 'mser.exe'); 44 | otherwise 45 | error('Unsupported platform.'); 46 | end 47 | BIN_URL = 'http://www.robots.ox.ac.uk/~vgg/research/affine/det_eval_files/mser.tar.gz'; 48 | % Make sure the detector is present 49 | if ~exist(BIN_PATH, 'file'), untar(BIN_URL, BIN_DIR); end 50 | 51 | tmpImgName = [tempname(), '.png']; 52 | if ischar(img) && exist(img, 'file') 53 | tmpImgName = img; 54 | else 55 | imwrite(img, tmpImgName); 56 | end 57 | 58 | framesFile = [tempname() '.feat']; 59 | args = ' -t 2'; % Define the output type 60 | fields = fieldnames(opts); 61 | for i = 1:numel(fields) 62 | val = opts.(fields{i}); 63 | if val >= 0, args = [args, ' -', fields{i}, ' ', num2str(val)]; end 64 | end 65 | cmd = sprintf('%s %s -i "%s" -o "%s"', BIN_PATH, args, tmpImgName, framesFile); 66 | [~, info] = utls.sysrun(cmd); 67 | frames = legacy.vgg_frames_read(framesFile); 68 | if ~strcmp(img, tmpImgName), delete(tmpImgName); end; 69 | delete(framesFile); 70 | res.frames = frames; 71 | res.dettime = info.time; -------------------------------------------------------------------------------- /matlab/+features/+det/tcdet.m: -------------------------------------------------------------------------------- 1 | function res = tcdet(img, varargin) 2 | % Dependecies in Python: tensorflow, scikit-image, opencv-python, exifread 3 | 4 | opts.url = 'https://codeload.github.com/ColumbiaDVMM/Transform_Covariant_Detector/zip/master'; 5 | opts.rootDir = fullfile(vlb_path('vendor'), 'tcdet'); 6 | [opts, varargin] = vl_argparse(opts, varargin); 7 | opts.binDir = fullfile(opts.rootDir, 'Transform_Covariant_Detector-master/'); 8 | opts.netsDir = fullfile(opts.binDir, 'tensorflow_model'); 9 | opts.runDir = fullfile(opts.binDir, 'tensorflow'); 10 | [opts, varargin] = vl_argparse(opts, varargin); 11 | opts.point_number = 4000; 12 | opts.thr = 1.2; 13 | [opts, varargin] = vl_argparse(opts, varargin); 14 | 15 | res.detName = 'tcdet'; res.args = opts; res.frames = zeros(5, 0); 16 | if isempty(img), return; end; 17 | 18 | padding = [0, 0]; 19 | imsz = [size(img, 1), size(img, 2)]; 20 | if any(imsz < 105) 21 | padding = ceil(max(105 - imsz, 0) ./ 2); 22 | img = padarray(img, [padding, 0], 'replicate'); 23 | end 24 | 25 | utls.provision(opts.url, opts.rootDir, 'forceExt', '.zip'); 26 | 27 | name = tempname; 28 | imname = [name, '.png']; 29 | imwrite(img, imname); 30 | featsname = [name, '.mat']; 31 | 32 | scriptPath = fullfile(vlb_path, 'matlab', '+features', '+utls', 'tcdet_eval.py'); 33 | copyfile(scriptPath, opts.runDir); 34 | scriptPath = fullfile(vlb_path, 'matlab', '+features', '+utls', 'tcdet_rundet.m'); 35 | copyfile(scriptPath, opts.runDir); 36 | 37 | cmd = sprintf('python2 tcdet_eval.py "%s" --save_feature "%s"', imname, featsname); 38 | env = struct(); %env = struct('LD_LIBRARY_PATH', '/users/karel/anaconda3/lib'); 39 | [out, info] = utls.sysrun(cmd, 'runDir', opts.runDir, 'unset_ld', false, 'env', env, varargin{:}); 40 | res.dettime = info.time; 41 | 42 | actpath = pwd; 43 | try 44 | cd(opts.runDir); 45 | [res.frames, res.detresponses, time] = tcdet_rundet(img, featsname, ... 46 | opts.point_number, opts.thr); 47 | if isfield(time, 'tftime') % Needs a hacked python_eval 48 | res.dettime = time.tftime; 49 | end 50 | res.dettime = res.dettime + time.dettime; 51 | catch e 52 | cd(actpath); 53 | throw(e); 54 | end 55 | cd(actpath); 56 | 57 | res.frames(1:2,:) = bsxfun(@minus, res.frames(1:2,:), padding'); 58 | res.frames(:, res.frames(1,:) < 0 | res.frames(2,:) < 0) = []; 59 | res.frames(:, res.frames(1,:) > imsz(2) | res.frames(2,:) > imsz(1)) = []; 60 | 61 | delete(imname); 62 | delete(featsname); 63 | 64 | end -------------------------------------------------------------------------------- /matlab/vlb_extract.m: -------------------------------------------------------------------------------- 1 | function vlb_extract(imdb, featsname, varargin) 2 | %VLB_EXTRACT Extract patches from all images of an imdb using featsname 3 | % VLB_EXTRACT imdb featsname 4 | 5 | % Copyright (C) 2016-2017 Karel Lenc 6 | % All rights reserved. 7 | % 8 | % This file is part of the VLFeat library and is made available under 9 | % the terms of the BSD license (see the COPYING file). 10 | 11 | opts.override = false; 12 | opts.grayscale = true; 13 | opts.imgExt = '.png'; 14 | opts.scalingFactor = 5; 15 | opts.extractPatchesFun = @utls.patches_extract_covdet; 16 | opts.maxNumFeatures = 10000; 17 | [opts, varargin] = vl_argparse(opts, varargin); 18 | 19 | imdb = dset.factory(imdb); 20 | if iscell(featsname), featsname = fullfile(featsname); end; 21 | 22 | dets_path = vlb_path('features', imdb, struct('name', featsname)); 23 | if ~isdir(dets_path), utls.features_not_found(dets_path); end; 24 | impaths = {imdb.images.path}; 25 | imnames = {imdb.images.name}; 26 | 27 | patches_dir = vlb_path('patches', imdb, struct('name', featsname)); 28 | vl_xmkdir(patches_dir); 29 | 30 | fprintf('Extracting patches %s - %s for %d images.\n', ... 31 | imdb.name, featsname, numel(impaths)); 32 | status = utls.textprogressbar(numel(impaths), 'startmsg', ... 33 | sprintf('Patch Extr. '), 'updatestep', 1); 34 | for di = 1:numel(impaths) 35 | status(di); 36 | imname = imnames{di}; 37 | respath = fullfile(patches_dir, [imname, opts.imgExt]); 38 | if exist(respath, 'file') == 2 && ~opts.override, continue; end 39 | 40 | [found, imi] = ismember(imname, {imdb.images.name}); 41 | if ~found, error('Detections %s not found.', imname); end; 42 | if opts.grayscale 43 | im = utls.imread_grayscale(imdb.images(imi).path); 44 | else 45 | im = imread(dset.images(imi).path); 46 | end 47 | feats = utls.features_load(fullfile(dets_path, imname))'; 48 | frames = feats.frames; 49 | if size(frames, 2) > opts.maxNumFeatures 50 | warning('Too many detected frames (%d) in %s, taking a random %d.\n', ... 51 | size(frames, 2), fullfile(dets_path, imname), opts.maxNumFeatures); 52 | frames = vl_colsubset(frames, opts.maxNumFeatures); 53 | end 54 | assert(isfield(feats, 'frames'), 'Invalid features %s - no geom. frames', ... 55 | dets_path); 56 | patches = opts.extractPatchesFun(im, frames, ... 57 | 'scalingFactor', opts.scalingFactor, varargin{:}); 58 | 59 | utls.patches_save(patches, respath, opts.scalingFactor); 60 | end 61 | 62 | end -------------------------------------------------------------------------------- /python/doc/new_dataset.rst: -------------------------------------------------------------------------------- 1 | How to Create New Dataset 2 | ========================================================= 3 | To test your own dataset with off-the-shelf detector and descriptor, you need to create your own dataset class. 4 | 5 | 6 | Image Matching Dataset 7 | ---------------------------------------------- 8 | 9 | To create new image matching dataset like VGG-Affine or HPatches, follow code `dset.vgg_dataset.vgg_Dataset`. There is an download() function helping users to download data from Internet, extract and orgnize the file. read_image_data() defines how to read all the images. And read_link_data() defines how to read link data (relation of image pair). 10 | 11 | Each dataset will have a json file in datasets/dataset_info/. dataset.json defines the general format for the matching dataset. The json file contains name, descriptor of the dataset, url, number of sequence and each sequence. In each sequence, there are the information of each image and each link. dset/write_dataset_vggh.py provides an example of how to using python script to write the json file. 12 | 13 | .. literalinclude:: ../dset/write_dataset_vggh.py 14 | 15 | 16 | Image Retrieval Dataset 17 | ---------------------------------------------- 18 | 19 | To create new image retrieval dataset like oxford5k or paris6k, follow code `dset.oxford5k_dataset.oxford_Dataset` and `dset.paris6k_dataset.paris6k_Dataset`. There is an download() function helping users to download data from Internet, extract and orgnize the file. read_gallery_list() defines how to read all galary images (world/dataset images). And read_query_list() defines how to read query_image and corresponding ground-truth in the gallery dataset. For the query image, each image name as well as a bounding box associate to the object [filename, left, top, right, bottom] are make an item in the query_list. There is one positive_lists each item is a list of filenames of the ground-truth images of the corresponding query. Also, there is one junk_lists each item is a list of filenames of the opt-out images of the corresponding query. 20 | 21 | The json file of the retrieval dataset is pretty simple. See datasets/dataset_info/oxford5k.json. There are only one dataset name, one url and one description. 22 | 23 | 24 | Baseline Matching Dataset 25 | ---------------------------------------------- 26 | It's very similar to Image Matching dataset. See `dset.W1BS_dataset.W1BS_Dataset` and ../dset/write_dataset_W1BS.py. 27 | 28 | 29 | -------------------------------------------------------------------------------- /matlab/+legacy/vgg_desc_benchmark.m: -------------------------------------------------------------------------------- 1 | function [results, info] = vgg_desc_benchmark(geom, ... 2 | ima_p, featsa, imb_p, featsb, varargin) 3 | %VGG_DESC_BENCHMARK Summary of this function goes here 4 | opts.maxOverlapError = 0.5; 5 | opts = vl_argparse(opts, varargin); 6 | 7 | BIN_URL = 'http://www.robots.ox.ac.uk/~vgg/research/affine/det_eval_files/repeatability.tar.gz'; 8 | BIN_DIR = fullfile(vlb_path('vendor'), 'km_frames_benchmark'); 9 | % Make sure all supplementary files are present 10 | if ~exist(fullfile(BIN_DIR, 'repeatability.m'), 'file') 11 | untar(BIN_URL, BIN_DIR); 12 | end 13 | if ~exist(fullfile(BIN_DIR, ['descdist.', mexext]), 'file') 14 | mex(fullfile(BIN_DIR, 'descdist.cxx'), '-outdir', BIN_DIR); 15 | end 16 | if ~exist(fullfile(BIN_DIR, ['c_eoverlap.', mexext]), 'file') 17 | mex(fullfile(BIN_DIR, 'c_eoverlap.cxx'), '-outdir', BIN_DIR); 18 | end 19 | fa = featsa.frames; da = single(featsa.descs); 20 | fb = featsb.frames; db = single(featsb.descs); 21 | assert(size(fa, 2) == size(da, 2), 'Invalid number of frames/descriptors'); 22 | assert(size(fb, 2) == size(db, 2), 'Invalid number of frames/descriptors'); 23 | 24 | tmpFile = tempname; 25 | ella_p = [tmpFile, 'ellA.txt']; ellb_p = [tmpFile, 'ellB.txt']; 26 | ella_f = utls.frame2ellipse(fa); ellb_f = utls.frame2ellipse(fb); 27 | legacy.vgg_features_write(ella_p, ella_f, da); 28 | legacy.vgg_features_write(ellb_p, ellb_f, db); 29 | tmpH_p = [tmpFile, 'H.txt']; H = geom.H; save(tmpH_p, 'H','-ASCII'); 30 | overlap_err_idx = round(opts.maxOverlapError*10); 31 | 32 | addpath(BIN_DIR); 33 | rehash; 34 | [~, rep_sc_t, nc_t, ms, numMatches, twi] = ... 35 | repeatability(ella_p, ellb_p, tmpH_p, ima_p, imb_p, 0); 36 | rep_sc = rep_sc_t(overlap_err_idx)./100; 37 | nc = nc_t(overlap_err_idx); 38 | ms = ms ./ 100; 39 | [corrMatchNn, totMatchNn, corrMatchSim, totMatchSim, corrMatchRn, totMatchRn] = ... 40 | descperf(ella_p, ellb_p, tmpH_p, ima_p, imb_p, nc, twi); 41 | rmpath(BIN_DIR); 42 | 43 | delete(ella_p); delete(ellb_p); delete(tmpH_p); 44 | 45 | results = struct(); 46 | 47 | results.threshold.recall = corrMatchSim / sum(twi(:)); 48 | results.threshold.precision = corrMatchSim ./ totMatchSim; 49 | 50 | results.nn.recall = corrMatchNn / nc; 51 | results.nn.precision = corrMatchNn ./ totMatchNn; 52 | 53 | results.nndistratio.recall = corrMatchRn / nc; 54 | results.nndistratio.precision = corrMatchRn ./ totMatchRn; 55 | 56 | info = struct('repScore',rep_sc, 'numCorresp', nc, ... 57 | 'numSimCorresp', sum(twi(:)), 'matchScore', ms, ... 58 | 'numMatches', numMatches); 59 | end 60 | 61 | -------------------------------------------------------------------------------- /python/test/test_allVerification_bench.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # =========================================================== 4 | # File Name: test_allVerification_bench.py 5 | # Author: Alex Butenko, Georiga Institute of Technology 6 | # Creation Date: 06-01-2019 7 | # Last Modified: Sat Jun 1 21:46:25 2019 8 | # 9 | # Description: Test all verification tasks 10 | # 11 | # Copyright (C) 2019 Alex Butenko 12 | # All rights reserved. 13 | # 14 | # This file is made available under 15 | # the terms of the BSD license (see the COPYING file). 16 | # =========================================================== 17 | 18 | 19 | import os 20 | import sys 21 | cwd = os.getcwd() 22 | sys.path.insert(0, '{}/python/'.format(cwd)) 23 | 24 | import bench.Utils 25 | import bench.allVerificationBenchs 26 | import verifiers.ransac 27 | import verifiers.mlesac 28 | import verifiers.learnedCorres 29 | import verifiers.lmeds 30 | import dset.verification_dataset 31 | 32 | 33 | if __name__ == "__main__": 34 | 35 | # Define epiConstraintBench benchmark 36 | all = bench.allVerificationBenchs.allVerificationBenchs() 37 | 38 | # Define feature 39 | ransac = verifiers.ransac.RANSAC() 40 | lmeds = verifiers.lmeds.LMEDS() 41 | learned = verifiers.learnedCorres.learnedCorres() 42 | ml = verifiers.mlesac.MLESAC() 43 | 44 | # Define dataset 45 | dataset = dset.verification_dataset.verification_dataset(['reichstag']) 46 | 47 | # Do the evaluation 48 | rep_result_r = all.evaluate( 49 | dataset, ransac, use_cache=False, save_result=True) 50 | 51 | rep_result_l = all.evaluate( 52 | dataset, lmeds, use_cache=False, save_result=True) 53 | 54 | rep_result_lr = all.evaluate( 55 | dataset, learned, use_cache=False, save_result=True) 56 | 57 | rep_result_m = all.evaluate( 58 | dataset, ml, use_cache=False, save_result=True) 59 | 60 | rep_result = [rep_result_r, rep_result_l, rep_result_m, rep_result_lr] 61 | 62 | # Show the result 63 | for result_term in rep_result[0]['result_term_list']: 64 | bench.Utils.print_result(rep_result, result_term) 65 | bench.Utils.save_result(rep_result, result_term) 66 | 67 | #Show result for different sequences 68 | # for sequence in vggh.sequence_name_list: 69 | # for result_term in rep_result[0]['result_term_list']: 70 | # bench.Utils.print_sequence_result(rep_result, sequence, result_term) 71 | # bench.Utils.save_sequence_result(rep_result, sequence, result_term) 72 | -------------------------------------------------------------------------------- /python/test/test_epiConstraint_bench.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # =========================================================== 4 | # File Name: test_epiConstraint_bench.py 5 | # Author: Alex Butenko, Georiga Institute of Technology 6 | # Creation Date: 06-01-2019 7 | # Last Modified: Sat Jun 1 21:46:25 2019 8 | # 9 | # Description: Test epipolar constraint benchmark 10 | # 11 | # Copyright (C) 2019 Alex Butenko 12 | # All rights reserved. 13 | # 14 | # This file is made available under 15 | # the terms of the BSD license (see the COPYING file). 16 | # =========================================================== 17 | 18 | import os 19 | import sys 20 | cwd = os.getcwd() 21 | sys.path.insert(0, '{}/python/'.format(cwd)) 22 | 23 | import bench.Utils 24 | import bench.epiConstraintBench 25 | import verifiers.ransac 26 | import verifiers.mlesac 27 | import verifiers.learnedCorres 28 | import verifiers.lmeds 29 | import dset.verification_dataset 30 | 31 | 32 | if __name__ == "__main__": 33 | 34 | # Define epiConstraintBench benchmark 35 | epiBench = bench.epiConstraintBench.epiConstraintBench() 36 | 37 | # Define feature 38 | ransac = verifiers.ransac.RANSAC() 39 | lmeds = verifiers.lmeds.LMEDS() 40 | learned = verifiers.learnedCorres.learnedCorres() 41 | ml = verifiers.mlesac.MLESAC() 42 | 43 | # Define dataset 44 | dataset = dset.verification_dataset.verification_dataset(['reichstag']) 45 | 46 | # Do the evaluation 47 | rep_result_r = epiBench.evaluate( 48 | dataset, ransac, use_cache=False, save_result=True) 49 | 50 | rep_result_l = epiBench.evaluate( 51 | dataset, lmeds, use_cache=False, save_result=True) 52 | 53 | rep_result_lr = epiBench.evaluate( 54 | dataset, learned, use_cache=False, save_result=True) 55 | 56 | rep_result_m = epiBench.evaluate( 57 | dataset, ml, use_cache=False, save_result=True) 58 | 59 | rep_result = [rep_result_r, rep_result_l, rep_result_m, rep_result_lr] 60 | 61 | # Show the result 62 | for result_term in rep_result[0]['result_term_list']: 63 | bench.Utils.print_result(rep_result, result_term) 64 | bench.Utils.save_result(rep_result, result_term) 65 | 66 | #Show result for different sequences 67 | # for sequence in vggh.sequence_name_list: 68 | # for result_term in rep_result[0]['result_term_list']: 69 | # bench.Utils.print_sequence_result(rep_result, sequence, result_term) 70 | # bench.Utils.save_sequence_result(rep_result, sequence, result_term) 71 | -------------------------------------------------------------------------------- /python/dset/write_dataset_W1BS.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | sequence_name_list = ['A','G','L','map2photo','S'] 4 | description_list = ['Viewpoint Appearance','Viewpoint','ViewPoint Lighting','Map to Photo','Modality'] 5 | label_list = [ 6 | ['arch', 'obama', 'vprice0', 'vprice1', 'vprice2', 'yosemite'], 7 | ['adam', 'boat','ExtremeZoomA','face','fox','graf','mag','shop','there','vin'], 8 | ['amos1','bdom','brugge_square', 'GC2','light','madrid',\ 9 | 'notredame15','paintedladies','rushmore','trevi','vatican'], 10 | ['map1', 'map2', 'map3', 'map4', 'map5', 'map6'], 11 | ['angiogram','brain1','EO-IR-2',\ 12 | 'maunaloa','mms68','mms75','treebranch'] 13 | ] 14 | #label_list = [ 15 | # ['arch', 'obama', 'vprice0', 'vprice1', 'vprice2', 'yosemite'] 16 | # ] 17 | 18 | json_data = {} 19 | json_data['Dataset Name'] = 'W1BS' 20 | json_data['Description'] = 'Baseline Stereo Benchmark' 21 | json_data['url'] = 'http://cmp.felk.cvut.cz/wbs/datasets/W1BS_with_patches.tar.gz' 22 | json_data['Sequence Number'] = len(sequence_name_list) 23 | json_data['Sequence Name List'] = sequence_name_list 24 | json_data['Sequences'] = [] 25 | 26 | for idx, sequence_name in enumerate(sequence_name_list): 27 | sequence = {} 28 | sequence['Name'] = sequence_name 29 | sequence['Description'] = sequence_name 30 | sequence['Label'] = description_list[idx] 31 | sequence['Images'] = [] 32 | sequence['Image Number'] = len(label_list[idx])*2 33 | sequence['Link Number'] = len(label_list[idx]) 34 | sequence['Links'] = [] 35 | 36 | for image_idx, image_label in enumerate(label_list[idx]): 37 | image = {} 38 | image['file'] = '{}/1/{}.bmp'.format(sequence_name,image_label) 39 | image['id'] = str(image_label) + '_1' 40 | image['label'] = str(image_label) + '_1' 41 | sequence['Images'].append(image) 42 | image = {} 43 | image['file'] = '{}/2/{}.bmp'.format(sequence_name,image_label) 44 | image['id'] = str(image_label) + '_2' 45 | image['label'] = str(image_label) + '_2' 46 | sequence['Images'].append(image) 47 | 48 | link = {} 49 | link['source'] = str(image_label) + '_1' 50 | link['target'] = str(image_label) + '_2' 51 | link['file'] = '{}/h/{}.txt'.format(sequence_name, image_label) 52 | sequence['Links'].append(link) 53 | json_data['Sequences'].append(sequence) 54 | 55 | with open('./datasets/dataset_info/{}.json'.format('W1BS'),'w') as json_file: 56 | json.dump(json_data, json_file, indent=2) 57 | -------------------------------------------------------------------------------- /matlab/+features/+det/vggaff.m: -------------------------------------------------------------------------------- 1 | function [ res ] = vggaff( img, varargin ) 2 | %VGG_AFF Detect frames using VGG Affine co-variant detector 3 | % FRAMES = VGG_AFF(IMG) Detects FRAMES from image IMG. 4 | % Only supported architectures are GLNX86 and GLNXA64 as for these the 5 | % binaries are avaialable. 6 | % 7 | % Function takes the following options: 8 | % Detector:: 'hesaff' 9 | % One of {'hesaff', 'haraff', 'heslap', 'harlap','har'} which are 10 | % supported by the binary. 11 | % 12 | % Threshold:: -1 13 | % If specified, passes a threshold option to the binary. 14 | 15 | % Copyright (C) 2011-16 Karel Lenc 16 | % All rights reserved. 17 | % 18 | % This file is part of the VLFeat library and is made available under 19 | % the terms of the BSD license (see the COPYING file). 20 | 21 | opts.detector = 'hesaff'; 22 | opts.threshold = -1; 23 | opts.extended = false; 24 | opts = vl_argparse(opts, varargin); 25 | res.detName = sprintf('vggaff-%s', opts.detector); res.args = opts; 26 | if isempty(img), res.frames = zeros(5, 0); return; end; 27 | 28 | % Constants 29 | VALID_DETECTORS = {'hesaff', 'haraff', 'heslap', 'harlap', 'har'}; 30 | BIN_DIR = fullfile(vlb_path('vendor'), 'vgg_aff'); 31 | BIN_PATH = fullfile(BIN_DIR, 'h_affine.ln'); 32 | BIN_URL = 'http://www.robots.ox.ac.uk/~vgg/research/affine/det_eval_files/h_affine.ln.gz'; 33 | 34 | % Make sure the detector is present 35 | if ~exist(BIN_PATH, 'file') 36 | vl_xmkdir(BIN_DIR); 37 | utls.ungzip(BIN_URL, BIN_DIR); 38 | system(sprintf('chmod +x %s', BIN_PATH)); 39 | end 40 | assert(ismember(computer, {'GLNXA64', 'GLNX86'}), 'Unsupported platform'); 41 | assert(ismember(opts.detector, VALID_DETECTORS), 'Invalid detector'); 42 | 43 | % Write the input image 44 | tmpImgName = [tempname(), '.png']; 45 | if ischar(img) && exist(img, 'file'), img = imread(img); end; 46 | imwrite(img, tmpImgName); 47 | 48 | framesFile = [tempname() '.' opts.detector]; 49 | thr = ''; 50 | if opts.threshold >= 0, thr = sprintf('-thres %f', opts.threshold); end 51 | if ~opts.extended 52 | detCmd = sprintf('%s %s -%s -i "%s" -o "%s" %s', BIN_PATH, thr, ... 53 | opts.detector, tmpImgName, framesFile); 54 | [~, info] = utls.sysrun(detCmd); 55 | frames = legacy.vgg_frames_read(framesFile); 56 | if strcmp(opts.detector, 'har'), frames([3, 5], :) = 3.5^2; end 57 | res.frames = frames; 58 | else 59 | detCmd = sprintf('%s %s -%s -i "%s" -o2 "%s" %s', BIN_PATH, thr, ... 60 | opts.detector, tmpImgName, framesFile); 61 | [~, info] = utls.sysrun(detCmd); 62 | res = legacy.vgg_frames_read_ext(framesFile); 63 | end 64 | res.dettime = info.time; 65 | delete(framesFile); delete(tmpImgName); -------------------------------------------------------------------------------- /matlab/xtest/suite/test_desc_benchmark.m: -------------------------------------------------------------------------------- 1 | classdef test_desc_benchmark < matlab.unittest.TestCase 2 | 3 | properties (TestParameter) 4 | detector = {@features.det.vlsift}; 5 | dataset = {dset.vggh}; 6 | taskid = {1, 6, 11}; 7 | maxOverlapError = {0.5}; 8 | end 9 | 10 | methods (Test) 11 | function pr(test, detector, dataset, taskid, maxOverlapError) 12 | [~,ima_id] = ismember(dataset.tasks(taskid).ima, {dataset.images.name}); 13 | [~,imb_id] = ismember(dataset.tasks(taskid).imb, {dataset.images.name}); 14 | 15 | ima_p = dataset.images(ima_id).path; 16 | fa = detector(single(utls.imread_grayscale(ima_p))); 17 | 18 | imb_p = dataset.images(imb_id).path; 19 | fb = detector(single(utls.imread_grayscale(imb_p))); 20 | 21 | g = dataset.tasks(taskid); 22 | matchFrames = @(fa, fb, varargin) geom.ellipse_overlap_H(g, fa, fb, ... 23 | 'maxOverlapError', maxOverlapError, 'mode', 'descriptors', varargin{:}); 24 | 25 | methods = {'threshold', 'nn', 'nndistratio'}; 26 | results = struct(); 27 | results_vgg = legacy.vgg_desc_benchmark(g, ima_p, fa, ... 28 | imb_p, fb, 'maxOverlapError', maxOverlapError); 29 | for mi = 1:numel(methods) 30 | [results.(methods{mi}).res, results.(methods{mi}).info] = ... 31 | bench.descmatch(matchFrames, fa, fb, 'matchingStrategy', methods{mi}); 32 | end 33 | if 0 34 | figure(1); clf; 35 | colors = lines(numel(methods)); 36 | for mi = 1:numel(methods) 37 | plot(results.(methods{mi}).info.recall, results.(methods{mi}).info.precision, ... 38 | 'Color', colors(mi, :)); hold on; 39 | plot(results_vgg.(methods{mi}).recall, results_vgg.(methods{mi}).precision, ... 40 | 'Color', colors(mi, :), 'LineStyle', '--'); hold on; 41 | end 42 | drawnow; 43 | end 44 | 45 | for mi = 1:numel(methods) 46 | res = [results.(methods{mi}).info.recall; results.(methods{mi}).info.precision]; 47 | res_vgg = [results_vgg.(methods{mi}).recall; results_vgg.(methods{mi}).precision]; 48 | d = test.find_closest(res, res_vgg); 49 | % end-1 because the last operation point seems to be quite 50 | % imprecise... 51 | test.verifyTrue(all(d(1:end-1) < 1e-3)); 52 | end 53 | end 54 | 55 | end 56 | 57 | methods (Static) 58 | function dist = find_closest(da, db) 59 | dist = zeros(1, size(db, 2)); 60 | for dd = 1:size(db, 2) 61 | dist(dd) = min(sum(bsxfun(@minus, da, db(:, dd)).^2, 1)); 62 | end 63 | end 64 | end 65 | 66 | end 67 | -------------------------------------------------------------------------------- /matlab/+legacy/vgg_frames_benchmark.m: -------------------------------------------------------------------------------- 1 | function [ repScore, numCorresp, matchScore, numMatches ] = ... 2 | vgg_frames_benchmark( geom, ima_p, featsa, imb_p, featsb, varargin) 3 | % VGG_FRAMES_BENCHMARK Compute scores of image features 4 | % [REP, NUM_CORR, MATCHING, NUM_MATCHES] = VGG_FRAMES_BENCHMARK(GEOM, 5 | % IMAGEA_PATH, FRAMES_A, DESCRIPTORS_A, IMAGEB_PATH, FRAMES_B, 6 | % DESCRIPTORS_B) Compute repeatability REP and matching MATHICNG score 7 | % between FRAMES_A and FRAMES_B which are related by homography TF and 8 | % their descriptors DESCRIPTORS_A and DESCRIPTORS_B which were 9 | % extracted from images IMAGE_A and IMAGE_B. 10 | % 11 | % [REP, NUM_CORR] = obj.testFeatures(TF, IMAGEA_PATH, FRAMES_A, [], 12 | % IMAGEB_PATH, FRAMES_B, []) Compute only repeatability 13 | % between the the frames FRAMES_A and FRAMES_B. 14 | 15 | opts.maxOverlapError = 0.4; 16 | opts.commonPart = 1; 17 | opts = vl_argparse(opts, varargin); 18 | 19 | % Constants 20 | BIN_URL = 'http://www.robots.ox.ac.uk/~vgg/research/affine/det_eval_files/repeatability.tar.gz'; 21 | BIN_DIR = fullfile(vlb_path('vendor'), 'km_frames_benchmark'); 22 | % Make sure all supplementary files are present 23 | if ~exist(fullfile(BIN_DIR, 'repeatability.m'), 'file') 24 | untar(BIN_URL, BIN_DIR); 25 | end 26 | if exist(fullfile(BIN_DIR, ['c_eoverlap', mexext]), 'file') 27 | vlb_compile(); 28 | copyfile(... 29 | fullfile(vlb_path(), 'matlab', 'mex', ['vgg_compute_ellipse_overlap.', mexext]), ... 30 | fullfile(BIN_DIR, ['c_eoverlap.', mexext])); 31 | end 32 | fa = featsa.frames; da = single(featsa.descs); 33 | fb = featsb.frames; db = single(featsb.descs); 34 | 35 | if ~isempty(da) 36 | assert(size(fa, 2) == size(da, 2), 'Invalid number of frames/descriptors'); 37 | end 38 | if ~isempty(db) 39 | assert(size(fb, 2) == size(db, 2), 'Invalid number of frames/descriptors'); 40 | end 41 | 42 | tmpFile = tempname; 43 | ellb_p = [tmpFile 'ellB.txt']; ella_p = [tmpFile 'ellA.txt']; 44 | ella_f = utls.frame2ellipse(fa); ellb_f = utls.frame2ellipse(fb); 45 | legacy.vgg_features_write(ella_p, ella_f, double(da)); 46 | legacy.vgg_features_write(ellb_p, ellb_f, double(db)); 47 | tmpH_p = [tmpFile 'H.txt']; H = geom.H; save(tmpH_p, 'H', '-ASCII'); 48 | overlap_err_idx = round(opts.maxOverlapError*10); 49 | 50 | addpath(BIN_DIR); 51 | rehash; 52 | [~, tmprepScore, tmpnumCorresp, matchScore, numMatches, ~] = repeatability(... 53 | ella_p, ellb_p, tmpH_p, ima_p, imb_p, opts.commonPart); 54 | rmpath(BIN_DIR); 55 | 56 | repScore = tmprepScore(overlap_err_idx)./100; 57 | numCorresp = tmpnumCorresp(overlap_err_idx); 58 | matchScore = matchScore ./ 100; 59 | delete(ella_p); 60 | delete(ellb_p); 61 | delete(tmpH_p); 62 | -------------------------------------------------------------------------------- /python/dset/retrieval_dataset.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #-*- coding: utf-8 -*- 3 | #=========================================================== 4 | # File Name: retrieval_dataset.py 5 | # Author: Xu Zhang, Columbia University 6 | # Creation Date: 09-26-2017 7 | # Last Modified: Sat Mar 2 20:48:02 2019 8 | # 9 | # Description:Retrieval dataset template 10 | # 11 | # Copyright (C) 2018 Xu Zhang 12 | # All rights reserved. 13 | # 14 | # This file is made available under 15 | # the terms of the BSD license (see the COPYING file). 16 | #=========================================================== 17 | 18 | """ 19 | This module describe dataset template for image retrieval task 20 | """ 21 | 22 | import json 23 | import os 24 | from abc import ABCMeta, abstractmethod 25 | 26 | 27 | class RetrievalDataset(): 28 | """Sequence dataset for image retrieval 29 | 30 | Attributes 31 | ---------- 32 | 33 | name: str 34 | Name of the dataset 35 | root_dir: str 36 | Directory for the data 37 | download_flag: boolean 38 | Download data or not. Keep it False, unless you need to update the dataset. 39 | Data will automatically download, if there is no data in the root_dir. 40 | """ 41 | 42 | __metaclass__ = ABCMeta 43 | def __init__(self, name, root_dir = './datasets/', download_flag = False): 44 | self.name = name 45 | self.root_dir = root_dir 46 | self.load_dataset_info() 47 | 48 | if download_flag: 49 | self.download() 50 | 51 | try: 52 | os.stat(root_dir + self.name + '/') 53 | except: 54 | self.download() 55 | 56 | self.read_gallery_list() 57 | self.read_query_list() 58 | 59 | def load_dataset_info(self): 60 | """ 61 | Load data from hard disk 62 | """ 63 | try: 64 | with open('{}/dataset_info/{}.json'.format(self.root_dir, self.name)) as info_file: 65 | json_info = json.load(info_file) 66 | except: 67 | print('Cannot load database information file: {}dataset_info/{}.json'.format(self.root_dir, self.name)) 68 | return 69 | 70 | self.url = json_info['url'] 71 | 72 | @abstractmethod 73 | def download(self): 74 | """ 75 | Download data 76 | """ 77 | pass 78 | 79 | @abstractmethod 80 | def read_gallery_list(self): 81 | """ 82 | Load gallery image list 83 | """ 84 | pass 85 | 86 | @abstractmethod 87 | def read_query_list(self): 88 | """ 89 | Load query image list 90 | """ 91 | pass 92 | -------------------------------------------------------------------------------- /python/dset/vgg_dataset.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #-*- coding: utf-8 -*- 3 | #=========================================================== 4 | # File Name: vgg_dataset.py 5 | # Author: Xu Zhang, Columbia University 6 | # Creation Date: 09-26-2017 7 | # Last Modified: Sun Mar 3 16:56:21 2019 8 | # 9 | # Description: VGG dataset 10 | # 11 | # Copyright (C) 2018 Xu Zhang 12 | # All rights reserved. 13 | # 14 | # This file is made available under 15 | # the terms of the BSD license (see the COPYING file). 16 | #=========================================================== 17 | 18 | from dset.dataset import SequenceDataset 19 | import urllib 20 | import tarfile 21 | import os 22 | import sys 23 | 24 | if sys.version_info[0] >= 3: 25 | from urllib.request import urlretrieve 26 | else: 27 | from urllib import urlretrieve 28 | 29 | 30 | class vggh_Dataset(SequenceDataset): 31 | """ 32 | Oxford image matching 33 | """ 34 | 35 | def __init__(self,root_dir = './datasets/', download_flag = False): 36 | super(vggh_Dataset,self).__init__(name = 'vggh', root_dir = root_dir, download_flag = download_flag) 37 | 38 | def download(self): 39 | """ 40 | Download data 41 | """ 42 | try: 43 | os.stat(self.root_dir) 44 | except: 45 | os.mkdir(self.root_dir) 46 | 47 | try: 48 | os.stat('{}{}'.format(self.root_dir,self.name)) 49 | except: 50 | os.mkdir('{}{}'.format(self.root_dir,self.name)) 51 | 52 | for sequence_name in self.sequence_name_list: 53 | print("Download and extract {} sequence".format(sequence_name)) 54 | download_url = "{}{}.tar.gz".format(self.url, sequence_name) 55 | download_filename = "{}{}/{}.tar.gz".format(self.root_dir, self.name, sequence_name) 56 | try: 57 | os.stat('{}{}/{}'.format(self.root_dir,self.name,sequence_name)) 58 | except: 59 | os.mkdir('{}{}/{}'.format(self.root_dir,self.name,sequence_name)) 60 | 61 | try: 62 | urlretrieve(download_url,download_filename) 63 | tar = tarfile.open(download_filename) 64 | tar.extractall('{}{}/{}'.format(self.root_dir,self.name,sequence_name)) 65 | tar.close() 66 | os.remove(download_filename) 67 | except: 68 | print('Cannot download from {}.'.format(download_url)) 69 | 70 | def read_image_data(self): 71 | """ 72 | Load image data 73 | """ 74 | self.read_image_data_vggh() 75 | 76 | def read_link_data(self): 77 | """ 78 | Load link data 79 | """ 80 | self.read_link_data_vggh() 81 | 82 | -------------------------------------------------------------------------------- /python/test/test_bench_csv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # =========================================================== 4 | # File Name: test_bench_csv.py 5 | # Author: Xu Zhang, Columbia University 6 | # Creation Date: 01-25-2019 7 | # Last Modified: Mon Feb 18 11:50:07 2019 8 | # 9 | # Usage: python test_bench_csv.py 10 | # Description:test repeatability benchmark from csv feature. 11 | # 12 | # Copyright (C) 2018 Xu Zhang 13 | # All rights reserved. 14 | # 15 | # This file is made available under 16 | # the terms of the BSD license (see the COPYING file). 17 | # =========================================================== 18 | 19 | import sys 20 | sys.path.insert(0, '/home/xuzhang/project/Medifor/code/vlb/python/dset/') 21 | sys.path.insert(0, '/home/xuzhang/project/Medifor/code/vlb/python/features/') 22 | sys.path.insert(0, '/home/xuzhang/project/Medifor/code/vlb/python/bench/') 23 | 24 | import Utils 25 | import MatchingScoreBench 26 | import repBench 27 | import my_surf 28 | import vlsift_load_matlab 29 | import vgg_dataset 30 | 31 | 32 | if __name__ == "__main__": 33 | #define dataset 34 | vggh = vgg_dataset.vggh_Dataset() 35 | 36 | #define feature 37 | vlsift_load_matlab = vlsift_load_matlab.vlsift_load_matlab() 38 | my_surf = my_surf.my_surf() 39 | 40 | # repeatability test 41 | rep_bench = repBench.repBench() 42 | rep_result_surf = rep_bench.evaluate( 43 | vggh, my_surf, use_cache=False, save_result=True) 44 | rep_result_matlab = rep_bench.evaluate( 45 | vggh, vlsift_load_matlab, use_cache=False, save_result=True) 46 | #merge result and show 47 | rep_result = [rep_result_matlab, rep_result_surf] 48 | for result_term in rep_result[0]['result_term_list']: 49 | Utils.print_result(rep_result, result_term) 50 | Utils.save_result(rep_result, result_term) 51 | 52 | #match score test 53 | ms_bench = MatchingScoreBench.MatchingScoreBench() 54 | ms_result_surf = ms_bench.evaluate( 55 | vggh, my_surf, use_cache=False, save_result=True) 56 | ms_result_matlab = ms_bench.evaluate( 57 | vggh, vlsift_load_matlab, use_cache=False, save_result=True) 58 | #merge result and show 59 | ms_result = [ms_result_matlab, ms_result_surf] 60 | for result_term in ms_result[0]['result_term_list']: 61 | Utils.print_result(ms_result, result_term) 62 | Utils.save_result(ms_result, result_term) 63 | 64 | #show result for different sequences 65 | for sequence in vggh.sequence_name_list: 66 | for result_term in ms_result[0]['result_term_list']: 67 | Utils.print_sequence_result(ms_result, sequence, result_term) 68 | Utils.save_sequence_result(ms_result, sequence, result_term) 69 | -------------------------------------------------------------------------------- /matlab/vlb.m: -------------------------------------------------------------------------------- 1 | function [res, info] = vlb(cmd, varargin) 2 | %VLB VLBenchmarks command line interface 3 | % `VLB help` 4 | % Print this help string. 5 | % `VLB help COMMAND` 6 | % Print a help string for a COMMAND. 7 | % 8 | % `VLB view` Various visualisations 9 | % `VLB imagelist` Create image list and feature list 10 | % 11 | % `VLB detect` 12 | % `VLB extract` 13 | % `VLB describe` 14 | % 15 | % `VLB detrep` 16 | % `VLB detmatch` 17 | % `VLB descmatch` 18 | 19 | 20 | 21 | % Copyright (C) 2016-2017 Karel Lenc 22 | % All rights reserved. 23 | % 24 | % This file is part of the VLFeat library and is made available under 25 | % the terms of the BSD license (see the COPYING file). 26 | vlb_setup(); 27 | usage = @(varargin) utls.helpbuilder(varargin{:}, 'name', 'vlb'); 28 | 29 | cmds = struct(); 30 | cmds.view = struct('fun', @vlb_view, 'help', ''); 31 | cmds.imagelist = struct('fun', @vlb_imagelist, 'help', ''); 32 | % Generate features 33 | cmds.detect = struct('fun', @vlb_detect, 'help', ''); 34 | cmds.extract = struct('fun', @vlb_extract, 'help', ''); 35 | cmds.describe = struct('fun', @vlb_describe, 'help', ''); 36 | % Benchmarks 37 | cmds.detrep = struct('fun', ... 38 | @(varargin) vlb_evalfeatures(@bench.detrep, varargin{:}), ... 39 | 'help', @(a) fprintf(['VLB DETREP Evaluate detector repeatability.\n',... 40 | ' VLB DETREP imdb featsname\n\n'])); 41 | cmds.detrepthr = struct('fun', ... 42 | @(varargin) vlb_evalfeatures(@bench.detrepthr, varargin{:}), ... 43 | 'help', @(a) fprintf(['VLB DETREPTHR Evaluate detector repeatability over all thresholds.\n',... 44 | ' VLB DETREPTHR imdb featsname\n\n'])); 45 | cmds.detmatch = struct('fun', ... 46 | @(varargin) vlb_evalfeatures(@bench.detmatch, varargin{:}), ... 47 | 'help', @(a) fprintf(['VLB DETMATCH Evaluate detector matching score.\n',... 48 | ' VLB DETMATCH imdb featsname\n\n'])); 49 | cmds.descmatch = struct('fun', ... 50 | @(varargin) vlb_evalfeatures(@bench.descmatch, varargin{:}), ... 51 | 'help', @(a) fprintf(['VLB DESCMATCH Evaluate descriptor matching score.\n',... 52 | ' VLB DESCMATCH imdb featsname\n\n'])); 53 | 54 | % The last command is always help 55 | if isempty(varargin), varargin = {''}; end 56 | cmds.help = struct('fun', @(varargin) usage(cmds, varargin{:})); 57 | 58 | if nargin < 1, cmd = nan; end 59 | if ~ischar(cmd), usage(cmds, ''); return; end 60 | if strcmp(cmd, 'commands'), res = cmds; return; end; 61 | 62 | if isfield(cmds, cmd) && ~isempty(cmds.(cmd).fun) 63 | if nargout == 1 64 | res = cmds.(cmd).fun(varargin{:}); 65 | elseif nargout == 2 66 | [res, info] = cmds.(cmd).fun(varargin{:}); 67 | else 68 | cmds.(cmd).fun(varargin{:}); 69 | end 70 | else 71 | error('Invalid command. Run help for list of valid commands.'); 72 | end 73 | 74 | end 75 | 76 | -------------------------------------------------------------------------------- /python/features/cyvlsift_official.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module is a warpper for cyvlsift 3 | """ 4 | 5 | import numpy as np 6 | import cv2 7 | import cyvlfeat 8 | import features.feature_utils 9 | from features.DetectorDescriptorTemplate import DetectorAndDescriptor 10 | 11 | 12 | class cyvlsift_official(DetectorAndDescriptor): 13 | """A warpper for cyvlsift. 14 | 15 | Attributes 16 | ---------- 17 | 18 | peak_thresh: float 19 | Peak threshold for feature detector 20 | 21 | """ 22 | def __init__(self, peak_thresh=0.0): 23 | super( 24 | cyvlsift_official, 25 | self).__init__( 26 | name='cyvlsift_official', 27 | is_detector=True, 28 | is_descriptor=True, 29 | is_both=True) 30 | self.peak_thresh = peak_thresh 31 | 32 | def detect_feature(self, image): 33 | """ 34 | Extract feature from image. 35 | 36 | :param image: The image 37 | :type image: array 38 | :returns: feature 39 | :rtype: array(n*d) 40 | """ 41 | new_image = image.astype(np.float32) 42 | new_image = new_image/255.0 43 | new_image = features.feature_utils.all_to_gray(new_image) 44 | feature = cyvlfeat.sift.sift( 45 | new_image, peak_thresh=self.peak_thresh, magnification=5.0) 46 | return feature 47 | 48 | def extract_descriptor(self, image, feature): 49 | """ 50 | Extract descriptor from image with feature. 51 | 52 | :param image: The image 53 | :type image: array 54 | :param feature: The feature output by detector 55 | :type feature: array 56 | :returns: descriptor 57 | :rtype: array(n*d) 58 | """ 59 | new_image = image.astype(np.float32) 60 | new_image = new_image/255.0 61 | new_image = features.feature_utils.all_to_gray(new_image) 62 | feature, descriptor = cyvlfeat.sift.sift( 63 | new_image, peak_thresh=self.peak_thresh, frames=feature, magnification=5.0, compute_descriptor=True) 64 | return descriptor 65 | 66 | def extract_all(self, image): 67 | """ 68 | Extract feature and descriptor from image. 69 | 70 | :param image: The image 71 | :type image: array 72 | :returns: feature, descriptor 73 | :rtype: array(n*d) 74 | """ 75 | 76 | new_image = image.astype(np.float32) 77 | new_image = new_image/255.0 78 | new_image = features.feature_utils.all_to_gray(new_image) 79 | feature, descriptor_vector = cyvlfeat.sift.sift( 80 | new_image, peak_thresh=self.peak_thresh, magnification=5.0, compute_descriptor=True) 81 | return feature, descriptor_vector 82 | -------------------------------------------------------------------------------- /matlab/+bench/detrepthr.m: -------------------------------------------------------------------------------- 1 | function [ res, info ] = detrepthr( matchFrames, featsa, featsb, varargin ) 2 | % VLB_THR_REPEATABILITY Compute a repetability over a set of thresholds 3 | opts.normFactor = 'b'; 4 | opts = vl_argparse(opts, varargin); 5 | fa = featsa.frames; fb = featsb.frames; 6 | fsca = featsa.detresponses; fscb = featsb.detresponses; 7 | 8 | res = struct('repeatability', [], 'numCorresp', [], 'numDets',[]); 9 | info = struct('geomMatches', zeros(2, 0)); 10 | if isempty(fa) || isempty(fb), return; end 11 | if ~iscell(fa), fa = {fa}; end; if ~iscell(fsca), fsca = {fsca}; end; 12 | if ~iscell(fb), fb = {fb}; end; if ~iscell(fscb), fscb = {fscb}; end 13 | if ~iscell(matchFrames), matchFrames = {matchFrames}; end; 14 | 15 | if numel(fa) == 1 && numel(fb) > 1 16 | fa = repmat(fa, 1, numel(fb)); 17 | fsca = repmat(fsca, 1, numel(fb)); 18 | end 19 | assert(numel(matchFrames) == numel(fb)); 20 | assert(numel(fa) == numel(fb)); 21 | assert(numel(fsca) == numel(fb)); 22 | assert(numel(fscb) == numel(fb)); 23 | 24 | arr = cell(1, numel(fa)); info = cell(1, numel(fa)); 25 | for ci = 1:numel(fa) 26 | [tcorr, tcorr_score, info{ci}] = matchFrames{ci}(fa{ci}, fb{ci}); 27 | info{ci}.tcorr = tcorr; info{ci}.corr_score = tcorr_score; 28 | fa_num = sum(info{ci}.fa_valid); 29 | fb_num = sum(info{ci}.fb_valid); 30 | %if isempty(tcorr), return; end; 31 | fsca{ci} = fsca{ci}(:, info{ci}.fa_valid); 32 | fscb{ci} = fscb{ci}(:, info{ci}.fb_valid); 33 | tcorr_fsc = min([fsca{ci}(tcorr(1, :)); fscb{ci}(tcorr(2, :))], [], 1); 34 | 35 | % Sort the edgest by decrasing score 36 | [tcorr_fsc, perm] = sort(tcorr_fsc, 'descend'); 37 | tcorr = tcorr(:, perm); 38 | % Approximate the best bipartite matching 39 | matches = vlb_greedy_matching(fa_num, fb_num, tcorr'); 40 | info{ci}.geomMatches = matches; 41 | 42 | tcorr_matched = false(1, size(tcorr, 2)); 43 | tcorr_matched(matches(2, matches(2, :)>0)) = true; 44 | %arr = [iscorrect, isdetection, score] 45 | % matches and detections put side by side to be able to compute the 46 | % number of detections per threshold 47 | arr{ci} = [tcorr_matched; zeros(1, numel(tcorr_matched)); tcorr_fsc]; 48 | if strcmp(opts.normFactor, 'minab') 49 | if numel(fsca{ci}) > numel(fscb{ci}) 50 | opts.normFactor = 'b'; 51 | else 52 | opts.normFactor = 'a'; 53 | end 54 | end 55 | switch opts.normFactor 56 | case 'a' 57 | arr{ci} = [arr{ci} [zeros(1, size(fsca{ci}, 2)); ones(1, size(fsca{ci}, 2)); fsca{ci}]]; 58 | case 'b' 59 | arr{ci} = [arr{ci} [zeros(1, size(fscb{ci}, 2)); ones(1, size(fscb{ci}, 2)); fscb{ci}]]; 60 | end 61 | end 62 | 63 | arr = cell2mat(arr); info = cell2mat(info); 64 | [~, perm] = sort(arr(3, :), 'descend'); 65 | arr = arr(:, perm); 66 | nmatches = cumsum(arr(1, :)); 67 | ndet = cumsum(arr(2, :)) + 1; 68 | rep = nmatches ./ ndet; 69 | 70 | res.repeatability = rep; 71 | res.numMatches = nmatches; 72 | res.numDets = ndet; -------------------------------------------------------------------------------- /matlab/vlb_evalfeatures.m: -------------------------------------------------------------------------------- 1 | function [scores, info] = vlb_evalfeatures( benchFun, imdb, feats, varargin ) 2 | %VLB_EVALFEATURES Run local features evaluation 3 | % VLB_EVALFEATURES benchfun imdb feats 4 | 5 | % Copyright (C) 2017 Karel Lenc 6 | % All rights reserved. 7 | % 8 | % This file is part of the VLFeat library and is made available under 9 | % the terms of the BSD license (see the COPYING file). 10 | opts.override = false; 11 | opts.loadOnly = false; 12 | 13 | imdb = dset.factory(imdb); 14 | if isstruct(feats) 15 | featsname = feats.name; 16 | % Allow a feats configuration to set the override parameter 17 | if isfield(feats, 'override') 18 | opts.override = feats.override; 19 | end 20 | else 21 | featsname = feats; 22 | end 23 | 24 | allargs = varargin; 25 | opts.benchName = strrep(func2str(benchFun), 'bench.', ''); 26 | opts.taskids = 1:numel(imdb.tasks); 27 | [opts, varargin] = vl_argparse(opts, varargin); 28 | 29 | scoresdir = vlb_path('scores', imdb, featsname, opts.benchName); 30 | vl_xmkdir(scoresdir); 31 | scores_path = fullfile(scoresdir, 'results.csv'); 32 | info_path = fullfile(scoresdir, 'results.mat'); 33 | res_exists = exist(scores_path, 'file'); 34 | if nargout > 1 35 | res_exists = res_exists && exist(info_path, 'file'); 36 | end 37 | if ~opts.override && res_exists 38 | scores = readtable(scores_path, 'delimiter', ','); 39 | if nargout > 1, info = load(info_path); end 40 | fprintf('Results loaded from %s.\n', scores_path); 41 | return; 42 | end 43 | if opts.loadOnly 44 | warning('Results %s not found.', scores_path); 45 | scores = table(); info = struct(); return; 46 | end 47 | 48 | fprintf('Running %d tasks of %s on %s for %s features.\n', ... 49 | numel(opts.taskids), opts.benchName, imdb.name, featsname); 50 | status = utls.textprogressbar(numel(imdb.tasks), 'updatestep', 1); 51 | scores = cell(1, numel(opts.taskids)); info = cell(1, numel(opts.taskids)); 52 | for ti = 1:numel(opts.taskids) 53 | task = imdb.tasks(opts.taskids(ti)); 54 | fa = utls.features_get(imdb, featsname, task.ima); 55 | fb = utls.features_get(imdb, featsname, task.imb); 56 | matchGeom = imdb.matchFramesFun(task); % Returns a functor 57 | [scores{ti}, info{ti}] = benchFun(matchGeom, fa, fb, varargin{:}); 58 | scores{ti}.benchmark = opts.benchName; 59 | scores{ti}.features = featsname; 60 | scores{ti}.dataset = imdb.name; 61 | scores{ti}.sequence = task.sequence; 62 | scores{ti}.ima = task.ima; 63 | scores{ti}.imb = task.imb; 64 | info{ti}.args = {allargs}; 65 | status(ti); 66 | end 67 | 68 | scores = struct2table(cell2mat(scores), 'AsArray', true); 69 | try 70 | writetable(scores, scores_path); 71 | info = cell2mat(info); 72 | save(info_path, 'info'); 73 | catch e 74 | fprintf('Cleaning up %s due to error', e.message); 75 | if exist(scores_path, 'file'), delete(scores_path); end 76 | if exist(info_path, 'file'), delete(info_path); end 77 | throw(e); 78 | end 79 | 80 | end 81 | 82 | -------------------------------------------------------------------------------- /matlab/vlb_describe.m: -------------------------------------------------------------------------------- 1 | function dest_feats_name = vlb_describe(imdb, featsname, descriptor, varargin) 2 | %VLB_DESCRIBE Compute descriptors for a given features 3 | % VLB_DESCRIBE imdb featsname descriptor 4 | % 5 | % Based on descriptor type, uses either full images and a set of frames, 6 | % or computes descriptors using extracted patches. 7 | 8 | % Copyright (C) 2016-2017 Karel Lenc 9 | % All rights reserved. 10 | % 11 | % This file is part of the VLFeat library and is made available under 12 | % the terms of the BSD license (see the COPYING file). 13 | 14 | import features.*; 15 | 16 | opts.imgExt = '.png'; 17 | opts.override = false; 18 | opts.imids = []; 19 | [opts, varargin] = vl_argparse(opts, varargin); 20 | 21 | imdb = dset.factory(imdb); 22 | if isstruct(featsname), featsname = featsname.name; end; 23 | if iscell(featsname), featsname = fullfile(featsname); end; 24 | impaths = {imdb.images(opts.imids).path}; 25 | imnames = {imdb.images(opts.imids).name}; 26 | descriptor = features.factory('desc', descriptor, varargin{:}); 27 | 28 | dets_dir = vlb_path('features', imdb, struct('name', featsname)); 29 | assert(isdir(dets_dir), 'Cannot find frames for %s - %s', ... 30 | imdb.name, featsname); 31 | 32 | dest_feats_name = fullfile(featsname, descriptor.name); 33 | desc_dest_dir = vlb_path('features', imdb, dest_feats_name); 34 | vl_xmkdir(desc_dest_dir); 35 | 36 | fprintf('Computing descriptor `%s` for %d images of features `%s` from a dset `%s`.\n', ... 37 | descriptor.name, numel(impaths), featsname, imdb.name); 38 | fprintf('Resulting features are going to be stored in:\n%s.\n', desc_dest_dir); 39 | status = utls.textprogressbar(numel(impaths), 'startmsg', ... 40 | sprintf('Computing %s ', descriptor.name), 'updatestep', 1); 41 | for si = 1:numel(impaths) 42 | imname = imnames{si}; 43 | feats_path = fullfile(desc_dest_dir, imname); 44 | feats = utls.features_load(feats_path, 'checkOnly', true); 45 | if ~isempty(feats) && ~opts.override, status(si); continue; end 46 | 47 | dets_path = fullfile(dets_dir, imname); 48 | det_feats = utls.features_load(dets_path); 49 | if isempty(det_feats) || ~isfield(det_feats, 'frames') 50 | error('Frames in %s not found.', dets_path); 51 | end 52 | 53 | switch descriptor.describes 54 | case 'patches' 55 | patches_path = fullfile(vlb_path('patches', imdb, ... 56 | struct('name', featsname)), [imname, '.png']); 57 | if ~exist(patches_path, 'file') 58 | error('Patches %s not found.', patches_path); 59 | end 60 | [patches, scalingFactor] = utls.patches_load(patches_path); 61 | desc_feats = descriptor.fun(patches); 62 | desc_feats.scalingFactor = scalingFactor; 63 | case 'frames' 64 | im = imread(impaths{si}); 65 | desc_feats = descriptor.fun(im, det_feats); 66 | end 67 | feats = vl_override(det_feats, desc_feats); 68 | utls.features_save(feats_path, feats); 69 | status(si); 70 | end 71 | 72 | end 73 | 74 | -------------------------------------------------------------------------------- /matlab/+dset/webcam.m: -------------------------------------------------------------------------------- 1 | function [ imdb ] = webcam( varargin ) 2 | 3 | % Copyright (C) 2017 Karel Lenc 4 | % All rights reserved. 5 | % 6 | % This file is part of the VLFeat library and is made available under 7 | % the terms of the BSD license (see the COPYING file). 8 | 9 | DATADIR = 'WebcamRelease'; 10 | NUMSEQUENCES = 6; 11 | 12 | opts.url = 'https://documents.epfl.ch/groups/c/cv/cvlab-unit/www/data/keypoints/WebcamRelease.tar.gz'; 13 | opts.rootDir = fullfile(vlb_path('datasets'), 'webcam'); 14 | opts.matchFramesFun = @(g) ... 15 | @(fa, fb, varargin) geom.ellipse_overlap_H(g, fa, fb, ... 16 | 'maxOverlapError', 0.5, varargin{:}); 17 | opts.impath = 'image_color'; 18 | opts = vl_argparse(opts, varargin); 19 | 20 | utls.provision(opts.url, opts.rootDir); 21 | 22 | dataDir = fullfile(opts.rootDir, DATADIR); 23 | getImPath = @(seq, imname) fullfile(dataDir, seq, 'test', opts.impath, imname); 24 | sequences = sort(utls.listdirs(dataDir)); 25 | assert(numel(sequences) == NUMSEQUENCES, ... 26 | 'Invalid number of sequences found.'); 27 | 28 | imdb.images = {}; 29 | imdb.tasks = {}; 30 | rfile = @(path) strtrim(strsplit(strtrim(fileread(path)), '\n')); 31 | 32 | imi = 1; lastim = 0; 33 | for sIdx = 1:numel(sequences) 34 | sequence = sequences{sIdx}; 35 | testimgs = rfile(fullfile(dataDir, sequence, 'test', 'test_imgs.txt')); 36 | valimgs = rfile(fullfile(dataDir, sequence, 'test', 'validation_imgs.txt')); 37 | allimgs = [valimgs, testimgs]; 38 | istest = [false(1, numel(valimgs)), true(1, numel(valimgs))]; 39 | [allimgs_u, ui, ic] = unique(allimgs); 40 | istest = istest(ui); 41 | for imi_l = 1:numel(allimgs_u) 42 | [~, filename, ext] = fileparts(allimgs_u{imi_l}); 43 | imPath = getImPath(sequence, [filename, ext]); 44 | assert(exist(imPath, 'file') == 2, 'Image %s not found.', imPath); 45 | imdb.images{imi} = struct('id', imi, ... 46 | 'name', sprintf('%s-%s', sequence, filename), 'path', imPath, ... 47 | 'sequence', sequence, 'sequence_id', sIdx, 'istest', istest(imi_l), 'isval', ~istest(imi_l), ... 48 | 'imsize', utls.get_image_size(imPath)); 49 | imi = imi + 1; 50 | end 51 | pidx = numel(allimgs)/2; 52 | for pi = 1:pidx 53 | ima = imdb.images{ic(pi) + lastim}; 54 | imb = imdb.images{ic(pi+pidx) + lastim}; 55 | assert(strcmp(ima.sequence, imb.sequence)); 56 | imdb.tasks{end+1} = struct(... 57 | 'ima', ima.name, 'imb', imb.name, ... 58 | 'ima_id', ima.id, 'imb_id', imb.id, 'H', eye(3), ... 59 | 'ima_size', ima.imsize, 'imb_size', imb.imsize, ... 60 | 'istest', ima.istest, 'isval', imb.isval, 'sequence', sequence, ... 61 | 'sequence_id', sIdx, 'description', struct('impair', [pi, pi+pidx])); 62 | end 63 | lastim = imi - 1; 64 | end 65 | 66 | imdb.images = cell2mat(imdb.images); 67 | imdb.tasks = cell2mat(imdb.tasks); 68 | imdb.name = 'webcam'; 69 | imdb.matchFramesFun = opts.matchFramesFun; 70 | imdb.geometry = 'homography'; 71 | imdb.rootdir = opts.rootDir; 72 | 73 | end 74 | 75 | 76 | -------------------------------------------------------------------------------- /examples/detbench.m: -------------------------------------------------------------------------------- 1 | % Setup and compile vlb, if run for the first time 2 | run(fullfile(fileparts(mfilename('fullpath')), '..', 'matlab', 'vlb_setup.m')); 3 | if ~exist(['vlb_greedy_matching.', mexext], 'file'), vlb_compile(); end; 4 | 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | %% Basic Commands 7 | 8 | imdb = dset.vggh(); 9 | figure(1); clf; 10 | vlb('view', 'matchpair', imdb, 1); 11 | 12 | figure(2); clf; 13 | vlb('view', 'matchpair', imdb, 1:5); 14 | 15 | %% Run a detector and show detection 16 | feat = vlb('detect', imdb, 'vlsift'); 17 | figure(3); clf; 18 | vlb('view', 'detections', imdb, feat, 1); 19 | 20 | %% Extract and visualise patches 21 | vlb('extract', imdb, 'vlsift'); 22 | figure(3); clf; 23 | vlb('view', 'patches', imdb, feat, 1); 24 | 25 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 26 | %% Repeatability example 27 | 28 | feats = {}; 29 | feats{end+1} = vlb('detect', imdb, 'vlsift'); 30 | %MACOS doesn't support hesaff and haraff 31 | if ~ismac 32 | feats{end+1} = vlb('detect', imdb, 'vggaff', 'detArgs', {'detector', 'hesaff'}); 33 | feats{end+1} = vlb('detect', imdb, 'vggaff', 'detArgs', {'detector', 'haraff'}); 34 | end 35 | res = cellfun(@(f) vlb('detrep', imdb, f), feats, 'Uni', false); 36 | res = vertcat(res{:}); 37 | 38 | %% Display average repeatability per detector 39 | display(varfun(@mean, res, 'InputVariables', 'repeatability',... 40 | 'GroupingVariables', 'features')); 41 | 42 | %% Plot the results 43 | 44 | figure(10); clf; 45 | subplot(1,2,1); 46 | vlb('view', 'sequencescores', 'detrep', imdb, feats, 'graf', 'repeatability'); 47 | title('Graph Repetability'); 48 | subplot(1,2,2); 49 | vlb('view', 'sequencescores', 'detrep', imdb, feats, 'graf', 'numCorresp'); 50 | 51 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 52 | %% Matching score example 53 | 54 | feats = {}; 55 | feats{end+1} = vlb('detect', imdb, 'vlsift'); 56 | %MACOS doesn't support hesaff and haraff 57 | if ~ismac 58 | feats{end+1} = vlb('detect', imdb, 'vggaff', 'detArgs', {'detector', 'hesaff'}); 59 | feats{end} = vlb('describe', imdb, feats{end}, 'vggdesc'); 60 | feats{end+1} = vlb('detect', imdb, 'vggaff', 'detArgs', {'detector', 'haraff'}); 61 | feats{end} = vlb('describe', imdb, feats{end}, 'vggdesc'); 62 | end 63 | 64 | res = cellfun(@(f) vlb('detmatch', imdb, f), feats, 'Uni', false); 65 | res = vertcat(res{:}); 66 | 67 | %% Show the average matching score per detector 68 | display(varfun(@mean, res, 'InputVariables', 'repeatability',... 69 | 'GroupingVariables', 'features')); 70 | 71 | %% Plot the results in a graph 72 | figure(11); clf; 73 | subplot(2,2,1); 74 | vlb('view', 'sequencescores', 'detmatch', imdb, feats, 'graf', 'matchingScore'); 75 | title('Graph Matching Score'); 76 | subplot(2,2,2); 77 | vlb('view', 'sequencescores', 'detmatch', imdb, feats, 'graf', 'numMatches'); 78 | 79 | %% View matched frames 80 | figure(21); clf; 81 | vlb('view', 'matches', imdb, feats{1}, 'detmatch', 3); 82 | -------------------------------------------------------------------------------- /python/bench/matrixNormBench.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # =========================================================== 4 | # File Name: matrixNormBench.py 5 | # Author: Alex Butenko, Georiga Institute of Technology 6 | # Creation Date: 06-01-2019 7 | # Last Modified: Sat Jun 1 21:46:25 2019 8 | # 9 | # Description: Frobenius Norm Difference benchmark 10 | # 11 | # Copyright (C) 2019 Alex Butenko 12 | # All rights reserved. 13 | # 14 | # This file is made available under 15 | # the terms of the BSD license (see the COPYING file). 16 | # =========================================================== 17 | 18 | 19 | """ 20 | This module describe benchmark for Frobenius norm Difference. 21 | """ 22 | 23 | import numpy as np 24 | import math 25 | from bench.VerificationBenchmarkTemplate import VerificationBenchmark 26 | 27 | import bench.geom as geom 28 | 29 | class matrixNormBench(VerificationBenchmark): 30 | """ 31 | EpiConstraint Template 32 | Return repeatability score and number of correspondence 33 | """ 34 | def __init__(self, tmp_feature_dir='./data/features/', 35 | result_dir='./python_scores/'): 36 | super(matrixNormBench, self).__init__(name='InlierPrecision', result_dir=result_dir) 37 | self.bench_name = 'diffFrobenius ' 38 | self.test_name = 'diffFrobenius' 39 | 40 | def evaluate_unit(self, data_dict): 41 | """ 42 | Single evaluation unit. Given and estimated F matrix, find the Frobenius norm 43 | of the the difference from the true F 44 | 45 | :param data_dict: dictionary containing necessary data 46 | :type data_dict: dict 47 | 48 | """ 49 | est_F = data_dict['est_F'] 50 | true_F = data_dict['F'] 51 | 52 | # Calculate F Matrix from E 53 | if est_F is None: 54 | est_F = geom.get_F_matrix_from_E(data_dict['est_E'], 55 | data_dict['K1'], 56 | data_dict['K2']) 57 | 58 | frobNorm = np.linalg.norm(true_F - est_F) 59 | 60 | return frobNorm 61 | 62 | def evaluate(self, dataset, verifier, use_cache=True, 63 | save_result=True): 64 | """ 65 | Main function to call the evaluation wrapper. It could be different for different evaluation 66 | 67 | :param dataset: Dataset to compare 68 | :type dataset: verification_dataset 69 | :param verifier: Verifier used to verify 70 | :type verifier: VerifierTemplate 71 | :param use_cache: Load cached feature and result or not 72 | :type use_cache: boolean 73 | :param save_result: Save result or not 74 | :type save_result: boolean 75 | :returns: result 76 | :rtype: dict 77 | """ 78 | result = self.evaluate_warpper(dataset, verifier, ['diffFrobenius'], 79 | use_cache=use_cache, save_result=save_result) 80 | 81 | result['bench_name'] = self.bench_name 82 | return result 83 | -------------------------------------------------------------------------------- /matlab/+bench/detrep.m: -------------------------------------------------------------------------------- 1 | function [ scores, info ] = detrep( matchFrames, feats_a, feats_b, varargin ) 2 | % VLB_REPEATABILITY Compute repeatability of given image features 3 | % [SCORES] = VLB_REPEATABILITY(MATCH, FRAMES_A, FRAMES_B) 4 | % Computes the repeatability between frames FRAMES_A and FRAMES_B 5 | % NUM_MATHCES is number of matches which is calcuated 6 | % according to object settings. 7 | % 8 | % [SCORE, NUM_MATCHES, REPR_FRAMES, MATCHES] = 9 | % obj.testFeatures(...) returns cell array REPR_FRAMES which 10 | % contains reprojected and eventually cropped frames in 11 | % format: 12 | % 13 | % REPR_FRAMES = {CFRAMES_A,CFRAMES_B,REP_CFRAMES_A,REP_CFRAMES_B} 14 | % 15 | % where CFRAMES_A are (cropped) frames detected in the IMAGEAPATH 16 | % image REP_CFRAMES_A are CFRAMES_A reprojected to the IMAGEBPATH 17 | % image using homography TF. Same hold for frames from the secons 18 | % image CFRAMES_B and REP_CFRAMES_B. 19 | % MATCHES is an array of size [size(CFRAMES_A),1]. Two frames are 20 | % CFRAMES_A(k) and CFRAMES_B(l) are matched when MATCHES(k) = l. 21 | % When frame CFRAMES_A(k) is not matched, MATCHES(k) = 0. 22 | 23 | opts.normFactor = 'minab'; 24 | opts.topn = inf; 25 | opts.forceTopn = true; 26 | opts.magnifyFrames = []; 27 | [opts, varargin] = vl_argparse(opts, varargin); 28 | 29 | info.geom = []; 30 | info.tcorr = zeros(2, 0); info.corr_score = zeros(1, 0); 31 | info.geomMatches = zeros(2, 0); info.matches = zeros(1, 0); 32 | scores = struct('repeatability', 0, 'numCorresp', 0); 33 | if isempty(feats_a.frames) || isempty(feats_b.frames), return; end 34 | if ~isinf(opts.topn) && isfield(feats_a, 'detresponses') && ... 35 | isfield(feats_b, 'detresponses') 36 | feats_a = utls.topnframes(feats_a, opts.topn); 37 | feats_b = utls.topnframes(feats_b, opts.topn); 38 | elseif ~isinf(opts.topn) && opts.forceTopn 39 | error('Features do not have `detresponses` fields for a topn.'); 40 | end 41 | if ~isempty(opts.magnifyFrames) 42 | feats_a.frames = utls.frame_magnify_scale(feats_a.frames, opts.magnifyFrames); 43 | feats_b.frames = utls.frame_magnify_scale(feats_b.frames, opts.magnifyFrames); 44 | end 45 | feats_a.descs = []; feats_b.descs = []; 46 | [tcorr, corr_score, info.geom] = matchFrames(feats_a.frames, feats_b.frames, varargin{:}); 47 | info.tcorr = tcorr; info.corr_score = corr_score; 48 | fa_num = sum(info.geom.fa_valid); fb_num = sum(info.geom.fb_valid); 49 | if isempty(tcorr), return; end 50 | 51 | % Sort the edgest by decrasing score 52 | [~, perm] = sort(corr_score, 'descend'); 53 | tcorr_s= tcorr(:, perm); 54 | % Approximate the best bipartite matching 55 | matches = vlb_greedy_matching(fa_num, fb_num, tcorr_s'); 56 | matches = matches(1, :); 57 | info.matches = matches; 58 | 59 | % Compute the score 60 | nc = sum(matches ~= 0); 61 | switch opts.normFactor 62 | case 'minab' 63 | rep = nc / min(fa_num, fb_num); 64 | case 'a' 65 | rep = nc / fa_num; 66 | case 'b' 67 | rep = nc / fb_num; 68 | otherwise 69 | error('Invalid `normFactor`.'); 70 | end 71 | scores = struct('repeatability', rep, 'numCorresp', nc); -------------------------------------------------------------------------------- /python/doc/test_match.rst: -------------------------------------------------------------------------------- 1 | Test Feature and Descripor Matching Benchmark 2 | ========================================================= 3 | This is how to run the feature matching (repeatability) and descriptor matching (matching score) benchmark. 4 | 5 | Repeatablity Benchmark: 6 | 7 | .. code-block:: python 8 | 9 | # Define retrieval benchmark 10 | rep_bench = bench.repBench.repBench() 11 | 12 | # Define feature 13 | vlsift_py = features.cyvlsift_official.cyvlsift_official() 14 | 15 | # Define dataset 16 | vggh = dset.vgg_dataset.vggh_Dataset() 17 | 18 | # Do the evaluation 19 | rep_result_py = rep_bench.evaluate( 20 | vggh, vlsift_py, use_cache=False, save_result=True) 21 | 22 | # Make the results from different detectors as a list. 23 | # (Only one here, but you can add more) 24 | rep_result = [rep_result_py] 25 | 26 | # Show the result 27 | for result_term in rep_result[0]['result_term_list']: 28 | bench.Utils.print_result(rep_result, result_term) 29 | bench.Utils.save_result(rep_result, result_term) 30 | 31 | #Show result for different sequences 32 | for sequence in vggh.sequence_name_list: 33 | for result_term in rep_result[0]['result_term_list']: 34 | bench.Utils.print_sequence_result(rep_result, sequence, result_term) 35 | bench.Utils.save_sequence_result(rep_result, sequence, result_term) 36 | 37 | 38 | Matching score Benchmark: 39 | 40 | .. code-block:: python 41 | 42 | # Define matching score benchmark 43 | ms_bench = bench.MatchingScoreBench.MatchingScoreBench() 44 | 45 | # Define feature 1 46 | vlsift_py = features.cyvlsift_official.cyvlsift_official() 47 | 48 | # Define feature 2 49 | vlsift_load_matlab = features.vlsift_load_matlab.vlsift_load_matlab() 50 | 51 | # Define dataset 52 | vggh = dset.vgg_dataset.vggh_Dataset() 53 | 54 | # Do the evaluation 55 | ms_result_py = ms_bench.evaluate( 56 | vggh, vlsift_py, use_cache=True, save_result=True) 57 | 58 | ms_result_matlab = ms_bench.evaluate( 59 | vggh, vlsift_load_matlab, use_cache=True, save_result=True) 60 | 61 | # Make the results from different detectors as a list. 62 | ms_result = [ms_result_py, ms_result_matlab] 63 | 64 | # Show the result 65 | for result_term in ms_result[0]['result_term_list']: 66 | bench.Utils.print_result(ms_result, result_term) 67 | bench.Utils.save_result(ms_result, result_term) 68 | 69 | #show result for different sequences 70 | for sequence in vggh.sequence_name_list: 71 | for result_term in ms_result[0]['result_term_list']: 72 | bench.Utils.print_sequence_result(ms_result, sequence, result_term) 73 | bench.Utils.save_sequence_result(ms_result, sequence, result_term) 74 | 75 | 76 | Full code for Repeatablity Benchmark (test/test_retrieval_bench.py): 77 | 78 | .. literalinclude:: ../test/test_rep_bench.py 79 | 80 | Full code for Matching Score Benchmark (test/test_ms_bench.py): 81 | 82 | .. literalinclude:: ../test/test_ms_bench.py 83 | -------------------------------------------------------------------------------- /matlab/+dset/edgefoci.m: -------------------------------------------------------------------------------- 1 | function [ imdb ] = edgefoci( varargin ) 2 | 3 | % Copyright (C) 2017 Karel Lenc 4 | % All rights reserved. 5 | % 6 | % This file is part of the VLFeat library and is made available under 7 | % the terms of the BSD license (see the COPYING file). 8 | 9 | DATADIR = 'OxfordRelease'; 10 | NUMSEQUENCES = 13; 11 | 12 | opts.url = 'https://documents.epfl.ch/groups/c/cv/cvlab-unit/www/data/keypoints/OxfordRelease.tar.gz'; 13 | opts.rootDir = fullfile(vlb_path('datasets'), 'edgefoci'); 14 | opts.matchFramesFun = @(g) ... 15 | @(fa, fb, varargin) geom.ellipse_overlap_H(g, fa, fb, ... 16 | 'maxOverlapError', 0.5, varargin{:}); 17 | opts.impath = 'image_color'; 18 | opts = vl_argparse(opts, varargin); 19 | 20 | utls.provision(opts.url, opts.rootDir); 21 | 22 | dataDir = fullfile(opts.rootDir, DATADIR); 23 | getImPath = @(seq, imname) fullfile(dataDir, seq, 'test', opts.impath, imname); 24 | getHomPath = @(seq, iman, imbn) fullfile(dataDir, seq, 'test', 'homography', sprintf('H%dto%dp', iman, imbn)); 25 | 26 | sequences = sort(utls.listdirs(dataDir)); 27 | assert(numel(sequences) == NUMSEQUENCES, ... 28 | 'Invalid number of sequences found.'); 29 | 30 | imdb.images = {}; 31 | imdb.tasks = {}; 32 | rfile = @(path) strtrim(strsplit(strtrim(fileread(path)), '\n')); 33 | 34 | imi = 1; lastim = 0; 35 | for sIdx = 1:numel(sequences) 36 | sequence = sequences{sIdx}; 37 | allimgs = rfile(fullfile(dataDir, sequence, 'test', 'test_imgs.txt')); 38 | [allimgs_u, ~, ic] = unique(allimgs); 39 | for imi_l = 1:numel(allimgs_u) 40 | [~, filename, ext] = fileparts(allimgs_u{imi_l}); 41 | imPath = getImPath(sequence, [filename, ext]); 42 | assert(exist(imPath, 'file') == 2, 'Image %s not found.', imPath); 43 | imdb.images{imi} = struct('id', imi, ... 44 | 'name', sprintf('%s-%s', sequence, filename), 'path', imPath, ... 45 | 'sequence', sequence, 'istest', true, 'isval', false, ... 46 | 'imsize', utls.get_image_size(imPath)); 47 | imi = imi + 1; 48 | end 49 | pidx = numel(allimgs)/2; 50 | for pi = 1:pidx 51 | ima = imdb.images{ic(pi) + lastim}; imb = imdb.images{ic(pi+pidx) + lastim}; 52 | assert(strcmp(ima.sequence, imb.sequence)); 53 | tan = regexp(ima.name, 'img(?[\d.]+)', 'names'); 54 | tbn = regexp(imb.name, 'img(?[\d.]+)', 'names'); 55 | homp = getHomPath(ima.sequence, str2double(tan.num), str2double(tbn.num)); 56 | hom = utls.read_vgg_homography(homp); 57 | imdb.tasks{end+1} = struct(... 58 | 'ima', ima.name, 'imb', imb.name, ... 59 | 'ima_id', ic(pi) + lastim, 'imb_id', ic(pi+pidx) + lastim, ... 60 | 'H', hom, ... 61 | 'ima_size', ima.imsize, 'imb_size', imb.imsize, ... 62 | 'istest', ima.istest, 'isval', imb.isval, 'sequence', sequence, ... 63 | 'description', struct('impair', [pi, pi+pidx])); 64 | end 65 | lastim = imi - 1; 66 | end 67 | 68 | imdb.images = cell2mat(imdb.images); 69 | imdb.tasks = cell2mat(imdb.tasks); 70 | imdb.name = 'edgefoci'; 71 | imdb.matchFramesFun = opts.matchFramesFun; 72 | imdb.geometry = 'homography'; 73 | imdb.rootdir = opts.rootDir; 74 | 75 | end 76 | 77 | 78 | -------------------------------------------------------------------------------- /matlab/vlb_path.m: -------------------------------------------------------------------------------- 1 | function root = vlb_path(set, imdb, featsname, benchname) 2 | %VLB_ROOT Get the root path of the VLB toolbox. 3 | % VLB_ROOT() returns the path to the VLB toolbox. 4 | % 5 | % Otherwise can return paths to particular data locations of the VLB. In 6 | % all cases, several specifiers are required: 7 | % IMDBNM: structure or a string, specifying the image database 8 | % FEATSNM: structure or a string, specifying the local features 9 | % FEATSNM: string, specifying the benchmark 10 | 11 | % To access the benchmark data and results one can call: 12 | % VLB_ROOT('features', IMDBNM, FEATSNM) returns features path 13 | % VLB_ROOT('patches', IMDBNM, FEATSNM) returns patches path 14 | % VLB_ROOT('results', IMDBNM, FEATSNM, BENCHNM) returns patches path 15 | % 16 | % By default, all data are stored in a path relative to the location of 17 | % this script. This can be overriden with an environment variable 18 | % VLB_DATAROOT. 19 | % 20 | % Additionally one can acces: 21 | % VLB_ROOT('datasets') returns the image database path 22 | % VLB_ROOT('vendor') returns the third party library path. 23 | 24 | 25 | % Copyright (C) 2017 Karel Lenc. 26 | % All rights reserved. 27 | % 28 | % This file is part of the VLFeat library and is made available under 29 | % the terms of the BSD license (see the COPYING file). 30 | 31 | env_root = getenv('VLB_ROOT'); 32 | if ~isempty(env_root) 33 | root = strtrim(env_root); 34 | else 35 | root = fileparts(fileparts(mfilename('fullpath'))) ; 36 | end 37 | 38 | % Allow to store data per project with a environment variable 39 | env_scoresroot = getenv('VLB_DATAROOT'); 40 | if ~isempty(env_scoresroot) 41 | dataroot = strtrim(env_scoresroot); 42 | else 43 | dataroot = fullfile(root, 'data'); 44 | end 45 | 46 | if nargin > 0 47 | if nargin > 1 48 | assert(isstruct(imdb) && isfield(imdb, 'name'), 'Invalid imdb'); 49 | imdb_name = imdb.name; 50 | end 51 | if nargin > 2 52 | switch class(featsname) 53 | case 'struct' 54 | featsname = featsname.name; 55 | case 'cell' 56 | featsname = fullfile(featsname{:}); 57 | case 'char' 58 | otherwise 59 | error('Invalid featsname'); 60 | end 61 | end 62 | if nargin > 3 63 | assert(ischar(benchname), 'Invalid benchmark name.'); 64 | end 65 | switch set 66 | case {'features', 'patches'} 67 | assert(nargin == 3, 'Invalid args (imdb, feats)'); 68 | root = fullfile(dataroot, set, imdb_name, featsname); 69 | case 'scores' 70 | assert(nargin == 4, 'Invalid input (imdb, feats, bench)'); 71 | root = fullfile(dataroot, 'scores', benchname, imdb_name, featsname); 72 | case 'datasets' 73 | assert(nargin == 1, 'Too many args for datasets'); 74 | root = fullfile(root, 'datasets'); 75 | case 'vendor' 76 | assert(nargin == 1, 'Too many args for vendor'); 77 | root = fullfile(root, 'vendor'); 78 | case 'imagelists' 79 | assert(nargin == 1, 'Too many args for vendor'); 80 | root = fullfile(dataroot, 'imagelists'); 81 | otherwise 82 | error('Invalid set %s.', set); 83 | end 84 | end -------------------------------------------------------------------------------- /python/dset/write_dataset_hpatches.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | sequence_name_list = ['i_ajuntament', 'i_autannes', 'i_bologna', 'i_books', 'i_boutique', 'i_bridger', 4 | 'i_brooklyn', 'i_castle', 'i_chestnuts', 'i_contruction', 'i_crownday', 'i_crownnight', 'i_dc', 5 | 'i_dome', 'i_duda', 'i_fenis', 'i_fog', 'i_fruits', 'i_gonnenberg', 'i_greenhouse', 'i_greentea', 6 | 'i_indiana', 'i_kions', 'i_ktirio', 'i_kurhaus', 'i_leuven', 'i_lionday', 'i_lionnight', 'i_londonbridge', 7 | 'i_melon', 'i_miniature', 'i_nescafe', 'i_nijmegen', 'i_nuts', 'i_objects','i_parking','i_partyfood', 8 | 'i_pencils', 'i_pinard', 'i_pool', 'i_porta', 'i_resort', 'i_salon', 'i_santuario', 'i_school', 'i_ski', 9 | 'i_smurf', 'i_steps', 'i_table', 'i_tools', 'i_toy', 'i_troulos', 'i_veggies', 'i_village', 10 | 'i_whitebuilding', 'i_yellowtent', 'i_zion', 'v_abstract', 'v_adam', 'v_apprentices', 'v_artisans', 11 | 'v_astronautis', 'v_azzola', 'v_bark', 'v_bees', 'v_beyus', 'v_bip', 'v_bird', 'v_birdwoman', 12 | 'v_blueprint', 'v_boat', 'v_bricks', 'v_busstop', 'v_calder', 'v_cartooncity', 'v_charing','v_churchill', 13 | 'v_circus', 'v_coffeehouse', 'v_colors', 'v_courses','v_dirtywall', 'v_dogman', 'v_eastsouth', 14 | 'v_feast', 'v_fest', 'v_gardens', 'v_grace', 'v_graffiti','v_home', 'v_laptop', 'v_london', 15 | 'v_machines', 'v_man', 'v_maskedman', 'v_pomegranate', 'v_posters', 'v_samples', 'v_soldiers', 16 | 'v_strand', 'v_sunseason', 'v_tabletop', 'v_talent', 'v_tempera', 'v_there', 'v_underground', 17 | 'v_vitro','v_wall','v_wapping','v_war','v_weapons','v_woman','v_wormhole','v_wounded','v_yard','v_yuri'] 18 | description_list = ['Decreasing Light']*57 + ['Viewpoint angle']*59 19 | 20 | label_list = ['1','2','3','4','5','6'] 21 | 22 | json_data = {} 23 | json_data['Dataset Name'] = 'HPatches' 24 | json_data['Description'] = 'Standard Benchmark' 25 | json_data['url'] = 'http://icvl.ee.ic.ac.uk/vbalnt/hpatches/hpatches-sequences-release.tar.gz' 26 | json_data['Sequence Number'] = len(sequence_name_list) 27 | json_data['Sequence Name List'] = sequence_name_list 28 | json_data['Sequences'] = [] 29 | 30 | for idx, sequence_name in enumerate(sequence_name_list): 31 | sequence = {} 32 | sequence['Name'] = sequence_name 33 | sequence['Description'] = sequence_name 34 | sequence['Label'] = description_list[idx] 35 | sequence['Images'] = [] 36 | sequence['Image Number'] = 6 37 | 38 | for image_idx, image_label in enumerate(label_list): 39 | image = {} 40 | image['file'] = '{}/{}.ppm'.format(sequence_name,image_label) 41 | image['id'] = str(image_idx+1) 42 | image['label'] = str(image_label) 43 | sequence['Images'].append(image) 44 | 45 | sequence['Link Number'] = 5 46 | sequence['Links'] = [] 47 | for i in range(1,5): 48 | link = {} 49 | link['source'] = str(1) 50 | link['target'] = str(i+1) 51 | link['file'] = '{}/H_1_{}'.format(sequence_name, i+1) 52 | sequence['Links'].append(link) 53 | json_data['Sequences'].append(sequence) 54 | 55 | with open('./datasets/dataset_info/{}.json'.format('hpatches'),'w') as json_file: 56 | json.dump(json_data, json_file, indent=2) 57 | -------------------------------------------------------------------------------- /matlab/+dset/hsequences.m: -------------------------------------------------------------------------------- 1 | function [ imdb ] = hsequences( varargin ) 2 | 3 | % Copyright (C) 2017 Karel Lenc 4 | % All rights reserved. 5 | % 6 | % This file is part of the VLFeat library and is made available under 7 | % the terms of the BSD license (see the COPYING file). 8 | 9 | IMEXT = 'ppm'; 10 | NUMIMSEQ = 6; 11 | DATADIR = 'hpatches-sequences-release'; 12 | NUMSEQUENCES = 116; 13 | 14 | opts.url = 'http://icvl.ee.ic.ac.uk/vbalnt/hpatches/hpatches-sequences-release.tar.gz'; 15 | opts.rootDir = fullfile(vlb_path('datasets'), 'hsequences'); 16 | opts.matchFramesFun = @(g) ... 17 | @(fa, fb, varargin) geom.ellipse_overlap_H(g, fa, fb, ... 18 | 'maxOverlapError', 0.5, varargin{:}); 19 | opts.category = ''; 20 | opts = vl_argparse(opts, varargin); 21 | 22 | utls.provision(opts.url, opts.rootDir); 23 | 24 | dataDir = fullfile(opts.rootDir, DATADIR); 25 | getImPath = @(seq, imid) fullfile(dataDir, seq, sprintf('%d.%s', imid, IMEXT)); 26 | sequences = sort(utls.listdirs(dataDir)); 27 | assert(numel(sequences) == NUMSEQUENCES, 'Invalid number of sequences found.'); 28 | 29 | numImages = NUMIMSEQ*numel(sequences); 30 | imdb.images = cell(1, numImages); 31 | imdb.tasks = {}; 32 | 33 | imi = 1; 34 | for sIdx = 1:numel(sequences) 35 | sequence = sequences{sIdx}; 36 | refim = imi; 37 | if strcmp(sequence(1), 'i') 38 | category = 'illumination'; 39 | elseif strcmp(sequence(1), 'v') 40 | category = 'viewpoint'; 41 | else 42 | error('Invalid category'); 43 | end 44 | if ~isempty(opts.category) && ~strcmp(category, opts.category) 45 | continue; 46 | end 47 | for imi_l = 1:NUMIMSEQ 48 | imPath = getImPath(sequence, imi_l); 49 | assert(exist(imPath, 'file') == 2, 'Image %s not found.', imPath); 50 | imSize = utls.get_image_size(imPath); 51 | imdb.images{imi}.id = imi; 52 | imdb.images{imi}.name = sprintf('%s-%d', sequence, imi_l); 53 | imdb.images{imi}.path = imPath; 54 | imdb.images{imi}.seqnum = imi_l; 55 | imdb.images{imi}.sequence = sequence; 56 | imdb.images{imi}.category = category; 57 | imdb.images{imi}.imsize = imSize; 58 | if imi_l == 1 59 | refImSize = utls.get_image_size(imPath); 60 | imi = imi + 1; 61 | continue; 62 | end; 63 | tfs = utls.read_vgg_homography(fullfile(dataDir, sequence, sprintf('H_1_%d', imi_l))); 64 | imdb.tasks{end+1} = struct('ima', imdb.images{refim}.name, ... 65 | 'imb', imdb.images{imi}.name, ... 66 | 'ima_id', refim, 'imb_id', imi, 'H', tfs, ... 67 | 'ima_size', refImSize, 'imb_size', imSize, ... 68 | 'sequence', sequence, 'sequence_id', 'sIdx', ... 69 | 'description', struct('category', category, ... 70 | 'impair', [1, imi_l])); 71 | imi = imi + 1; 72 | end 73 | end 74 | 75 | imdb.images = cell2mat(imdb.images(~cellfun(@isempty, imdb.images))); 76 | imdb.tasks = cell2mat(imdb.tasks(~cellfun(@isempty, imdb.tasks))); 77 | imdb.name = 'hpatches-sequences'; 78 | if ~isempty(opts.category) 79 | imdb.name = [imdb.name, '-', opts.category]; 80 | end 81 | imdb.matchFramesFun = opts.matchFramesFun; 82 | imdb.geometry = 'homography'; 83 | imdb.rootdir = opts.rootDir; 84 | 85 | end 86 | 87 | 88 | --------------------------------------------------------------------------------