Skip to content
Browse files

xtest: new Matlab toolbox unit tests

  • Loading branch information...
1 parent d88f3ee commit c16f1334abe9ef95708698b567077176070cef66 @vedaldi vedaldi committed Jan 21, 2010
View
14 toolbox/xtest/vl_assert_almost_equal.m
@@ -0,0 +1,14 @@
+function vl_assert_almost_equal(x, y, varargin)
+ epsilon = 1e-6 ;
+ if length(varargin) > 0
+ if isnumeric(varargin{1})
+ epsilon = varargin{1} ;
+ varargin(1) = [] ;
+ end
+ end
+ assert(isequal(class(x), class(y)), varargin{:}) ;
+ assert(isequal(size(x),size(y)), varargin{:}) ;
+ i = isnan(x) ;
+ assert(all(isnan(y(i))), varargin{:}) ;
+ assert(max(abs(x(~i) - y(~i))) < epsilon, varargin{:}) ;
+end
View
3 toolbox/xtest/vl_assert_equal.m
@@ -0,0 +1,3 @@
+function vl_assert_equal(x, y, varargin)
+ assert(isequalwithequalnans(x,y),varargin{:}) ;
+end
View
48 toolbox/xtest/vl_test.m
@@ -0,0 +1,48 @@
+function results = vl_test(suite, test)
+% VL_TEST Run test suite
+% RESULTS = VL_TEST() runs all VLFeat test suites. The tests
+% verify that VLFeat is working correctly.
+%
+% RESULTS is a structure listing the result of each test.
+% It has fileds:
+%
+% TESTNAME: name of the test
+% SUCCEDED: a boolean flag indicating whether the test succeded
+% EXCEPTION: the exception generated if the test failed
+%
+% VL_TEST(SUITE, TEST) runs the specified SUITE/TEST without catching
+% the potential exception. Useful to DBSTOP to debug.
+%
+% Author:: Andrea Vedaldi
+
+% AUTORIGHTS
+
+testRoot = fileparts(mfilename('fullpath')) ;
+
+if nargin == 0
+ files = dir(fullfile(testRoot, 'vl_test_*m')) ;
+
+ results = {} ;
+ for i = 1:length(files)
+ testCommand = files(i).name(1:end-2) ;
+ if strcmp(testCommand, 'vl_test_init'), continue ; end
+ fprintf('vl_test: running %s\n', testCommand) ;
+ results{i} = feval(str2func(testCommand)) ;
+ end
+
+ results = cat(2, results{:}) ;
+ for i = 1:length(results)
+ if results(i).succeded
+ fprintf('vl_test: %-35s ... passed\n', results(i).testName) ;
+ else
+ fprintf('vl_test: %-35s ... failed\n', results(i).testName) ;
+ fprintf('%s:%d: %s\n', ...
+ results(i).exception.stack(1).name, ...
+ results(i).exception.stack(1).line, ...
+ results(i).exception.message) ;
+ end
+ end
+
+else
+ feval(str2func(sprintf('vl_test_%s', suite)), test) ;
+end
View
58 toolbox/xtest/vl_test_alldist.m
@@ -0,0 +1,58 @@
+function results = vl_test_alldist(varargin)
+vl_test_init ;
+
+function s = setup()
+vl_twister('state', 0) ;
+s.X = 3.1 * vl_twister(10,10) ;
+s.Y = 4.7 * vl_twister(10,7) ;
+
+function test_self(s)
+vl_assert_almost_equal(...
+ vl_alldist(s.X, 'kl2'), ...
+ makedist(@(x,y) x*y, s.X, s.X), ...
+ 1e-6) ;
+
+function test_distances(s)
+dists = {'chi2', 'l2', 'l1', 'kchi2', 'kl2', 'kl1'} ;
+distsEquiv = { ...
+ @(x,y) (x-y)^2 / (x + y), ...
+ @(x,y) (x-y)^2, ...
+ @(x,y) abs(x-y), ...
+ @(x,y) 2 * (x*y) / (x + y), ...
+ @(x,y) x*y, ...
+ @(x,y) min(x,y) } ;
+types = {'single', 'double'} ;
+
+for simd = [0 1]
+ for d = 1:length(dists)
+ for t = 1:length(types)
+ vl_simdctrl(simd) ;
+ X = feval(str2func(types{t}), s.X) ;
+ Y = feval(str2func(types{t}), s.Y) ;
+ vl_assert_almost_equal(...
+ vl_alldist(X,Y,dists{d}), ...
+ makedist(distsEquiv{d},X,Y), ...
+ 1e-5, ...
+ 'alldist failed for dist=%s type=%s simd=%d', ...
+ dists{d}, ...
+ types{t}, ...
+ simd) ;
+ end
+ end
+end
+
+function D = makedist(cmp,X,Y)
+[d,m] = size(X) ;
+[d,n] = size(Y) ;
+D = zeros(m,n) ;
+for i = 1:m
+ for j = 1:n
+ acc = 0 ;
+ for k = 1:d
+ acc = acc + cmp(X(k,i),Y(k,j)) ;
+ end
+ D(i,j) = acc ;
+ end
+end
+conv = str2func(class(X)) ;
+D = conv(D) ;
View
36 toolbox/xtest/vl_test_binsum.m
@@ -0,0 +1,36 @@
+% VL_TEST_BINSUM
+function results = vl_test_binsum(varargin)
+vl_test_init ;
+
+function test_three_args()
+vl_assert_almost_equal(...
+ vl_binsum([0 0], 1, 2), [0 1]) ;
+vl_assert_almost_equal(...
+ vl_binsum([1 7], -1, 1), [0 7]) ;
+vl_assert_almost_equal(...
+ vl_binsum([1 7], -1, [1 2 2 2 2 2 2 2]), [0 0]) ;
+
+function test_four_args()
+vl_assert_almost_equal(...
+ vl_binsum(eye(3), [1 1 1], [1 2 3], 1), 2*eye(3)) ;
+vl_assert_almost_equal(...
+ vl_binsum(eye(3), [1 1 1]', [1 2 3]', 2), 2*eye(3)) ;
+vl_assert_almost_equal(...
+ vl_binsum(eye(3), 1, [1 2 3], 1), 2*eye(3)) ;
+vl_assert_almost_equal(...
+ vl_binsum(eye(3), 1, [1 2 3]', 2), 2*eye(3)) ;
+
+function test_3d_one()
+Z = zeros(3,3,3) ;
+B = 3*ones(3,1,3) ;
+R = Z ; R(:,3,:) = 17 ;
+vl_assert_almost_equal(...
+ vl_binsum(Z, 17, B, 2), R) ;
+
+function test_3d_two()
+Z = zeros(3,3,3) ;
+B = 3*ones(3,3,1) ;
+X = zeros(3,3,1) ; X(:,:,1) = 17 ;
+R = Z ; R(:,:,3) = 17 ;
+vl_assert_almost_equal(...
+ vl_binsum(Z, X, B, 3), R) ;
View
62 toolbox/xtest/vl_test_dsift.m
@@ -0,0 +1,62 @@
+function results = vl_test_dsift(varargin)
+% VL_TEST_DSIFT
+vl_test_init ;
+
+function s = setup()
+I = im2double(imread(fullfile(vl_root,'data','spots.jpg'))) ;
+s.I = rgb2gray(single(I)) ;
+
+function test_fast_slow(s)
+binSize = 4 ; % bin size in pixels
+magnif = 3 ; % bin size / keypoint scale
+scale = binSize / magnif ;
+windowSize = 5 ;
+
+[f, d] = vl_dsift(vl_imsmooth(s.I, sqrt(scale.^2 - .25)), ...
+ 'size', binSize, ...
+ 'step', 10, ...
+ 'bounds', [20,20,210,140], ...
+ 'windowsize', windowSize, ...
+ 'floatdescriptors') ;
+
+[f_, d_] = vl_dsift(vl_imsmooth(s.I, sqrt(scale.^2 - .25)), ...
+ 'size', binSize, ...
+ 'step', 10, ...
+ 'bounds', [20,20,210,140], ...
+ 'windowsize', windowSize, ...
+ 'floatdescriptors', ...
+ 'fast') ;
+
+error = std(d_(:) - d(:)) / std(d(:)) ;
+assert(error < 0.1, 'dsift fast approximation not close') ;
+
+function test_sift(s)
+binSize = 4 ; % bin size in pixels
+magnif = 3 ; % bin size / keypoint scale
+scale = binSize / magnif ;
+
+windowSizeRange = [1 1.2 5] ;
+for wi = 1:length(windowSizeRange)
+ windowSize = windowSizeRange(wi) ;
+
+ [f, d] = vl_dsift(vl_imsmooth(s.I, sqrt(scale.^2 - .25)), ...
+ 'size', binSize, ...
+ 'step', 10, ...
+ 'bounds', [20,20,210,140], ...
+ 'windowsize', windowSize, ...
+ 'floatdescriptors') ;
+
+ numKeys = size(f, 2) ;
+ f_ = [f ; ones(1, numKeys) * scale ; zeros(1, numKeys)] ;
+
+ [f_, d_] = vl_sift(s.I, ...
+ 'magnif', magnif, ...
+ 'frames', f_, ...
+ 'firstoctave', -1, ...
+ 'levels', 5, ...
+ 'floatdescriptors', ...
+ 'windowsize', windowSize) ;
+
+ error = std(d_(:) - d(:)) / std(d(:)) ;
+ assert(error < 0.1, 'dsift and sift equivalence') ;
+end
View
39 toolbox/xtest/vl_test_imintegral.m
@@ -0,0 +1,39 @@
+function results = vl_test_imintegral(varargin)
+% VL_TEST_IMINTEGRAL
+vl_test_init ;
+
+function state = setup()
+state.I = ones(5,6) ;
+state.correct = [ 1 2 3 4 5 6 ;
+ 2 4 6 8 10 12 ;
+ 3 6 9 12 15 18 ;
+ 4 8 12 16 20 24 ;
+ 5 10 15 20 25 30 ; ] ;
+
+function test_matlab_equivalent(s)
+vl_assert_equal(slow_imintegral(s.I), s.correct) ;
+
+function test_basic(s)
+vl_assert_equal(vl_imintegral(s.I), s.correct) ;
+
+function test_multi_dimensional(s)
+vl_assert_equal(vl_imintegral(repmat(s.I, [1 1 3])), ...
+ repmat(s.correct, [1 1 3])) ;
+
+function test_random(s)
+numTests = 50 ;
+for i = 1:numTests
+ I = rand(5) ;
+ vl_assert_almost_equal(vl_imintegral(s.I), ...
+ slow_imintegral(s.I)) ;
+end
+
+function integral = slow_imintegral(I)
+integral = zeros(size(I));
+for k = 1:size(I,3)
+ for r = 1:size(I,1)
+ for c = 1:size(I,2)
+ integral(r,c,k) = sum(sum(I(1:r,1:c,k)));
+ end
+ end
+end
View
67 toolbox/xtest/vl_test_imsmooth.m
@@ -0,0 +1,67 @@
+function results = vl_test_imsmooth(varargin)
+% VL_TEST_IMSMOOTH
+vl_test_init ;
+
+function s = setup()
+I = im2double(imread(fullfile(vl_root,'data','spots.jpg'))) ;
+I = max(min(imresize(I,2),1),0) ;
+s.I = single(I) ;
+
+function test_pad_by_continuity(s)
+% Convolving a constant signal padded with continuity does not change
+% the signal.
+I = ones(3) ;
+for ker = {'triangular', 'gaussian'}
+ ker = char(ker) ;
+ J = vl_imsmooth(I, 2, ...
+ 'kernel', ker, ...
+ 'padding', 'continuity') ;
+ vl_assert_almost_equal(J, I, 1e-4, ...
+ 'padding by continutiy with kernel = %s', ker) ;
+end
+
+function test_kernels(s)
+for ker = {'triangular', 'gaussian'}
+ ker = char(ker) ;
+ for type = {@single, @double}
+ for simd = [0 1]
+ for sigma = [1 2 7]
+ for step = [1 2 3]
+ vl_simdctrl(simd) ;
+ conv = type{1} ;
+ g = equivalent_kernel(ker, sigma) ;
+ J = vl_imsmooth(conv(s.I), sigma, ...
+ 'kernel', ker, ...
+ 'padding', 'zero', ...
+ 'subsample', step) ;
+ J_ = conv(convolve(s.I, g, step)) ;
+ vl_assert_almost_equal(J, J_, 1e-4, ...
+ 'kernel=%s sigma=%f step=%d simd=%d', ...
+ ker, sigma, step, simd) ;
+ end
+ end
+ end
+ end
+end
+
+function g = equivalent_kernel(ker, sigma)
+switch ker
+ case 'gaussian'
+ W = ceil(4*sigma) ;
+ g = exp(-.5*((-W:W)/(sigma+eps)).^2) ;
+ case 'triangular'
+ W = max(round(sigma),1) ;
+ g = W - abs(-W+1:W-1) ;
+end
+g = g / sum(g) ;
+
+function I = convolve(I, g, step)
+if strcmp(class(I),'single')
+ g = single(g) ;
+else
+ g = double(g) ;
+end
+for k=1:size(I,3)
+ I(:,:,k) = conv2(g,g,I(:,:,k),'same');
+end
+I = I(1:step:end,1:step:end,:) ;
View
98 toolbox/xtest/vl_test_init.m
@@ -0,0 +1,98 @@
+% VL_TEST_INIT Intialize test file
+% This is a VLFeat internal function used to initialize
+% a file containing tests.
+%
+% Author:: Andrea Vedaldi
+
+% AUTORIGHTS
+
+% obtain path to caller m-file
+stack = dbstack(1) ;
+mfilePath = stack(1).file ;
+mfileName = stack(1).name ;
+fid = fopen(mfilePath, 'r') ;
+
+% Parse source code to get subfunction names. It could use
+% which('-subfun', stack(1).name) instead, but it is undocumented.
+
+setupFunc = [] ;
+teardownFunc = [] ;
+
+tests = {} ;
+l = 0 ;
+t = 0 ;
+while 1
+ tline = fgetl(fid) ;
+ l = l + 1 ;
+ if ~ischar(tline), break ; end
+ mo = regexp(tline, '^\s*function\s+(\w\s*=\s*)?test_(?<name>[\w_]+)\s*\(.*\)\s*$', ...
+ 'names') ;
+ if length(mo) > 0
+ t = t + 1 ;
+ tests{t}.name = mo(1).name ;
+ tests{t}.func = str2func(['test_' mo(1).name]) ;
+ tests{t}.lineNumber = l ;
+ end
+
+ mo = regexp(tline, '^\s*function\s+(\w+\s*=\s*)?(?<name>setup|teardown)\s*\(.*\)\s*$', ...
+ 'names') ;
+ if length(mo) > 0
+ switch mo(1).name
+ case 'setup'
+ if isempty(setupFunc)
+ setupFunc = @setup ;
+ else
+ warning('%s:%d: ignoring redundant definition of the setup function', ...
+ mfilePath) ;
+ end
+ case 'teardown'
+ if isempty(teardownFunc)
+ teardownFunc = @teardown ;
+ else
+ warning('%s:%d: ignoring redundant definition of the setup function', ...
+ mfilePath) ;
+ end
+ otherwise
+ assert(0) ;
+ end
+ end
+end
+
+if ~isempty(setupFunc), state = setupFunc() ; end
+
+if length(varargin) > 0
+ testFunc = str2func(sprintf('test_%s', varargin{1})) ;
+ if exist('state','var')
+ testFunc(state) ;
+ else
+ testFunc() ;
+ end
+ if ~isempty(teardownFunc), teardownFunc(state) ; end
+ return ;
+end
+
+% Run all tests collecting the results.
+if length(tests) == 0
+ error('No tests found in ''%s''', mfileName) ;
+end
+
+for t = 1:length(tests)
+ subTestName = sprintf('test_%s', tests{t}.name) ;
+ results{t}.testName = sprintf('%s:%s', mfileName(9:end), tests{t}.name) ;
+ results{t}.succeded = true ;
+ results{t}.exception = [] ;
+ try
+ if exist('state', 'var')
+ tests{t}.func(state) ;
+ else
+ tests{t}.func() ;
+ end
+ catch exception
+ results{t}.succeded = false ;
+ results{t}.exception = exception ;
+ end
+end
+
+if ~isempty(teardownFunc), teardownFunc(state) ; end
+
+results = cat(2, results{:}) ;
View
46 toolbox/xtest/vl_test_sift.m
@@ -0,0 +1,46 @@
+function results = vl_test_sift(varargin)
+% VL_TEST_SIFT
+vl_test_init ;
+
+function s = setup()
+s.I = im2single(imread(fullfile(vl_root,'data','box.pgm'))) ;
+[s.ubc.f, s.ubc.d] = ...
+ vl_ubcread(fullfile(vl_root,'data','box.sift')) ;
+
+function test_ubc_descriptor(s)
+err = [] ;
+[f, d] = vl_sift(s.I,...
+ 'firstoctave', -1, ...
+ 'frames', s.ubc.f) ;
+D2 = vl_alldist(f, s.ubc.f) ;
+[drop, perm] = min(D2) ;
+f = f(:,perm) ;
+d = d(:,perm) ;
+error = mean(sqrt(sum((single(s.ubc.d) - single(d)).^2))) ...
+ / mean(sqrt(sum(single(s.ubc.d).^2))) ;
+assert(error < 0.1, ...
+ 'sift descriptor did not produce desctiptors similar to UBC ones') ;
+
+function test_ubc_detector(s)
+[f, d] = vl_sift(s.I,...
+ 'firstoctave', -1, ...
+ 'peakthresh', .01, ...
+ 'edgethresh', 10) ;
+
+s.ubc.f(4,:) = mod(s.ubc.f(4,:), 2*pi) ;
+f(4,:) = mod(f(4,:), 2*pi) ;
+
+% scale the components so that 1 pixel erro in x,y,z is equal to a
+% 10-th of angle.
+S = diag([1 1 1 20/pi]);
+D2 = vl_alldist(S * s.ubc.f, S * f) ;
+[d2,perm] = sort(min(D2)) ;
+error = sqrt(d2) ;
+quant80 = round(.8 * size(f,2)) ;
+
+% check for less than one pixel error at 80% quantile
+assert(error(quant80) < 1, ...
+ 'sift detector did not produce enough keypoints similar to UBC ones') ;
+
+
+
View
35 toolbox/xtest/vl_test_twister.m
@@ -0,0 +1,35 @@
+function results = vl_test_twister(varargin)
+% VL_TEST_TWISTER
+vl_test_init ;
+
+function test_seed_by_scalar()
+rand('twister',1) ; a = rand ;
+vl_twister('state',1) ; b = vl_twister ;
+vl_assert_equal(a,b,'seed by scalar + VL_TWISTER()') ;
+
+function test_get_set_state()
+rand('twister',1) ; a = rand('twister') ;
+vl_twister('state',1) ; b = vl_twister('state') ;
+vl_assert_equal(a,b,'read state') ;
+
+a(1) = a(1) + 1 ;
+vl_twister('state',a) ; b = vl_twister('state') ;
+vl_assert_equal(a,b,'set state') ;
+
+function test_multi_dimensions()
+b = rand('twister') ;
+rand('twister',b) ;
+vl_twister('state',b) ;
+a=rand([1 2 3 4 5]) ;
+b=vl_twister([1 2 3 4 5]) ;
+vl_assert_equal(a,b,'VL_TWISTER([M N P ...])') ;
+
+function test_multi_multi_args()
+a=rand(1, 2, 3, 4, 5) ;
+b=vl_twister(1, 2, 3, 4, 5) ;
+vl_assert_equal(a,b,'VL_TWISTER(M, N, P, ...)') ;
+
+function test_square()
+a=rand(10) ;
+b=vl_twister(10) ;
+vl_assert_equal(a,b,'VL_TWISTER(N)') ;

0 comments on commit c16f133

Please sign in to comment.
Something went wrong with that request. Please try again.