# HG changeset patch # User idamnjanovic # Date 1269270385 0 # Node ID 207a6ae9a76fd4a65c5abb6374bc75bdfbfead0c # Parent 28f2b5fe3483cdf50993a858fe749a9e3efb0542 diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/Pierre_Problem.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/Pierre_Problem.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,112 @@ +function data=Pierre_Problem(src, trg, blocksize, dictsize); +%%% Generate Pierre Problem +% Ivan Damnjanovic 2010 +% +% Pierre_Problem is a part of the SMALLbox and generates the problem +% suggested by Professor Pierre Vandergheynst on the SMALL meeting in +% Villars. +% The function takes as an input: +% - src - source image matrix (if not present function promts user for +% an image file) , +% - trg - target image matrix (if not present function promts user for +% an image file) , +% - blocksize - block (patch) vertical/horizontal dimension (default 8), +% - dictsize - dictionary size (default - all patches from target +% image). +% +% The output of the function is stucture with following fields: +% - srcname - source image name, +% - imageSrc - source image matrix, +% - trgname - target image name, +% - imageTrg - Target image matrix, +% - A - dictonary with patches from the source image, +% - b - measurement matrix (i.e. patches from target image to be +% represented in dictionary A, +% - m - size of patches (default 25), +% - n - number of patches to be represented, +% - p - dictionary size, +% - blocksize - block size (default [5 5]), +% - maxval - maximum value (default - 255) +% - sparse - if 1 SMALL_solve will keep solution matrix in sparse form, +% due to memory constrains. + +%% prompt user for images %% + +%ask for source file name + +TMPpath=pwd; +FS=filesep; +if ~ exist( 'src', 'var' ) || isempty(src) +[pathstr1, name, ext, versn] = fileparts(which('SMALLboxSetup.m')); +cd([pathstr1,FS,'data',FS,'images']); +[filename,pathname] = uigetfile({'*.png;'},'Select a source image'); +[pathstr, name, ext, versn] = fileparts(filename); +data.srcname=name; +src = imread(filename); +src = double(src); +end; + +%ask for target file name + +if ~ exist( 'trg', 'var' ) || isempty(trg) +[filename,pathname] = uigetfile({'*.png;'},'Select a target image'); +[pathstr, name, ext, versn] = fileparts(filename); +data.trgname=name; +trg = imread(filename); +trg = double(trg); +end; +cd(TMPpath); + +%% set parameters %% + +maxval = 255; +if ~ exist( 'blocksize', 'var' ) || isempty(blocksize),blocksize = 5;end + +if ~ exist( 'dictsize', 'var' ) || isempty(dictsize), + dictsize = (size(src,1)-blocksize+1)*(size(src,2)-blocksize+1); + patch_idx=1:dictsize; +else + num_blocks_src=(size(src,1)-blocksize+1)*(size(src,2)-blocksize+1); + patch_idx=1:floor(num_blocks_src/dictsize):dictsize*floor(num_blocks_src/dictsize); +end + +p = ndims(src); +if (p==2 && any(size(src)==1) && length(blocksize)==1) + p = 1; +end + + +% blocksize % +if (numel(blocksize)==1) + blocksize = ones(1,p)*blocksize; +end +%% +%% create dictionary data %% + +S=im2col(src,blocksize,'sliding'); + +for j= 1:size(S,2) + S(:,j)=S(:,j)./norm(S(:,j)); +end + +%% create measurement matrix %% + +T=im2col(trg,blocksize, 'distinct'); + +%% output structure %% + +data.imageSrc = src; +data.imageTrg = trg; +data.A = S(:,patch_idx); +data.b = T; +data.m = size(T,1); +data.n = size(T,2); +data.p = size(data.A,2); +data.blocksize=blocksize; +data.maxval=maxval; + +% geting around out of memory problem when converting big matrix from +% sparse to full... (check SMALL_solve function) +data.sparse=1; + + diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/generateAMT_Learning_Problem.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/generateAMT_Learning_Problem.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,84 @@ +function data = generateAMT_Learning_Problem(nfft, windowSize, overlap) +%%% Generate Automatic Music Transcription Problem +% Ivan Damnjanovic 2010 +% +% +% generateAMT_Learning_Problem is a part of the SMALLbox and generates +% a problem that can be used for comparison of Dictionary Learning/Sparse +% Representation techniques in automatic music transcription scenario. +% The function prompts a user for an audio file (mid, wav, mat) reads it +% and generates a spectrogram given fft size (default nfft=4096), analysis +% window size (windowSize=2822), and analysis window overlap (overlap = +% 0.5). +% +% The output of the function is stucture with following fields: +% b - matrix with magnitudes of the spectrogram +% f - vector of frequencies at wihch spectrogram is computed +% windowSize - analysis window size +% overlap - analysis window overlap +% fs - sampling frequency +% m - number of frequenciy points in spectrogram +% n - number of time points in the spectrogram +% p - number of dictionary elements to be learned (eg 88 for piano) +% notesOriginal - notes of the original audio to be used for +% comparison (if midi of the original exists) +% name - name of the audio file to transcribe + +%% +FS=filesep; +if ~ exist( 'nfft', 'var' ) || isempty(nfft), nfft = 4096; end +if ~ exist( 'windowSize', 'var' ) || isempty(windowSize), windowSize = 2822; end +if ~ exist( 'overlap', 'var' ) || isempty(overlap), overlap = 0.5; end + +%% +%ask for file name +TMPpath=pwd; +[pathstr1, name, ext, versn] = fileparts(which('SMALLboxSetup.m')); +cd([pathstr1,FS,'data',FS,'audio']); +[filename,pathname] = uigetfile({'*.mat; *.mid; *.wav'},'Select a file to transcribe'); +[pathstr, name, ext, versn] = fileparts(filename); +data.name=name; + +data.notesOriginal=[]; + +if strcmp(ext,'.mid') + midi=readmidi(filename); + data.notesOriginal=midiInfo(midi); + y=midi2audio(midi); + wavwrite(y, 44100, 16, 'temp.wav'); + [x.signal, x.fs, x.nbits]=wavread('temp.wav'); + delete('temp.wav'); +elseif strcmp(ext,'.wav') + cd([pathstr1,FS, 'data', FS, 'audio', FS, 'midi']); + filename1=[name, '.mid']; + if exist(filename1, 'file') + midi=readmidi(filename1); + data.notesOriginal=midiInfo(midi); + end + cd([pathstr1,FS, 'data', FS, 'audio', FS, 'wav']); + [x.signal, x.fs, x.nbits]=wavread(filename); +else + cd([pathstr1,FS, 'data', FS, 'audio', FS, 'midi']); + filename1=[name, '.mid']; + if exist(filename1, 'file') + midi=readmidi(filename1); + data.notesOriginal=midiInfo(midi); + end + cd([pathstr1,FS, 'data', FS, 'audio', FS, 'mat']); + x=load([pathname,filename]); +end +%% +[X, frX]=spectrogram(x.signal, hanning(windowSize), overlap*windowSize, nfft, x.fs); +%% +data.b=abs(X); +data.f=frX; +data.windowSize=windowSize; +data.overlap=overlap; +data.fs=x.fs; +data.m=size(X,1); +data.n=size(X,2); + +data.p=88; %number of dictionary elements (ie notes to recover) +cd(TMPpath); + +end diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/generateAudioDenoiseProblem.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/generateAudioDenoiseProblem.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,159 @@ +function data=generateAudioDenoiseProblem(au, trainnum, blocksize, dictsize, overlap, sigma, gain, maxval, initdict); + +% Ivan Damnjanovic 2010 +% +% +% generateAudioDenoiseProblem is part of the SMALLbox and generate a +% problem for comaprison of Dictionary Learning/Sparse Representation +% techniques in audio denoising scenario. It is based on KSVD image +% denoise demo by Ron Rubinstein (see bellow). +% The fuction takes as an optional input +% au - audio samples to be denoised +% trainnum - number of frames for training +% blocksize - 1D frame size (eg 512) +% dictsize - number of atoms to be trained +% overlap - ammount of overlaping frames between 0 and 1 +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% August 2009 + + +disp(' '); +disp(' ********** Denoising Problem **********'); +disp(' '); +disp(' This function reads an audio, adds random Gaussian noise,'); +disp(' that can be later denoised by using dictionary learning techniques.'); +disp(' '); + +FS=filesep; +if ~ exist( 'sigma', 'var' ) || isempty(sigma), sigma = 26.74; end +if ~ exist( 'gain', 'var' ) || isempty(gain), gain = 1.15; end + +if ~ exist( 'initdict', 'var' ) || isempty(initdict), initdict = 'odct'; end +if ~ exist( 'overlap', 'var' ) || isempty(overlap), overlap = 15/16; end +%% prompt user for wav file %% +%ask for file name + +TMPpath=pwd; +if ~ exist( 'au', 'var' ) || isempty(au) + [pathstr1, name, ext, versn] = fileparts(which('SMALLboxSetup.m')); + cd([pathstr1,FS,'data',FS,'audio',FS,'wav']); + [filename,pathname] = uigetfile({'*.wav;'},'Select a wav file'); + [pathstr, name, ext, versn] = fileparts(filename); + data.name=name; + + au = wavread(filename); + au = mean(au,2); % turn it into mono. +end; +if ~ exist( 'maxval', 'var' ) || isempty(maxval), maxval = max(au); end + +%% generate noisy audio %% + +disp(' '); +disp('Generating noisy audio...'); +sigma = max(au)/10^(sigma/20); +n = randn(size(au)) .* sigma; +aunoise = au + n;% here we can load noise audio if available + % for example: wavread('icassp06_x.wav');% + + + +%% set parameters %% + +x = aunoise; +if ~ exist( 'blocksize', 'var' ) || isempty(blocksize),blocksize = 512;end +if ~ exist( 'dictsize', 'var' ) || isempty(dictsize), dictsize = 2048;end + +if ~ exist( 'trainnum', 'var' ) || isempty(trainnum),trainnum = (size(x,1)-blocksize+1);end + + + + + +p=1; + + +% +% msgdelta = 5; +% +% verbose = 't'; +% if (msgdelta <= 0) +% verbose=''; +% msgdelta = -1; +% end +% +% +% % initial dictionary % +% +if (strcmpi(initdict,'odct')) + initdict = odctndict(blocksize,dictsize,p); +elseif (strcmpi(initdict,'data')) + clear initdict; % causes initialization using random examples +else + error('Invalid initial dictionary specified.'); +end + +if exist( 'initdict', 'var' ) + initdict = initdict(:,1:dictsize); +end + + +% noise mode % +% if (isfield(params,'noisemode')) +% switch lower(params.noisemode) +% case 'psnr' +% sigma = maxval / 10^(params.psnr/20); +% case 'sigma' +% sigma = params.sigma; +% otherwise +% error('Invalid noise mode specified'); +% end +% elseif (isfield(params,'sigma')) +% sigma = params.sigma; +% elseif (isfield(params,'psnr')) +% sigma = maxval / 10^(params.psnr/20); +% else +% error('Noise strength not specified'); +% end + +% params.Edata = sqrt(prod(blocksize)) * sigma * gain; % target error for omp +% params.codemode = 'error'; +% +% params.sigma = sigma; +% params.noisemode = 'sigma'; +% +% +% % make sure test data is not present in params +% if (isfield(params,'testdata')) +% params = rmfield(params,'testdata'); +% end + + +%%%% create training data %%% + + +X = buffer( x(1:trainnum),blocksize, overlap*blocksize); + +% remove dc in blocks to conserve memory % +% bsize = 2000; +% for i = 1:bsize:size(X,2) +% blockids = i : min(i+bsize-1,size(X,2)); +% X(:,blockids) = remove_dc(X(:,blockids),'columns'); +% end +data.Original = au; +data.Noisy = aunoise; +data.b = X; +data.m = size(X,1); +data.n = size(X,2); +data.p = dictsize; +data.blocksize=blocksize; +data.sigma = sigma; +data.gain = gain; +data.maxval = maxval; +data.initdict= initdict; +data.signalDim=1; +cd(TMPpath); + diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/generateImageDenoiseProblem.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/generateImageDenoiseProblem.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,144 @@ +function data=generateImageDenoiseProblem(im, trainnum, blocksize, dictsize, sigma, gain, maxval, initdict); +%%% Generate Image Denoising Problem +% Ivan Damnjanovic 2010 +% +% generateImageDenoiseProblem is a part of the SMALLbox and generates +% a problem that can be used for comparison of Dictionary Learning/Sparse +% Representation techniques in image denoising scenario. +% The function takes as an input: +% - im - image matrix (if not present function promts user for an +% image file) , +% - trainnum - number of training samples (default - 40000) +% - blocksize - block (patch) vertical/horizontal dimension (default 8), +% - dictsize - dictionary size (default - 256), +% - sigma - noise level (default - 20), +% - noise gain (default - 1.15), +% - maxval - maximum value (default - 255) +% - initdict - initial dictionary (default - 4x overcomlete dct) +% +% The output of the function is stucture with following fields: +% - name - name of the original image (if image is read inside of the +% function) +% - Original - original image matrix, +% - Noisy - image with added noise, +% - b - training patches, +% - m - size of training patches (default 64), +% - n - number of training patches, +% - p - number of dictionary elements to be learned, +% - blocksize - block size (default [8 8]), +% - sigma - noise level, +% - noise gain (default - 1.15), +% - maxval - maximum value (default - 255) +% - initdict - initial dictionary (default - 4x overcomlete dct) +% - signalDim - signal dimension (default - 2) +% +% Based on KSVD denoise demo by Ron Rubinstein +% See also KSVDDENOISEDEMO and KSVDDEMO. +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% August 2009 +%% +disp(' '); +disp(' ********** Denoising Problem **********'); +disp(' '); +disp(' This function reads an image, adds random Gaussian noise,'); +disp(' that can be later denoised by using dictionary learning techniques.'); +disp(' '); + + +%% prompt user for image %% +%ask for file name +FS=filesep; +TMPpath=pwd; +if ~ exist( 'im', 'var' ) || isempty(im) + [pathstr1, name, ext, versn] = fileparts(which('SMALLboxSetup.m')); + cd([pathstr1,FS,'data',FS,'images']); + [filename,pathname] = uigetfile({'*.png;'},'Select a file containin pre-calculated notes'); + [pathstr, name, ext, versn] = fileparts(filename); + data.name=name; + im = imread(filename); + im = double(im); +end; +cd(TMPpath); + +%% check input parameters %% + +if ~ exist( 'blocksize', 'var' ) || isempty(blocksize),blocksize = 8;end +if ~ exist( 'dictsize', 'var' ) || isempty(dictsize), dictsize = 256;end +if ~ exist( 'trainnum', 'var' ) || isempty(trainnum),trainnum = 40000;end +if ~ exist( 'sigma', 'var' ) || isempty(sigma), sigma = 20; end +if ~ exist( 'gain', 'var' ) || isempty(gain), gain = 1.15; end +if ~ exist( 'maxval', 'var' ) || isempty(maxval), maxval = 255; end +if ~ exist( 'initdict', 'var' ) || isempty(initdict), initdict = 'odct'; end + +%% generate noisy image %% + +disp(' '); +disp('Generating noisy image...'); + +n = randn(size(im)) * sigma; +imnoise = im + n; + +%% set parameters %% + +x = imnoise; +p = ndims(x); + +if (p==2 && any(size(x)==1) && length(blocksize)==1) + p = 1; +end + +% blocksize % + +if (numel(blocksize)==1) + blocksize = ones(1,p)*blocksize; +end + +if (strcmpi(initdict,'odct')) + initdict = odctndict(blocksize,dictsize,p); +elseif (strcmpi(initdict,'data')) + clear initdict; % causes initialization using random examples +else + error('Invalid initial dictionary specified.'); +end + +if exist( 'initdict', 'var' ) + initdict = initdict(:,1:dictsize); +end + +%%%% create training data %%% + +ids = cell(p,1); +if (p==1) + ids{1} = reggrid(length(x)-blocksize+1, trainnum, 'eqdist'); +else + [ids{:}] = reggrid(size(x)-blocksize+1, trainnum, 'eqdist'); +end +X = sampgrid(x,blocksize,ids{:}); + +% remove dc in blocks to conserve memory % + +bsize = 2000; +for i = 1:bsize:size(X,2) + blockids = i : min(i+bsize-1,size(X,2)); + X(:,blockids) = remove_dc(X(:,blockids),'columns'); +end + +%% output structure %% + +data.Original = im; +data.Noisy = imnoise; +data.b = X; +data.m = size(X,1); +data.n = size(X,2); +data.p = dictsize; +data.blocksize=blocksize; +data.sigma = sigma; +data.gain = gain; +data.maxval = maxval; +data.initdict= initdict; +data.signalDim=2; + +end %% end of function \ No newline at end of file diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/add_dc.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/add_dc.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,33 @@ +function x = add_dc(y,dc,columns) +%ADD_DC Add DC channel to signals. +% X = ADD_DC(Y,DC) adds the specified DC value to the (possibly +% multi-dimensional) signal Y, returning the result as X. DC should be a +% scalar value. +% +% X = ADD_DC(Y,DC,'columns') where Y is a 2D matrix and DC is an array of +% length size(Y,2), treats the columns of Y as individual 1D signals, +% adding to each one the corresponding DC value from the DC array. X is +% the same size as Y and contains the resulting signals. +% +% See also REMOVE_DC. + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% April 2009 + + +if (nargin==3 && strcmpi(columns,'columns')), columns = 1; +else columns = 0; +end + +if (columns) + x = addtocols(y,dc); +else + x = y + dc; +end + + + diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/addtocols.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/addtocols.c Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,85 @@ +/************************************************************************** + * + * File name: addtocols.c + * + * Ron Rubinstein + * Computer Science Department + * Technion, Haifa 32000 Israel + * ronrubin@cs + * + * Last Updated: 19.4.2009 + * + *************************************************************************/ + + +#include "mex.h" + + +/* Input Arguments */ + +#define X_IN prhs[0] +#define V_IN prhs[1] + + +/* Output Arguments */ + +#define Y_OUT plhs[0] + + +void mexFunction(int nlhs, mxArray *plhs[], + int nrhs, const mxArray*prhs[]) + +{ + double *x, *y, *v, *xend; + mwSize m,n,m1,n1; + mwIndex counter; + + + /* Check for proper number of arguments */ + + if (nrhs != 2) { + mexErrMsgTxt("Two input arguments required."); + } else if (nlhs > 1) { + mexErrMsgTxt("Too many output arguments."); + } + + + /* Check the the input dimensions */ + + m = mxGetM(X_IN); + n = mxGetN(X_IN); + if (!mxIsDouble(X_IN) || mxIsComplex(X_IN) || mxGetNumberOfDimensions(X_IN)>2) { + mexErrMsgTxt("ADDTOCOLS requires that X be a double matrix."); + } + m1 = mxGetM(V_IN); + n1 = mxGetN(V_IN); + if (!mxIsDouble(V_IN) || mxIsComplex(V_IN) || (m1!=1 && n1!=1)) { + mexErrMsgTxt("ADDTOCOLS requires that V be a double vector."); + } + if ((m1==1 && n1!=n) || (n1==1 && m1!=n)) { + mexErrMsgTxt("Error in ADDTOCOLS: dimensions of V and X must agree."); + } + + + /* Create a matrix for the return argument */ + Y_OUT = mxCreateDoubleMatrix(m, n, mxREAL); + + + /* Assign pointers to the various parameters */ + x = mxGetPr(X_IN); + v = mxGetPr(V_IN); + y = mxGetPr(Y_OUT); + + + /* Do the actual computation */ + + xend = x+(m*n); + counter = 0; + while (x 1) { + mexErrMsgTxt("Too many output arguments."); + } + + + /* Check the input dimensions */ + + m = mxGetM(A_IN); + n = mxGetN(A_IN); + if (!mxIsDouble(A_IN) || mxIsComplex(A_IN) || mxGetNumberOfDimensions(A_IN)>2) { + mexErrMsgTxt("COLLINCOMB requires that A be a double matrix."); + } + + if (nrhs==3) { + + m1 = mxGetM(COLS_IN1); + n1 = mxGetN(COLS_IN1); + if (!mxIsDouble(COLS_IN1) || mxIsComplex(COLS_IN1) || (m1!=1 && n1!=1)) { + mexErrMsgTxt("COLLINCOMB requires that COLS be an index vector of type double."); + } + colnum = (m1 > n1) ? m1 : n1; /* the number of columns in the linear combination */ + + m2 = mxGetM(X_IN1); + n2 = mxGetN(X_IN1); + if (!mxIsDouble(X_IN1) || mxIsComplex(X_IN1) || (m2!=1 && n2!=1)) { + mexErrMsgTxt("COLLINCOMB requires that X be a double vector."); + } + + if (m2!=colnum && n2!=colnum) { + mexErrMsgTxt("The length of X does not match the number of columns in COLS."); + } + + rows = 0; + Y_OUT = mxCreateDoubleMatrix(m, 1, mxREAL); + cols = mxGetPr(COLS_IN1); + x = mxGetPr(X_IN1); + } + else { + + m1 = mxGetM(ROWS_IN); + n1 = mxGetN(ROWS_IN); + if (!mxIsDouble(ROWS_IN) || mxIsComplex(ROWS_IN) || (m1!=1 && n1!=1)) { + mexErrMsgTxt("COLLINCOMB requires that ROWS be an index vector of type double."); + } + rownum = (m1 > n1) ? m1 : n1; /* the number of rows in the linear combination */ + rownumspecified = 1; + rows = mxGetPr(ROWS_IN); + + m1 = mxGetM(COLS_IN2); + n1 = mxGetN(COLS_IN2); + if (!mxIsDouble(COLS_IN2) || mxIsComplex(COLS_IN2) || (m1!=1 && n1!=1)) { + mexErrMsgTxt("COLLINCOMB requires that COLS be an index vector of type double."); + } + colnum = (m1 > n1) ? m1 : n1; /* the number of columns in the linear combination */ + + m2 = mxGetM(X_IN2); + n2 = mxGetN(X_IN2); + if (!mxIsDouble(X_IN2) || mxIsComplex(X_IN2) || (m2!=1 && n2!=1)) { + mexErrMsgTxt("COLLINCOMB requires that X be a double vector."); + } + + if (m2!=colnum && n2!=colnum) { + mexErrMsgTxt("The length of X does not match the number of columns in COLS."); + } + + Y_OUT = mxCreateDoubleMatrix(rownum, 1, mxREAL); + cols = mxGetPr(COLS_IN2); + x = mxGetPr(X_IN2); + } + + + /* Assign pointers to the various parameters */ + A = mxGetPr(A_IN); + y = mxGetPr(Y_OUT); + + + if (rownumspecified) { + + /* check row indices */ + + row_ids = (mwIndex*)mxMalloc(rownum*sizeof(mwIndex)); + + for (i=0; i=m) { + mexErrMsgTxt("Row index in ROWS is out of range."); + } + } + + /* Do the actual computation */ + for (i=0; i=n) { + mexErrMsgTxt("Column index in COLS is out of range."); + } + for (j=0; j=n) { + mexErrMsgTxt("Column index in COLS is out of range."); + } + for (j=0; jm), id = id(1:end-(l-k-m)); end +if (l+k>n), id = id(1:end-(l+k-n)); end diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/dictdist.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/dictdist.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,61 @@ +function [dist,ratio] = dictdist(approxD,D,epsilon) +%DICTDIST Distance between dictionaries. +% [DIST,RATIO] = DICTDIST(APPROXD,D) computes the distance between the +% approximate dictionary APPROXD and the true dictionary D, where APPROXD +% is NxK and D is NxM. +% +% The distance between the dictionary APPROXD and a single atom A of D is +% defined as: +% +% DIST(APPROXD,A) = min { 1-abs(APPROXD(:,i)' * A) } +% i +% +% The distance between the dictionaries APPROXD and D is defined as: +% +% DIST(APPROXD,D) = sum { dist(APPROXD, D(:,k)) } / M +% k +% +% Note that 0 <= DIST(APPROXD,D) <= 1, where 0 implies that all atoms in D +% appear in APPROXD, and 1 implies that the atoms of D are orthogonal to +% APPROXD. +% +% The similarity ratio between APPROXD and D is defined as: +% +% RATIO(APPROXD,D) = #(atoms in D that appear in APPROXD) / M +% +% where two atoms are considered identical when DIST(A1,A2) < EPSILON with +% EPSILON=0.01 by default. Note that 0 <= RATIO(APPROXD,D) <= 1, where 0 +% means APPROXD and D have no identical atoms, and 1 means that all atoms +% of D appear in APPROXD. +% +% [DIST,RATIO] = DICTDIST(DICT1,DICT2,EPSILON) specifies a different value +% for EPSILON. + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% October 2007 + + +if (nargin < 3), epsilon = 0.01; end + +[n,m] = size(D); + +approxD = normcols(approxD*spdiag(sign(approxD(1,:)))); +D = normcols(D*spdiag(sign(D(1,:)))); + +identical_atoms = 0; +dist = 0; + +for i = 1:m + atom = D(:,i); + distances = 1-abs(atom'*approxD); + mindist = min(distances); + dist = dist + mindist; + identical_atoms = identical_atoms + (mindist < epsilon); +end + +dist = dist / m; +ratio = identical_atoms / m; diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/imnormalize.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/imnormalize.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,19 @@ +function y = imnormalize(x) +%IMNORMALIZE Normalize image values. +% Y = IMNORMALIZE(X) linearly transforms the intensity values of the image +% X to tightly cover the range [0,1]. If X has more than one channel, the +% channels are handled as one and normalized using the same transform. + + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% May 2004 + + +maxval = max(x(:)); +minval = min(x(:)); + +y = (x-minval) / (maxval-minval); diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/iswhole.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/iswhole.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,17 @@ +function z = iswhole(x,epsilon) +%ISWHOLE Determine whole numbers with finite precision. +% Z = ISWHOLE(X,EPSILON) returns a matrix the same size as X, containing +% 1's where X is whole up to precision EPSILON, and 0's elsewhere. +% +% Z = ISWHOLE(X) uses the default value of EPSILON=1e-6. + + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% May 2005 + +if (nargin<2), epsilon = 1e-6; end +z = abs(round(x)-x) < epsilon; diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/make.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/make.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,40 @@ +function make +%MAKE Build the KSVDBox MEX support files. +% MAKE compiles the KSVDBox supporting MEX functions, using Matlab's +% default MEX compiler. If the MEX compiler has not been set-up before, +% please run +% +% mex -setup +% +% before using this MAKE file. + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% April 2009 + + +% detect platform + +compstr = computer; +is64bit = strcmp(compstr(end-1:end),'64'); + + +% compilation parameters + +compile_params = cell(0); +if (is64bit) + compile_params{1} = '-largeArrayDims'; +end + + +% Compile files % + +sourcefiles = {'addtocols.c','collincomb.c','rowlincomb.c'}; + +for i = 1:length(sourcefiles) + printf('Compiling %s...', sourcefiles{i}); + mex(sourcefiles{i},compile_params{:}); +end diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/normcols.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/normcols.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,17 @@ +function y = normcols(x) +%NORMCOLS Normalize matrix columns. +% Y = NORMCOLS(X) normalizes the columns of X to unit length, returning +% the result as Y. +% +% See also ADDTOCOLS. + + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% April 2009 + + +y = x*spdiag(1./sqrt(sum(x.*x))); diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/printf.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/printf.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,26 @@ +function str = printf(varargin) +%PRINTF Print formatted text to screen. +% PRINTF(FMT,VAL1,VAL2,...) formats the data in VAL1,VAL2,... according to +% the format string FMT, and prints the result to the screen. +% +% The call to PRINTF(FMT,VAL1,VAL2,...) simply invokes the call +% DISP(SPRINTF(FMT,VAL1,VAL2,...)). For a complete description of the +% format string options see function SPRINTF. +% +% STR = PRINTF(...) also returns the formatted string. + + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% April 2008 + + +if (nargout>0) + str = sprintf(varargin{:}); + disp(str); +else + disp(sprintf(varargin{:})); +end diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/reggrid.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/reggrid.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,136 @@ +function [varargout] = reggrid(sz,num,mode) +%REGGRID Regular sampling grid. +% [I1,I2,...,Ip] = REGGRID([N1 N2 ... Np], NUM) returns the indices +% of a regular uniform sampling grid over a p-dimensional matrix with +% dimensions N1xN2x...xNp. NUM is the minimal number of required samples, +% and it is ensured that the actual number of samples, given by +% length(I1)xlength(I2)x...xlength(Ip), is at least as large as NUM. +% +% [I1,I2,...,Ip] = REGGRID([N1 N2 ... Np], NUM,'MODE') specifies the +% method for distributing the samples along each dimension. Valid modes +% include 'eqdist' (the default mode) and 'eqnum'. 'eqdist' indicates an +% equal distance between the samples in each dimension, while 'eqnum' +% indicates an equal number of samples in each dimension. +% +% Notes about MODE: +% +% 1. The 'eqnum' mode will generally fail when the p-th root of NUM +% (i.e. NUM^(1/p)) is larger than min([N1 N2 ... Np]). Thus 'eqdist' is +% the more useful choice for sampling an arbitrary number of samples +% from the matrix (up to the total number of matrix entries). +% +% 2. In both modes, the equality (of the distance between samples, or +% the number of samples in each dimension) is only approximate. This is +% because REGGRID attempts to maintain the appropriate equality while at +% the same time find a sampling pattern where the total number of +% samples is as close as possible to NUM. In general, the larger {Ni} +% and NUM are, the tighter the equality. +% +% Example: Sample a set of blocks uniformly from a 2D image. +% +% n = 512; blocknum = 20000; blocksize = [8 8]; +% im = rand(n,n); +% [i1,i2] = reggrid(size(im)-blocksize+1, blocknum); +% blocks = sampgrid(im, blocksize, i1, i2); +% +% See also SAMPGRID. + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% November 2007 + +dim = length(sz); + +if (nargin<3) + mode = 'eqdist'; +end + +if (any(sz<1)) + error(['Invalid matrix size : [' num2str(sz) ']']); +end + +if (num > prod(sz)) + warning(['Invalid number of samples, returning maximum number of samples.']); +elseif (num <= 0) + if (num < 0) + warning('Invalid number of samples, assuming 0 samples.'); + end + for i = 1:length(sz) + varargout{i} = []; + end + return; +end + + +if (strcmp(mode,'eqdist')) + + % approximate distance between samples: total volume divided by number of + % samples gives the average volume per sample. then, taking the p-th root + % gives the average distance between samples + d = (prod(sz)/num)^(1/dim); + + % compute the initial guess for number of samples in each dimension. + % then, while total number of samples is too large, decrese the number of + % samples by one in the dimension where the samples are the most crowded. + % finally, do the opposite process until just passing num, so the final + % number of samples is the closest to num from above. + + n = min(max(round(sz/d),1),sz); % set n so that it saturates at 1 and sz + + active_dims = find(n>1); % dimensions where the sample num can be reduced + while(prod(n)>num && ~isempty(active_dims)) + [y,id] = min((sz(active_dims)-1)./n(active_dims)); + n(active_dims(id)) = n(active_dims(id))-1; + if (n(active_dims(id)) < 2) + active_dims = find(n>1); + end + end + + active_dims = find(n= sz(active_dims(id))) + active_dims = find(n1); + while(prod(n)>num && ~isempty(active_dims)) + [y,id] = min((sz(active_dims)-1)./n(active_dims)); + n(active_dims(id)) = n(active_dims(id))-1; + if (n(active_dims(id)) < 2) + active_dims = find(n>1); + end + end + + active_dims = find(n= sz(active_dims(id))) + active_dims = find(n 1) { + mexErrMsgTxt("Too many output arguments."); + } + + + /* Check the input dimensions */ + + m = mxGetM(A_IN); + n = mxGetN(A_IN); + if (!mxIsDouble(A_IN) || mxIsComplex(A_IN) || mxGetNumberOfDimensions(A_IN)>2) { + mexErrMsgTxt("ROWLINCOMB requires that A be a double matrix."); + } + + m1 = mxGetM(ROWS_IN); + n1 = mxGetN(ROWS_IN); + if (!mxIsDouble(ROWS_IN) || mxIsComplex(ROWS_IN) || (m1!=1 && n1!=1)) { + mexErrMsgTxt("ROWLINCOMB requires that ROWS be an index vector of type double."); + } + rownum = (m1 > n1) ? m1 : n1; /* the number of rows in the linear combination */ + + m2 = mxGetM(X_IN); + n2 = mxGetN(X_IN); + if (!mxIsDouble(X_IN) || mxIsComplex(X_IN) || ((m2!=1) && (n2!=1))) { + mexErrMsgTxt("ROWLINCOMB requires that X be a double vector."); + } + + if (m2 != rownum && n2 != rownum) { + mexErrMsgTxt("The length of X does not match the number of rows in ROWS."); + } + + if (nrhs==4) { + m1 = mxGetM(COLS_IN); + n1 = mxGetN(COLS_IN); + if (!mxIsDouble(COLS_IN) || mxIsComplex(COLS_IN) || (m1!=1 && n1!=1)) { + mexErrMsgTxt("ROWLINCOMB requires that COLS be an index vector of type double."); + } + colnum = (m1 > n1) ? m1 : n1; /* the number of columns */ + colnumspecified = 1; + cols = mxGetPr(COLS_IN); + + Y_OUT = mxCreateDoubleMatrix(1, colnum, mxREAL); + } + else { + cols = 0; + Y_OUT = mxCreateDoubleMatrix(1, n, mxREAL); + } + + + /* Assign pointers to the various parameters */ + A = mxGetPr(A_IN); + rows = mxGetPr(ROWS_IN); + x = mxGetPr(X_IN); + y = mxGetPr(Y_OUT); + + + /* check row indices */ + + row_ids = (mwIndex*)mxMalloc(rownum*sizeof(mwIndex)); + + for (i=0; i=m) { + mexErrMsgTxt("Row index in ROWS is out of range."); + } + } + + + + if (colnumspecified) { + + /* check column indices */ + col_ids = (mwIndex*)mxMalloc(colnum*sizeof(mwIndex)); + + for (i=0; i=n) { + mexErrMsgTxt("Column index in COLS is out of range."); + } + } + + /* Do the actual computation */ + for (j=0; j 0 is above the main diagonal and K < 0 +% is below the main diagonal. +% +% SPDIAG(V) is the same as SPDIAG(V,0) and puts V on the main diagonal. +% +% See also DIAG, SPDIAGS. + + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% June 2008 + + +if (nargin<2) + K = 0; +end + +n = length(V) + abs(K); + +if (K>0) + i = 1:length(V); + j = K+1:n; +elseif (K<0) + i = -K+1:n; + j = 1:length(V); +else + i = 1:n; + j = 1:n; +end + +Y = sparse(i,j,V(:),n,n); \ No newline at end of file diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/timerclear.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/timerclear.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,37 @@ +function timerclear() +%TIMERCLEAR Clear all timers. +% TIMERCLEAR clears all currenly registered timers, invalidating all +% timer ids. +% +% Note: since registered timers do not consume CPU power except for when +% the TIMER<*> functions are called, this function is only useful in +% situations where a large number of timers have been initialized, and +% there is a need to reclaim memory. +% +% See also TIMERINIT, TIMERETA. + + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% June 2008 + + +global utiltbx_timer_start_times % start times +global utiltbx_time_lastdisp % last display times +global utiltbx_timer_iternums % iteration numbers +global utiltbx_timer_lastiter % last queried iteration numbers +global utiltbx_timer_name % timer names +global utiltbx_timer_callfun % timer calling functions + + +% clear all timers % + +utiltbx_timer_start_times = []; +utiltbx_time_lastdisp = []; +utiltbx_timer_iternums = []; +utiltbx_timer_lastiter = []; +utiltbx_timer_name = []; +utiltbx_timer_callfun = []; diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/timereta.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/timereta.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,98 @@ +function varargout = timereta(tid,iter,delay) +%TIMERETA Estimated remaining time. +% S = TIMERETA(TID,ITER) returns the estimated remaining time (in +% seconds) for the process associated with timer TID, assuming the +% process has completed ITER iterations. Note: the function will exit +% with an error if the timer TID does not have an associated number of +% iterations (see function TIMERINIT). +% +% [H,M,S] = TIMERETA(TID,ITER) returns the estimated remaining time in +% hours, minutes and seconds. +% +% TIMERETA(TID,ITER), with no output arguments, prints the estimated +% remaining time to the screen. The time is displayed in the format +% +% TIMERNAME: iteration ITER / ITERNUM, estimated remaining time: HH:MM:SS.SS +% +% If the timer has no assigned name, the display format changes to +% +% Iteration ITER / ITERNUM, estimated remaining time: HH:MM:SS.SS +% +% TIMERETA(TID,ITER,DELAY) only displays the remaining time if the +% time elapsed since the previous printout is at least DELAY seconds. +% +% See also TIMERINIT, TIMERCLEAR. + + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% June 2008 + + +global utiltbx_timer_start_times +global utiltbx_timer_iternums +global utiltbx_timer_lastiter +global utiltbx_time_lastdisp +global utiltbx_timer_name + + +if (tid<1 || tid>length(utiltbx_timer_iternums)) + error('Unknown timer id'); +end + +if (utiltbx_timer_iternums(tid) < 0) + error('Specified timer does not have an associated number of iterations'); +end + +% update last reported iteration number +utiltbx_timer_lastiter(tid) = iter; + +% compute elapsed time +starttime = utiltbx_timer_start_times(tid,:); +currtime = clock; +timediff = etime(currtime, starttime); + +% total iteration number +iternum = utiltbx_timer_iternums(tid); + +% compute eta +timeremain = (iternum-iter)*timediff/iter; + +% return eta in seconds +if (nargout==1) + varargout{1} = timeremain; + +% return eta in hms +elseif (nargout==3) + [varargout{1}, varargout{2}, varargout{3}] = secs2hms(timeremain); + + +% print eta +elseif (nargout==0) + + % check last display time + lastdisptime = utiltbx_time_lastdisp(tid,:); + if (nargin>2 && etime(currtime,lastdisptime) < delay) + return; + end + + % update last display time + utiltbx_time_lastdisp(tid,:) = currtime; + + % display timer + [hrs,mins,secs] = secs2hms(timeremain); + if (isempty(utiltbx_timer_name{tid})) + printf('Iteration %d / %d, estimated remaining time: %02d:%02d:%05.2f', iter, iternum, hrs, mins, secs); + else + timername = utiltbx_timer_name{tid}; + printf('%s: iteration %d / %d, estimated remaining time: %02d:%02d:%05.2f', timername, iter, iternum, hrs, mins, secs); + end + +% invalid number of outputs +else + error('Invalid number of output arguments'); +end + diff -r 28f2b5fe3483 -r 207a6ae9a76f Problems/private/timerinit.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Problems/private/timerinit.m Mon Mar 22 15:06:25 2010 +0000 @@ -0,0 +1,110 @@ +function tid = timerinit(par1,par2) +%TIMERINIT Initialize a new timer. +% TID = TIMERINIT() initializes a new timer for counting elapsed time, +% and returns its id. +% +% TID = TIMERINIT('TIMERNAME') sets the timer name to the specified +% string for display purposes. +% +% TID = TIMERINIT(ITERNUM) initializes a new ETA timer for a process with +% ITERNUM iterations. An ETA timer can be used for both counting elapsed +% time and estimating remaining time. +% +% TID = TIMERINIT('TIMERNAME',ITERNUM) sets the ETA timer name to the +% specified string for display purposes. +% +% Example: +% +% tid = timerinit(100); +% for i = 1:100 +% pause(0.07); +% timereta(tid,i,1); +% end +% timereta(tid,i); +% +% See also TIMERETA, TIMERCLEAR. + + +% Ron Rubinstein +% Computer Science Department +% Technion, Haifa 32000 Israel +% ronrubin@cs +% +% June 2008 + + +global utiltbx_timer_start_times % start times +global utiltbx_time_lastdisp % last display times +global utiltbx_timer_iternums % iteration numbers +global utiltbx_timer_lastiter % last queried iteration numbers +global utiltbx_timer_name % timer names +global utiltbx_timer_callfun % timer calling functions + + +% parse function arguments % + +if (nargin==0) + + iternum = -1; + timername = ''; + +elseif (nargin==1) + + if (ischar(par1)) + iternum = -1; + timername = par1; + + elseif (isnumeric(par1) && numel(par1)==1 && par1>0) + iternum = par1; + timername = ''; + + else + error('Invalid number of iterations'); + end + +elseif (nargin==2) + + if (ischar(par1) && isnumeric(par2)) + if (numel(par2)==1 && par2>0) + timername = par1; + iternum = par2; + else + error('Invalid number of iterations'); + end + else + error('Invalid function syntax'); + end + +else + error('Too many function parameters'); +end + + +% register the timer % + +if (isempty(utiltbx_timer_start_times)) + utiltbx_timer_start_times = clock; + utiltbx_time_lastdisp = utiltbx_timer_start_times; + utiltbx_timer_iternums = double(iternum); + utiltbx_timer_lastiter = 0; + utiltbx_timer_name = { timername }; + utiltbx_timer_callfun = {}; + tid = 1; +else + utiltbx_timer_start_times(end+1,:) = clock; + utiltbx_time_lastdisp(end+1,:) = utiltbx_timer_start_times(end,:); + utiltbx_timer_iternums(end+1) = double(iternum); + utiltbx_timer_lastiter(end+1) = 0; + utiltbx_timer_name{end+1} = timername; + tid = size(utiltbx_timer_start_times,1); +end + + +% detect timer calling function % + +st = dbstack; +if (length(dbstack) >= 2) + utiltbx_timer_callfun{end+1} = st(2).name; +else + utiltbx_timer_callfun{end+1} = ''; +end