/normxcorr/trunk

To get this branch, use:
bzr branch http://suren.me/webbzr/normxcorr/trunk
1 by Suren A. Chilingaryan
Initial import
1
function [validx,validy]=automate_image(grid_x,grid_y,filenamelist,validx,validy);
2
3
% Code to start actual image correlation
4
% Programmed by Chris and Rob
5
% Last revision: 09/10/08
6
7
% The automation function is the central function and processes all markers and 
8
% images by the use of the matlab function cpcorr.m. 
9
% Therefore the Current directory in matlab has to be the folder where 
10
%  automate_image.m finds the filenamelist.mat, grid_x.dat and grid_y.dat as well 
11
% as the images specified in filenamelist.mat. Just type automate_image; and 
12
% press ENTER at the command line of matlab. 
13
% At first, automate_image.m will open the first image in the filenamelist.mat and 
14
% plot the grid as green crosses on top. The next step will need some time since 
15
% all markers in that image have to be processed for the first image. After correlating 
16
% image one and two the new raster positions will be plotted as red crosses. On top 
17
% of the image and the green crosses. The next dialog will ask you if you want to 
18
% continue with this correlation or cancel. If you press continue, automate_image.m 
19
% will process all images in the filenamelist.mat. The time it will take to process 
20
% all images will be plotted on the figure but can easily be estimated by knowing the 
21
% raster point processing speed (see processing speed). 
22
% Depending on the number of images and markers you are tracking, this process 
23
% can take between seconds and days. For 100 images and 200 markers a decent 
24
% computer should need 200 seconds. To get a better resolution you can always 
25
% run jobs overnight (e.g. 6000 markers in 1000 images) with higher resolutions. 
26
% Keep in mind that CORRSIZE which you changed in cpcorr.m will limit your 
27
% resolution. If you chose to use the 15 pixel as suggested a marker distance of 
28
% 30 pixel will lead to a full cover of the strain field. Choosing smaller marker 
29
% distances will lead to an interpolation since two neighboring markers share 
30
% pixels. Nevertheless a higher marker density can reduce the noise of the strain field.
31
% When all images are processed, automate_image will write the files validx.mat, 
32
% validy.mat, validx.txt and validy.txt. The text files are meant to store the result in a 
33
% format which can be accessed by other programs also in the future.
34
2 by Suren A. Chilingaryan
Support for different optimization modes
35
% Changed by Suren A. Chilingaryan <csa@dside.dyndns.org> to optimize performance
36
% by tighter integration with Matlab images toolkit (few sources from the toolkit
37
% are moved to the current source tree and adjusted to benefit from knowledge of 
38
% tasks we are solving here. As well CUDA framework, if available, is used to
39
% speed-up core computations using parallel processors of latest NVidia video
40
% cards.
41
% OPTIMIZE parameter is controlling which optimizations should be used. 
42
%  0 - The original version, no optimizations
43
%  1 - The modified sources from images toolkit are used
44
%  2 - The CUDA matlab plugin is used to compute FFT's
45
%  3 - Most of computations are performed on NVidia card
46
% You can safely set an optimization level to 3. If NVidia card is not available
47
% the level will be automatically reduced to 1.
6 by Suren A. Chilingaryan
A little more computations are moved to CUDA
48
%
49
% SAVEDATA controls if data is saved per iteration or at the end
50
% 0 - in the end
51
% 1 - per iteration
2 by Suren A. Chilingaryan
Support for different optimization modes
52
53
OPTIMIZE = 3;
54
CORRSIZE = 15;	
1 by Suren A. Chilingaryan
Initial import
55
PRECISION = 1000;
4 by Suren A. Chilingaryan
Instead of transfer compute local sums and denormals on board
56
SILENT = 1;
6 by Suren A. Chilingaryan
A little more computations are moved to CUDA
57
SAVEDATA = 0;
2 by Suren A. Chilingaryan
Support for different optimization modes
58
1 by Suren A. Chilingaryan
Initial import
59
% exist('grid_x')
60
% exist('grid_y')
61
% exist('filenamelist')
62
% exist('validx')
63
% exist('validy')
64
65
if exist('data', 'dir')
66
    datadir = 'data/';
67
else
68
    datadir = '';
69
end
70
71
if exist('images', 'dir')
72
    imagedir = 'images/';
73
else
74
    imagedir = '';
75
end
76
77
% Load necessary files
78
if exist('grid_x')==0
79
    load([datadir, 'grid_x.dat'])              % file with x position, created by grid_generator.m
80
end
81
if exist('grid_y')==0
82
    load([datadir, 'grid_y.dat'])              % file with y position, created by grid_generator.m
83
end
84
if exist('filenamelist')==0
85
    load([datadir, 'filenamelist'])            % file with the list of filenames to be processed
86
end
87
88
89
resume=0;
90
if exist('validx')==1
91
    if exist('validy')==1
92
        resume=1;
93
        [Rasternum Imagenum]=size(validx);
94
    end
95
end
96
97
[r,c]=size(filenamelist);           % this will determine the number of images we have to loop through
98
99
% Open new figure so previous ones (if open) are not overwritten
100
if (~SILENT)
101
    h=figure;
102
    imshow([imagedir, filenamelist(1,:)])           % show the first image
103
    title('Initial Grid For Image Correlation (Note green crosses)')        % put a title
104
    hold on
105
    plot(grid_x,grid_y,'g+')            % plot the grid onto the image
106
    hold off
107
108
    % Start image correlation using cpcorr.m
109
    g = waitbar(0,sprintf('Processing images'));        % initialize the waitbar
110
    set(g,'Position',[275,50,275,50])                   % set the position of the waitbar [left bottom width height]
111
end
112
113
firstimage=1;
114
115
if resume==1
116
    firstimage=Imagenum+1
117
end
118
119
%Initializing hardware code
120
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
121
ncp = prod(size(grid_x));
1 by Suren A. Chilingaryan
Initial import
122
2 by Suren A. Chilingaryan
Support for different optimization modes
123
if OPTIMIZE > 2
124
    hwid = normxcorr_hw();
4 by Suren A. Chilingaryan
Instead of transfer compute local sums and denormals on board
125
2 by Suren A. Chilingaryan
Support for different optimization modes
126
    if hwid > 0
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
127
	err = normxcorr_hw(hwid, 1, ncp, CORRSIZE, PRECISION);
3 by Suren A. Chilingaryan
Add error checking to initialization process
128
	if (err ~= 0)
129
	    normxcorr_hw(1);
130
	    OPTIMIZE = 2;
131
	end
2 by Suren A. Chilingaryan
Support for different optimization modes
132
    else
133
	if hwid < 0
134
	    OPTIMIZE = 1;
135
	else
136
	    OPTIMIZE = 2;
137
	end
138
    end
139
else
140
    hwid = 0;
141
end
1 by Suren A. Chilingaryan
Initial import
142
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
143
% Initialize variables
144
if OPTIMIZE>2
145
    base_points_x=single(grid_x);
146
    base_points_y=single(grid_y);
147
else
148
    base_points_x=grid_x;
149
    base_points_y=grid_y;
150
end
151
152
if resume==1
153
    if OPTIMIZE>2
154
	input_points_x=single(validx(:,Imagenum));
155
	input_points_y=single(validy(:,Imagenum));
156
    else
157
	input_points_x=validx(:,Imagenum);
158
	input_points_y=validy(:,Imagenum);
159
    end
160
    inputpoints=1;
161
else
162
    if OPTIMIZE>2
163
	input_points_x=single(grid_x);
164
	input_points_y=single(grid_y);
165
    else
166
	input_points_x=grid_x;
167
	input_points_y=grid_y;
168
    end
169
end
170
171
base = uint8(mean(double(imread([imagedir, filenamelist(1,:)])),3));            % read in the base image ( which is always  image number one. You might want to change that to improve correlation results in case the light conditions are changing during the experiment
172
173
if OPTIMIZE > 2
4 by Suren A. Chilingaryan
Instead of transfer compute local sums and denormals on board
174
%    crop_dim = [min(base_points_x(:)) - 2*CORRSIZE, min(base_points_y(:)) - 2 * CORRSIZE, max(base_points_x(:)) + 2*CORRSIZE, max(base_points_y(:)) + 2 * CORRSIZE]
175
%    crop_size = (crop_dim(3) - crop_dim(1)) * (crop_dim(4) - crop_dim(2))
176
%    mesh_size = ncp * 4 * CORRSIZE * CORRSIZE
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
177
178
%    Verification of GPU local sum and denom computations
179
%    dic_basecorr3(CORRSIZE, PRECISION, OPTIMIZE, hwid, base_points_x, base_points_y, base);
180
181
    data_base = struct;
182
    base_points_for(:,1)=reshape(base_points_x,[],1);
183
    base_points_for(:,2)=reshape(base_points_y,[],1);
184
    for icp = 1:ncp
185
	data_base(icp).base_fractional_offset = base_points_for(icp,:) - round(base_points_for(icp,:)*PRECISION)/PRECISION;
1 by Suren A. Chilingaryan
Initial import
186
    end
187
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
188
    normxcorr_hw(hwid, 3, base_points_x, base_points_y);
189
    normxcorr_hw(hwid, 4, base);
190
191
    normxcorr_hw(hwid, 5);
192
else
193
  base_points_for(:,1)=reshape(base_points_x,[],1);
194
  base_points_for(:,2)=reshape(base_points_y,[],1);
195
196
  %some checks (moved here from cpcorr)
197
  if any(base_points_for(:)<0.5) || any(base_points_for(:,1)>size(base,2)+0.5) || any(base_points_for(:,2)>size(base,1)+0.5)
198
    msg = sprintf('In function %s, Control Points must be in pixel coordinates.',mfilename);
199
    eid = sprintf('Images:%s:cpPointsMustBeInPixCoord',mfilename);
200
    error(eid, msg);
201
  end
202
203
  if OPTIMIZE > 0
204
     data_base = struct;
1 by Suren A. Chilingaryan
Initial import
205
    
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
206
     %moved from normxcorr2
207
     % We can precalculate it here, since near-edge images are dropped and, therefore, A,T always have the same size 
208
     % n is width and height of T, but following computations are done for A
209
     % outsize is sum if widths and heights of T and A - 1 (outsize = size(A) + size(T) - 1)
210
211
     outsize = 6 * CORRSIZE + 1;
212
     n = 2*CORRSIZE + 1;
213
     mn = n*n;
214
215
     rects_base = dic_calc_rects(base_points_for,2*CORRSIZE,base);
216
217
     for icp = 1:ncp
218
	if isequal(rects_base(icp,3:4),[0 0])
219
	    %near edge
220
	    data_base(icp).skip = 1;
221
	    continue
4 by Suren A. Chilingaryan
Instead of transfer compute local sums and denormals on board
222
	end
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
223
224
	sub_base = imcrop(base,rects_base(icp,:));
225
    
226
	data_base(icp).skip = 0;
227
4 by Suren A. Chilingaryan
Instead of transfer compute local sums and denormals on board
228
	double_sub_base = double(sub_base);
229
230
	if (numel(sub_base) < 2) ||  (std(double_sub_base(:)) == 0)
231
	    % This check is moved here for normxcorr2
232
	    eid = sprintf('Images:%s:sameElementsInTemplate',mfilename);
233
	    msg = 'The values of TEMPLATE cannot all be the same.';
234
	    error(eid,'%s',msg);
235
	end
236
237
	local_sum_A = dic_local_sum(double_sub_base,n,n);
238
	local_sum_A2 = dic_local_sum(double_sub_base.*double_sub_base,n,n);
239
240
	% Note: diff_local_sums should be nonnegative, but may have negative
241
	% values due to round off errors. Below, we use max to ensure the
242
	% radicand is nonnegative.
243
	denom_A = sqrt( max(( local_sum_A2 - (local_sum_A.^2)/mn ) / (mn-1), 0) );
244
	i_nonzero = find(denom_A~=0);
245
    
2 by Suren A. Chilingaryan
Support for different optimization modes
246
	data_base(icp).denom_A = denom_A;
247
	data_base(icp).i_nonzero = i_nonzero;
248
249
	data_base(icp).local_sum_A = local_sum_A;
250
	data_base(icp).sub_base = sub_base;
251
	
252
	if (OPTIMIZE > 1)
253
	    data_base(icp).sub_base_fft = fft2_cuda(double_sub_base, outsize, outsize);
254
	else
255
	    data_base(icp).sub_base_fft = fft2(double_sub_base, outsize, outsize);
256
	end
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
257
258
	data_base(icp).base_fractional_offset = base_points_for(icp,:) - round(base_points_for(icp,:)*PRECISION)/PRECISION;
2 by Suren A. Chilingaryan
Support for different optimization modes
259
    end
260
  end
1 by Suren A. Chilingaryan
Initial import
261
end
262
263
%normxcorr_hw(hwid);
264
%return;
265
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
266
if OPTIMIZE > 2
267
    normxcorr_hw(hwid, 12, input_points_x, input_points_y);
268
else
6 by Suren A. Chilingaryan
A little more computations are moved to CUDA
269
    input_correl(:,1)=reshape(input_points_x,[],1);         % we reshape the input points to one row of values since this is the shape cpcorr will accept
270
    input_correl(:,2)=reshape(input_points_y,[],1);
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
271
end
6 by Suren A. Chilingaryan
A little more computations are moved to CUDA
272
1 by Suren A. Chilingaryan
Initial import
273
for i=firstimage:(r-1)               % run through all images
274
    tic             % start the timer
275
276
    input = uint8(mean(double(imread([imagedir, filenamelist((i+1),:)])),3));       % read in the image which has to be correlated
277
6 by Suren A. Chilingaryan
A little more computations are moved to CUDA
278
    if OPTIMIZE > 2
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
279
	%Validate findpeak
280
	%dic_cpcorr3(CORRSIZE, PRECISION, OPTIMIZE, hwid, ncp, input);
281
282
	normxcorr_hw(hwid, 13, input)
283
	input_correl = normxcorr_hw(hwid, 14);
6 by Suren A. Chilingaryan
A little more computations are moved to CUDA
284
    elseif OPTIMIZE > 0
285
	input_correl(:,:)=dic_cpcorr(CORRSIZE, PRECISION, OPTIMIZE, hwid, data_base, input_correl, input);
2 by Suren A. Chilingaryan
Support for different optimization modes
286
    else
6 by Suren A. Chilingaryan
A little more computations are moved to CUDA
287
	input_correl(:,:)=cpcorr(input_correl, base_points_for, input, base);
288
    end
8 by Suren A. Chilingaryan
Complete elimination of cpcorr
289
290
    %We need to copy
6 by Suren A. Chilingaryan
A little more computations are moved to CUDA
291
    validx(:,i)=double(input_correl(:,1));                                       % the results we get from cpcorr for the x-direction
292
    validy(:,i)=double(input_correl(:,2));                                       % the results we get from cpcorr for the y-direction
293
294
    if (SAVEDATA)    
295
	savelinex=validx(:,i)';
296
	dlmwrite([datadir, 'resultsimcorrx.txt'], savelinex , 'delimiter', '\t', '-append');       % Here we save the result from each image; if you are desperately want to run this function with e.g. matlab 6.5 then you should comment this line out. If you do that the data will be saved at the end of the correlation step - good luck ;-)
297
    
298
	saveliney=validy(:,i)';
299
	dlmwrite([datadir, 'resultsimcorry.txt'], saveliney , 'delimiter', '\t', '-append');
300
    end
1 by Suren A. Chilingaryan
Initial import
301
    
302
    if (~SILENT) 
303
	waitbar(i/(r-1))                                % update the waitbar
304
305
	imshow([imagedir, filenamelist(i+1,:)])                     % update image
306
	hold on
307
	plot(grid_x,grid_y,'g+')                                % plot start position of raster
6 by Suren A. Chilingaryan
A little more computations are moved to CUDA
308
	plot(input_correl(:,1),input_correl(:,2),'r+')        % plot actual postition of raster
1 by Suren A. Chilingaryan
Initial import
309
	hold off
310
	drawnow
311
	time(i)=toc;                                                 % take time
312
	estimatedtime=sum(time)/i*(r-1);            % estimate time to process
313
	title(['# Im.: ', num2str((r-1)),'; Proc. Im. #: ', num2str((i)),'; # Rasterp.:',num2str(row*col), '; Est. Time [s] ', num2str(round(estimatedtime)), ';  Elapsed Time [s] ', num2str(round(sum(time)))]);    % plot a title onto the image
314
	drawnow
315
    end
316
end    
317
2 by Suren A. Chilingaryan
Support for different optimization modes
318
if OPTIMIZE > 2
319
    normxcorr_hw(hwid);
320
end
1 by Suren A. Chilingaryan
Initial import
321
322
if (~SILENT)
323
    close(g)
324
end
325
326
close all
327
328
% save
329
330
if (~SILENT)
331
    save ([datadir,'time.dat'], 'time', '-ascii', '-tabs');
332
end
333
334
save ([datadir,'validx.dat'], 'validx', '-ascii', '-tabs');
335
save ([datadir,'validy.dat'], 'validy', '-ascii', '-tabs');