zhaxie commited on
Commit
9b344a2
·
verified ·
1 Parent(s): fcd99cd

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. UVDoc_official/__pycache__/compute_uvdoc_grid3d_stats.cpython-313.pyc +0 -0
  2. UVDoc_official/__pycache__/data_UVDoc.cpython-312.pyc +0 -0
  3. UVDoc_official/__pycache__/data_doc3D.cpython-310.pyc +0 -0
  4. UVDoc_official/__pycache__/data_mixDataset.cpython-310.pyc +0 -0
  5. UVDoc_official/__pycache__/data_utils.cpython-310.pyc +0 -0
  6. UVDoc_official/__pycache__/model.cpython-310.pyc +0 -0
  7. UVDoc_official/__pycache__/train.cpython-310.pyc +0 -0
  8. UVDoc_official/__pycache__/train.cpython-313.pyc +0 -0
  9. UVDoc_official/__pycache__/utils.cpython-310.pyc +0 -0
  10. UVDoc_official/__pycache__/verify_ckpt_val_pipeline.cpython-313.pyc +0 -0
  11. UVDoc_official/eval/eval_code/SIFTflow/SIFTflowc2f.m +180 -0
  12. UVDoc_official/eval/eval_code/SIFTflow/computeColor.m +115 -0
  13. UVDoc_official/eval/eval_code/SIFTflow/demo.asv +52 -0
  14. UVDoc_official/eval/eval_code/SIFTflow/demo.m +52 -0
  15. UVDoc_official/eval/eval_code/SIFTflow/flowToColor.m +88 -0
  16. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/Image.h +1788 -0
  17. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/ImageFeature.h +283 -0
  18. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/ImageIO.h +343 -0
  19. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/ImageProcessing.h +414 -0
  20. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/Matrix.cpp +419 -0
  21. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/Matrix.h +92 -0
  22. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/Vector.cpp +285 -0
  23. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/Vector.h +73 -0
  24. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/dir.cpp +121 -0
  25. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/dir.h +24 -0
  26. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/mexDenseSIFT.cpp +47 -0
  27. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/mexDenseSIFT.m +19 -0
  28. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/mexDenseSIFT.mexa64 +0 -0
  29. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/mexDenseSIFT.mexmaci64 +0 -0
  30. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/mexDenseSIFT.mexw64 +0 -0
  31. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/project.h +47 -0
  32. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/readme.txt +12 -0
  33. UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/showColorSIFT.m +23 -0
  34. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/BPFlow.cpp +1084 -0
  35. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/BPFlow.h +246 -0
  36. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/Image.h +1574 -0
  37. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/ImageIO.h +200 -0
  38. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/ImageProcessing.h +387 -0
  39. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/Stochastic.cpp +107 -0
  40. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/Stochastic.h +410 -0
  41. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/main.cpp +86 -0
  42. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/mexDiscreteFlow.cpp +130 -0
  43. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/mexDiscreteFlow.m +47 -0
  44. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/mexDiscreteFlow.mexa64 +0 -0
  45. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/mexDiscreteFlow.mexmaci64 +0 -0
  46. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/mexDiscreteFlow.mexw64 +0 -0
  47. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/project.h +46 -0
  48. UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/readme.txt +12 -0
  49. UVDoc_official/eval/eval_code/SIFTflow/readme.txt +24 -0
  50. UVDoc_official/eval/eval_code/SIFTflow/warpFL.m +7 -0
UVDoc_official/__pycache__/compute_uvdoc_grid3d_stats.cpython-313.pyc ADDED
Binary file (4.22 kB). View file
 
UVDoc_official/__pycache__/data_UVDoc.cpython-312.pyc ADDED
Binary file (7.26 kB). View file
 
UVDoc_official/__pycache__/data_doc3D.cpython-310.pyc ADDED
Binary file (3.01 kB). View file
 
UVDoc_official/__pycache__/data_mixDataset.cpython-310.pyc ADDED
Binary file (1.2 kB). View file
 
UVDoc_official/__pycache__/data_utils.cpython-310.pyc ADDED
Binary file (4.71 kB). View file
 
UVDoc_official/__pycache__/model.cpython-310.pyc ADDED
Binary file (6.4 kB). View file
 
UVDoc_official/__pycache__/train.cpython-310.pyc ADDED
Binary file (12 kB). View file
 
UVDoc_official/__pycache__/train.cpython-313.pyc ADDED
Binary file (18 kB). View file
 
UVDoc_official/__pycache__/utils.cpython-310.pyc ADDED
Binary file (2.34 kB). View file
 
UVDoc_official/__pycache__/verify_ckpt_val_pipeline.cpython-313.pyc ADDED
Binary file (8.03 kB). View file
 
UVDoc_official/eval/eval_code/SIFTflow/SIFTflowc2f.m ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ % function to do coarse to fine SIFT flow matching
2
+ function [vx,vy,energylist]=SIFTflowc2f(im1,im2,SIFTflowpara,isdisplay,Segmentation)
3
+
4
+ if isfield(SIFTflowpara,'alpha')
5
+ alpha=SIFTflowpara.alpha;
6
+ else
7
+ alpha=0.01;
8
+ end
9
+
10
+ if isfield(SIFTflowpara,'d')
11
+ d=SIFTflowpara.d;
12
+ else
13
+ d=alpha*20;
14
+ end
15
+
16
+ if isfield(SIFTflowpara,'gamma')
17
+ gamma=SIFTflowpara.gamma;
18
+ else
19
+ gamma=0.001;
20
+ end
21
+
22
+ if isfield(SIFTflowpara,'nlevels')
23
+ nlevels=SIFTflowpara.nlevels;
24
+ else
25
+ nlevels=4;
26
+ end
27
+
28
+ if isfield(SIFTflowpara,'wsize')
29
+ wsize=SIFTflowpara.wsize;
30
+ else
31
+ wsize=3;
32
+ end
33
+
34
+ if isfield(SIFTflowpara,'topwsize')
35
+ topwsize=SIFTflowpara.topwsize;
36
+ else
37
+ topwsize=10;
38
+ end
39
+
40
+ if isfield(SIFTflowpara,'nIterations')
41
+ nIterations=SIFTflowpara.nIterations;
42
+ else
43
+ nIterations=40;
44
+ end
45
+
46
+ if isfield(SIFTflowpara,'nTopIterations')
47
+ nTopIterations=SIFTflowpara.nTopIterations;
48
+ else
49
+ nTopIterations=100;
50
+ end
51
+
52
+ if exist('isdisplay','var')~=1
53
+ isdisplay=false;
54
+ end
55
+
56
+ if exist('Segmentation','var')==1
57
+ IsSegmentation=true;
58
+ else
59
+ IsSegmentation=false;
60
+ end
61
+
62
+ % build the pyramid
63
+ pyrd(1).im1=im1;
64
+ pyrd(1).im2=im2;
65
+ if IsSegmentation
66
+ pyrd(1).seg=Segmentation;
67
+ end
68
+
69
+ for i=2:nlevels
70
+ pyrd(i).im1=imresize(imfilter(pyrd(i-1).im1,fspecial('gaussian',5,0.67),'same','replicate'),0.5,'bicubic');
71
+ pyrd(i).im2=imresize(imfilter(pyrd(i-1).im2,fspecial('gaussian',5,0.67),'same','replicate'),0.5,'bicubic');
72
+ % pyrd(i).im1 = reduceImage(pyrd(i-1).im1);
73
+ % pyrd(i).im2 = reduceImage(pyrd(i-1).im2);
74
+ if IsSegmentation
75
+ pyrd(i).seg=imresize(pyrd(i-1).seg,0.5,'nearest');
76
+ end
77
+ end
78
+
79
+ for i=1:nlevels
80
+ [height,width,nchannels]=size(pyrd(i).im1);
81
+ [height2,width2,nchannels]=size(pyrd(i).im2);
82
+ [xx,yy]=meshgrid(1:width,1:height);
83
+ pyrd(i).xx=round((xx-1)*(width2-1)/(width-1)+1-xx);
84
+ pyrd(i).yy=round((yy-1)*(height2-1)/(height-1)+1-yy);
85
+ end
86
+
87
+ nIterationArray=round(linspace(nIterations,nIterations,nlevels));
88
+
89
+ for i=nlevels:-1:1
90
+ if isdisplay
91
+ fprintf('Level: %d...',i);
92
+ end
93
+ [height,width,nchannels]=size(pyrd(i).im1);
94
+ [height2,width2,nchannels]=size(pyrd(i).im2);
95
+ [xx,yy]=meshgrid(1:width,1:height);
96
+
97
+ if i==nlevels
98
+ % vx=zeros(height,width);
99
+ % vy=vx;
100
+ vx=pyrd(i).xx;
101
+ vy=pyrd(i).yy;
102
+
103
+ winSizeX=ones(height,width)*topwsize;
104
+ winSizeY=ones(height,width)*topwsize;
105
+ else
106
+ % vx=imresize(vx-pyrd(i+1).xx,[height,width],'bicubic')*2+pyrd(i).xx;
107
+ % vy=imresize(vy-pyrd(i+1).yy,[height,width],'bicubic')*2+pyrd(i).yy;
108
+
109
+ % winSizeX=decideWinSize(vx,wsize);
110
+ % winSizeY=decideWinSize(vy,wsize);
111
+ vx=round(pyrd(i).xx+imresize(vx-pyrd(i+1).xx,[height,width],'bicubic')*2);
112
+ vy=round(pyrd(i).yy+imresize(vy-pyrd(i+1).yy,[height,width],'bicubic')*2);
113
+
114
+ winSizeX=ones(height,width)*(wsize+i-1);
115
+ winSizeY=ones(height,width)*(wsize+i-1);
116
+ end
117
+ if nchannels<=3
118
+ Im1=im2feature(pyrd(i).im1);
119
+ Im2=im2feature(pyrd(i).im2);
120
+ else
121
+ Im1=pyrd(i).im1;
122
+ Im2=pyrd(i).im2;
123
+ end
124
+ % compute the image-based coefficient
125
+ if IsSegmentation
126
+ imdiff=zeros(height,width,2);
127
+ imdiff(:,1:end-1,1)=double(pyrd(i).seg(:,1:end-1)==pyrd(i).seg(:,2:end));
128
+ imdiff(1:end-1,:,2)=double(pyrd(i).seg(1:end-1,:)==pyrd(i).seg(2:end,:));
129
+ Im_s=imdiff*alpha+(1-imdiff)*alpha*0.01;
130
+ Im_d=imdiff*alpha*100+(1-imdiff)*alpha*0.01*20;
131
+ end
132
+ if i==nlevels
133
+ if IsSegmentation
134
+ [flow,foo]=mexDiscreteFlow(Im1,Im2,[alpha,d,gamma*2^(i-1),nTopIterations,2,topwsize],vx,vy,winSizeX,winSizeY,Im_s,Im_d);
135
+ else
136
+ [flow,foo]=mexDiscreteFlow(Im1,Im2,[alpha,d,gamma*2^(i-1),nTopIterations,2,topwsize],vx,vy,winSizeX,winSizeY);
137
+ %[flow,foo]=mexDiscreteFlow(Im1,Im2,[alpha,d,gamma*2^(i-1),nTopIterations,0,topwsize],vx,vy,winSizeX,winSizeY);
138
+ end
139
+ % [flow1,foo1]=mexDiscreteFlow(Im1,Im2,[alpha,d,gamma*2^(i-1),nIterationArray(i),0,topwsize],vx,vy,winSizeX,winSizeY);
140
+ % [flow2,foo2]=mexDiscreteFlow(Im1,Im2,[alpha,d,gamma*2^(i-1),nTopIterations,2,topwsize],vx,vy,winSizeX,winSizeY);
141
+ % if foo1(end)<foo2(end)
142
+ % flow=flow1;
143
+ % foo=foo1;
144
+ % else
145
+ % flow=flow2;
146
+ % foo=foo2;
147
+ % end
148
+ else
149
+ %[flow,foo]=mexDiscreteFlow(Im1,Im2,[alpha,d,gamma*2^(i-1),nIterations,nlevels-i,wsize],vx,vy,winSizeX,winSizeY);
150
+ if IsSegmentation
151
+ [flow,foo]=mexDiscreteFlow(Im1,Im2,[alpha,d,gamma*2^(i-1),nIterationArray(i),nlevels-i,wsize],vx,vy,winSizeX,winSizeY,Im_s,Im_d);
152
+ else
153
+ [flow,foo]=mexDiscreteFlow(Im1,Im2,[alpha,d,gamma*2^(i-1),nIterationArray(i),nlevels-i,wsize],vx,vy,winSizeX,winSizeY);
154
+ %[flow,foo]=mexDiscreteFlow(Im1,Im2,[alpha,d,gamma*2^(i-1),nIterationArray(i),0,wsize],vx,vy,winSizeX,winSizeY);
155
+ end
156
+ % [flow,foo]=mexDiscreteFlow(Im1,Im2,[alpha,d,gamma*2^(i-1),nIterationArray(i),0,wsize],vx,vy,winSizeX,winSizeY);
157
+ end
158
+ energylist(i).data=foo;
159
+ vx=flow(:,:,1);
160
+ vy=flow(:,:,2);
161
+ if isdisplay
162
+ fprintf('done!\n');
163
+ end
164
+ end
165
+
166
+ function winSizeIm=decideWinSize(offset,wsize)
167
+
168
+ % design the DOG filter
169
+ f1=fspecial('gaussian',9,1);
170
+ f2=fspecial('gaussian',9,.5);
171
+ f=f2-f1;
172
+
173
+ foo=imfilter(abs(imfilter(offset,f,'same','replicate')),fspecial('gaussian',9,1.5),'same','replicate');
174
+
175
+ Min=min(foo(:));
176
+ Max=max(foo(:));
177
+ winSizeIm=wsize*(foo-Min)/(Max-Min)+wsize;
178
+
179
+
180
+
UVDoc_official/eval/eval_code/SIFTflow/computeColor.m ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function img = computeColor(u,v)
2
+
3
+ % computeColor color codes flow field U, V
4
+
5
+ % According to the c++ source code of Daniel Scharstein
6
+ % Contact: schar@middlebury.edu
7
+
8
+ % Author: Deqing Sun, Department of Computer Science, Brown University
9
+ % Contact: dqsun@cs.brown.edu
10
+ % $Date: 2007-10-31 21:20:30 (Wed, 31 Oct 2006) $
11
+
12
+ % Copyright 2007, Deqing Sun.
13
+ %
14
+ % All Rights Reserved
15
+ %
16
+ % Permission to use, copy, modify, and distribute this software and its
17
+ % documentation for any purpose other than its incorporation into a
18
+ % commercial product is hereby granted without fee, provided that the
19
+ % above copyright notice appear in all copies and that both that
20
+ % copyright notice and this permission notice appear in supporting
21
+ % documentation, and that the name of the author and Brown University not be used in
22
+ % advertising or publicity pertaining to distribution of the software
23
+ % without specific, written prior permission.
24
+ %
25
+ % THE AUTHOR AND BROWN UNIVERSITY DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
26
+ % INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ANY
27
+ % PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR BROWN UNIVERSITY BE LIABLE FOR
28
+ % ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29
+ % WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30
+ % ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31
+ % OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32
+
33
+ nanIdx = isnan(u) | isnan(v);
34
+ u(nanIdx) = 0;
35
+ v(nanIdx) = 0;
36
+
37
+ colorwheel = makeColorwheel();
38
+ ncols = size(colorwheel, 1);
39
+
40
+ rad = sqrt(u.^2+v.^2);
41
+
42
+ a = atan2(-v, -u)/pi;
43
+
44
+ fk = (a+1) /2 * (ncols-1) + 1; % -1~1 maped to 1~ncols
45
+
46
+ k0 = floor(fk); % 1, 2, ..., ncols
47
+
48
+ k1 = k0+1;
49
+ k1(k1==ncols+1) = 1;
50
+
51
+ f = fk - k0;
52
+
53
+ for i = 1:size(colorwheel,2)
54
+ tmp = colorwheel(:,i);
55
+ col0 = tmp(k0)/255;
56
+ col1 = tmp(k1)/255;
57
+ col = (1-f).*col0 + f.*col1;
58
+
59
+ idx = rad <= 1;
60
+ col(idx) = 1-rad(idx).*(1-col(idx)); % increase saturation with radius
61
+
62
+ col(~idx) = col(~idx)*0.75; % out of range
63
+
64
+ img(:,:, i) = uint8(floor(255*col.*(1-nanIdx)));
65
+ end;
66
+
67
+ %%
68
+ function colorwheel = makeColorwheel()
69
+
70
+ % color encoding scheme
71
+
72
+ % adapted from the color circle idea described at
73
+ % http://members.shaw.ca/quadibloc/other/colint.htm
74
+
75
+
76
+ RY = 15;
77
+ YG = 6;
78
+ GC = 4;
79
+ CB = 11;
80
+ BM = 13;
81
+ MR = 6;
82
+
83
+ ncols = RY + YG + GC + CB + BM + MR;
84
+
85
+ colorwheel = zeros(ncols, 3); % r g b
86
+
87
+ col = 0;
88
+ %RY
89
+ colorwheel(1:RY, 1) = 255;
90
+ colorwheel(1:RY, 2) = floor(255*(0:RY-1)/RY)';
91
+ col = col+RY;
92
+
93
+ %YG
94
+ colorwheel(col+(1:YG), 1) = 255 - floor(255*(0:YG-1)/YG)';
95
+ colorwheel(col+(1:YG), 2) = 255;
96
+ col = col+YG;
97
+
98
+ %GC
99
+ colorwheel(col+(1:GC), 2) = 255;
100
+ colorwheel(col+(1:GC), 3) = floor(255*(0:GC-1)/GC)';
101
+ col = col+GC;
102
+
103
+ %CB
104
+ colorwheel(col+(1:CB), 2) = 255 - floor(255*(0:CB-1)/CB)';
105
+ colorwheel(col+(1:CB), 3) = 255;
106
+ col = col+CB;
107
+
108
+ %BM
109
+ colorwheel(col+(1:BM), 3) = 255;
110
+ colorwheel(col+(1:BM), 1) = floor(255*(0:BM-1)/BM)';
111
+ col = col+BM;
112
+
113
+ %MR
114
+ colorwheel(col+(1:MR), 3) = 255 - floor(255*(0:MR-1)/MR)';
115
+ colorwheel(col+(1:MR), 1) = 255;
UVDoc_official/eval/eval_code/SIFTflow/demo.asv ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ % im1=imread('Mars-1.jpg');
2
+ % im2=imread('Mars-2.jpg');
3
+
4
+ im1 = xcell{11, 2};
5
+ im1 = rgb2gray(im1);
6
+ im2 = ycell{11};
7
+ im2 = rgb2gray(im2);
8
+ % im1 = imresize(im1, size(im2));
9
+
10
+ im1=imresize(imfilter(im1,fspecial('gaussian',7,1.),'same','replicate'),0.5,'bicubic');
11
+ im2=imresize(imfilter(im2,fspecial('gaussian',7,1.),'same','replicate'),0.5,'bicubic');
12
+
13
+ im1=im2double(im1);
14
+ im2=im2double(im2);
15
+
16
+ %figure;imshow(im1);figure;imshow(im2);
17
+
18
+ cellsize=3;
19
+ gridspacing=1;
20
+
21
+ addpath(fullfile(pwd,'mexDenseSIFT'));
22
+ addpath(fullfile(pwd,'mexDiscreteFlow'));
23
+
24
+ sift1 = mexDenseSIFT(im1,cellsize,gridspacing);
25
+ sift2 = mexDenseSIFT(im2,cellsize,gridspacing);
26
+
27
+ SIFTflowpara.alpha=2*255;
28
+ SIFTflowpara.d=40*255;
29
+ SIFTflowpara.gamma=0.005*255;
30
+ SIFTflowpara.nlevels=4;
31
+ SIFTflowpara.wsize=2;
32
+ SIFTflowpara.topwsize=10;
33
+ SIFTflowpara.nTopIterations = 60;
34
+ SIFTflowpara.nIterations= 30;
35
+
36
+
37
+ tic;[vx,vy,energylist]=SIFTflowc2f(sift1,sift2,SIFTflowpara);toc
38
+
39
+ warpI2=warpImage(im2,vx,vy);
40
+ figure;imshow(im1);figure;imshow(warpI2);
41
+
42
+ % display flow
43
+ clear flow;
44
+ flow(:,:,1)=vx;
45
+ flow(:,:,2)=vy;
46
+ figure;imshow(flowToColor(flow));
47
+
48
+ return;
49
+
50
+ % this is the code doing the brute force matching
51
+ tic;[flow2,energylist2]=mexDiscreteFlow(Sift1,Sift2,[alpha,alpha*20,60,30]);toc
52
+ figure;imshow(flowToColor(flow2));
UVDoc_official/eval/eval_code/SIFTflow/demo.m ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ im1=imread('Mars-1.jpg');
2
+ im2=imread('Mars-2.jpg');
3
+
4
+ %im1 = ycell{36};
5
+ im1 = rgb2gray(im1);
6
+ %im2 = xcell{36, 2};
7
+ im2 = rgb2gray(im2);
8
+ % im2 = imresize(im2, size(im1));
9
+
10
+ im1=imresize(imfilter(im1,fspecial('gaussian',3,1.),'same','replicate'),1,'bicubic');
11
+ im2=imresize(imfilter(im2,fspecial('gaussian',3,1.),'same','replicate'),1,'bicubic');
12
+
13
+ im1=im2double(im1);
14
+ im2=im2double(im2);
15
+
16
+ %figure;imshow(im1);figure;imshow(im2);
17
+
18
+ cellsize=3;
19
+ gridspacing=1;
20
+
21
+ addpath(fullfile(pwd,'mexDenseSIFT'));
22
+ addpath(fullfile(pwd,'mexDiscreteFlow'));
23
+
24
+ sift1 = mexDenseSIFT(im1,cellsize,gridspacing);
25
+ sift2 = mexDenseSIFT(im2,cellsize,gridspacing);
26
+
27
+ SIFTflowpara.alpha=2*255;
28
+ SIFTflowpara.d=40*255;
29
+ SIFTflowpara.gamma=0.005*255;
30
+ SIFTflowpara.nlevels=4;
31
+ SIFTflowpara.wsize=2;
32
+ SIFTflowpara.topwsize=10;
33
+ SIFTflowpara.nTopIterations = 60;
34
+ SIFTflowpara.nIterations= 30;
35
+
36
+
37
+ tic;[vx,vy,energylist]=SIFTflowc2f(sift1,sift2,SIFTflowpara);toc
38
+
39
+ warpI2=warpImage(im2,vx,vy);
40
+ figure;imshow(im1);figure;imshow(warpI2);
41
+
42
+ % display flow
43
+ clear flow;
44
+ flow(:,:,1)=vx;
45
+ flow(:,:,2)=vy;
46
+ figure;imshow(flowToColor(flow));
47
+
48
+ return;
49
+
50
+ % this is the code doing the brute force matching
51
+ tic;[flow2,energylist2]=mexDiscreteFlow(Sift1,Sift2,[alpha,alpha*20,60,30]);toc
52
+ figure;imshow(flowToColor(flow2));
UVDoc_official/eval/eval_code/SIFTflow/flowToColor.m ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function img = flowToColor(flow, varargin)
2
+
3
+ % flowToColor(flow, maxFlow) flowToColor color codes flow field, normalize
4
+ % based on specified value,
5
+ %
6
+ % flowToColor(flow) flowToColor color codes flow field, normalize
7
+ % based on maximum flow present otherwise
8
+
9
+ % According to the c++ source code of Daniel Scharstein
10
+ % Contact: schar@middlebury.edu
11
+
12
+ % Author: Deqing Sun, Department of Computer Science, Brown University
13
+ % Contact: dqsun@cs.brown.edu
14
+ % $Date: 2007-10-31 18:33:30 (Wed, 31 Oct 2006) $
15
+
16
+ % Copyright 2007, Deqing Sun.
17
+ %
18
+ % All Rights Reserved
19
+ %
20
+ % Permission to use, copy, modify, and distribute this software and its
21
+ % documentation for any purpose other than its incorporation into a
22
+ % commercial product is hereby granted without fee, provided that the
23
+ % above copyright notice appear in all copies and that both that
24
+ % copyright notice and this permission notice appear in supporting
25
+ % documentation, and that the name of the author and Brown University not be used in
26
+ % advertising or publicity pertaining to distribution of the software
27
+ % without specific, written prior permission.
28
+ %
29
+ % THE AUTHOR AND BROWN UNIVERSITY DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
30
+ % INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ANY
31
+ % PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR BROWN UNIVERSITY BE LIABLE FOR
32
+ % ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
33
+ % WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
34
+ % ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
35
+ % OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
36
+
37
+ UNKNOWN_FLOW_THRESH = 1e9;
38
+ UNKNOWN_FLOW = 1e10; %
39
+
40
+ [height widht nBands] = size(flow);
41
+
42
+ if nBands ~= 2
43
+ error('flowToColor: image must have two bands');
44
+ end;
45
+
46
+ u = flow(:,:,1);
47
+ v = flow(:,:,2);
48
+
49
+ maxu = -999;
50
+ maxv = -999;
51
+
52
+ minu = 999;
53
+ minv = 999;
54
+ maxrad = -1;
55
+
56
+ % fix unknown flow
57
+ idxUnknown = (abs(u)> UNKNOWN_FLOW_THRESH) | (abs(v)> UNKNOWN_FLOW_THRESH) ;
58
+ u(idxUnknown) = 0;
59
+ v(idxUnknown) = 0;
60
+
61
+ maxu = max(maxu, max(u(:)));
62
+ minu = min(minu, min(u(:)));
63
+
64
+ maxv = max(maxv, max(v(:)));
65
+ minv = min(minv, min(v(:)));
66
+
67
+ rad = sqrt(u.^2+v.^2);
68
+ maxrad = max(maxrad, max(rad(:)));
69
+
70
+ fprintf('max flow: %.4f flow range: u = %.3f .. %.3f; v = %.3f .. %.3f\n', maxrad, minu, maxu, minv, maxv);
71
+
72
+ if isempty(varargin) ==0
73
+ maxFlow = varargin{1};
74
+ if maxFlow > 0
75
+ maxrad = maxFlow;
76
+ end;
77
+ end;
78
+
79
+ u = u/(maxrad+eps);
80
+ v = v/(maxrad+eps);
81
+
82
+ % compute color
83
+
84
+ img = computeColor(u, v);
85
+
86
+ % unknown flow
87
+ IDX = repmat(idxUnknown, [1 1 3]);
88
+ img(IDX) = 0;
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/Image.h ADDED
@@ -0,0 +1,1788 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include "project.h"
4
+ #include "stdio.h"
5
+ #include "memory.h"
6
+ #include "ImageProcessing.h"
7
+ #include <iostream>
8
+ #include <fstream>
9
+ #include <typeinfo>
10
+
11
+ #ifndef _MATLAB
12
+ #include "ImageIO.h"
13
+ #else
14
+ #include "mex.h"
15
+ #endif
16
+
17
+ using namespace std;
18
+
19
+ // template class for image
20
+ template <class T>
21
+ class Image
22
+ {
23
+ public:
24
+ T* pData;
25
+ enum collapse_type{collapse_average,collapse_max,collapse_min};
26
+ enum color_type{RGB,BGR,DATA,GRAY};
27
+ protected:
28
+ int imWidth,imHeight,nChannels;
29
+ int nPixels,nElements;
30
+ bool IsDerivativeImage;
31
+ color_type colorType;
32
+ public:
33
+ Image(void);
34
+ Image(int width,int height,int nchannels=1);
35
+ Image(const T& value,int _width,int _height,int _nchannels=1);
36
+ Image(const Image<T>& other);
37
+ ~Image(void);
38
+ virtual Image<T>& operator=(const Image<T>& other);
39
+
40
+ virtual inline void computeDimension(){nPixels=imWidth*imHeight;nElements=nPixels*nChannels;};
41
+
42
+ virtual void allocate(int width,int height,int nchannels=1);
43
+
44
+ template <class T1>
45
+ void allocate(const Image<T1>& other);
46
+
47
+ virtual void clear();
48
+ virtual void reset();
49
+ virtual void copyData(const Image<T>& other);
50
+ void setValue(const T& value);
51
+ void setValue(const T& value,int _width,int _height,int _nchannels=1);
52
+ T immax() const
53
+ {
54
+ T Max=pData[0];
55
+ for(int i=1;i<nElements;i++)
56
+ Max=__max(Max,pData[i]);
57
+ return Max;
58
+ };
59
+ T immin() const{
60
+ T Min=pData[0];
61
+ for(int i=1;i<nElements;i++)
62
+ Min=__min(Min,pData[i]);
63
+ return Min;
64
+ }
65
+ template <class T1>
66
+ void copy(const Image<T1>& other);
67
+
68
+ void im2double();
69
+
70
+ // function to access the member variables
71
+ inline const T& operator [] (int index) const {return pData[index];};
72
+ inline T& operator[](int index) {return pData[index];};
73
+
74
+ inline T*& data(){return pData;};
75
+ inline const T*& data() const{return (const T*&)pData;};
76
+ inline int width() const {return imWidth;};
77
+ inline int height() const {return imHeight;};
78
+ inline int nchannels() const {return nChannels;};
79
+ inline int npixels() const {return nPixels;};
80
+ inline int nelements() const {return nElements;};
81
+ inline bool isDerivativeImage() const {return IsDerivativeImage;};
82
+ inline color_type colortype() const{return colorType;};
83
+
84
+ bool IsFloat () const;
85
+ bool IsEmpty() const {if(nElements==0) return true;else return false;};
86
+ bool IsInImage(int x,int y) const {if(x>=0 && x<imWidth && y>=0 && y<imHeight) return true; else return false;};
87
+
88
+ template <class T1>
89
+ bool matchDimension (const Image<T1>& image) const;
90
+
91
+ bool matchDimension (int width,int height,int nchannels) const;
92
+
93
+ inline void setDerivative(bool isDerivativeImage=true){IsDerivativeImage=isDerivativeImage;};
94
+
95
+ // function to move this image to another one
96
+ template <class T1>
97
+ void moveto(Image<T1>& image,int x,int y,int width=0,int height=0);
98
+
99
+ // function of basic image operations
100
+ virtual bool imresize(double ratio);
101
+ template <class T1>
102
+ void imresize(Image<T1>& result,double ratio) const;
103
+ void imresize(int dstWidth,int dstHeight);
104
+ template <class T1>
105
+ void imresize(Image<T1>& result,int dstWidth,int dstHeight) const;
106
+
107
+ // get the string type
108
+
109
+ // image IO's
110
+ virtual bool saveImage(const char* filename) const;
111
+ virtual bool loadImage(const char* filename);
112
+ #ifndef _MATLAB
113
+ virtual bool imread(const char* filename);
114
+ virtual bool imwrite(const char* filename) const;
115
+ virtual bool imwrite(const char* filename,ImageIO::ImageType) const;
116
+ //virtual bool imread(const QString& filename);
117
+ //virtual void imread(const QImage& image);
118
+
119
+ //virtual bool imwrite(const QString& filename,int quality=100) const;
120
+ //virtual bool imwrite(const QString& filename,ImageIO::ImageType imagetype,int quality=100) const;
121
+ //virtual bool imwrite(const QString& fileanme,T min,T max,int quality=100) const;
122
+ #else
123
+ virtual bool imread(const char* filename) const {return true;};
124
+ virtual bool imwrite(const char* filename) const {return true;};
125
+ #endif
126
+
127
+ template <class T1>
128
+ Image<T1> dx (bool IsAdvancedFilter=false) const;
129
+
130
+ template <class T1>
131
+ void dx(Image<T1>& image,bool IsAdvancedFilter=false) const;
132
+
133
+ template<class T1>
134
+ Image<T1> dy(bool IsAdvancedFilter=false) const;
135
+
136
+ template <class T1>
137
+ void dy(Image<T1>& image,bool IsAdvancedFilter=false) const;
138
+
139
+ template <class T1>
140
+ void dxx(Image<T1>& image) const;
141
+
142
+ template <class T1>
143
+ void dyy(Image<T1>& image) const;
144
+
145
+ template <class T1>
146
+ void laplacian(Image<T1>& image) const;
147
+
148
+ template <class T1>
149
+ void gradientmag(Image<T1>& image) const;
150
+
151
+ template <class T1>
152
+ void GaussianSmoothing(Image<T1>& image,double sigma,int fsize) const;
153
+
154
+ template <class T1>
155
+ void smoothing(Image<T1>& image,double factor=4);
156
+
157
+ template <class T1>
158
+ Image<T1> smoothing(double factor=4);
159
+
160
+ void smoothing(double factor=4);
161
+
162
+ // funciton for filtering
163
+ template <class T1>
164
+ void imfilter(Image<T1>& image,double* filter,int fsize) const;
165
+
166
+ template <class T1>
167
+ Image<T1> imfilter(double* filter,int fsize);
168
+
169
+ template <class T1>
170
+ void imfilter_h(Image<T1>& image,double* filter,int fsize) const;
171
+
172
+ template <class T1>
173
+ void imfilter_v(Image<T1>& image,double* filter,int fsize) const;
174
+
175
+ template <class T1>
176
+ void imfilter_hv(Image<T1>& image,double* hfilter,int hfsize,double* vfilter,int vfsize) const;
177
+
178
+ // function to desaturating
179
+ template <class T1>
180
+ void desaturate(Image<T1>& image) const;
181
+
182
+ void desaturate();
183
+
184
+ template <class T1>
185
+ void collapse(Image<T1>& image,collapse_type type = collapse_average) const;
186
+
187
+ void collapse(collapse_type type = collapse_average);
188
+
189
+ // function to concatenate images
190
+ template <class T1,class T2>
191
+ void concatenate(Image<T1>& destImage,const Image<T2>& addImage) const;
192
+
193
+ template <class T1,class T2>
194
+ void concatenate(Image<T1>& destImage,const Image<T2>& addImage,double ratio) const;
195
+
196
+ template <class T1>
197
+ Image<T> concatenate(const Image<T1>& addImage) const;
198
+
199
+ // function to separate the channels of the image
200
+ template <class T1,class T2>
201
+ void separate(unsigned firstNChannels,Image<T1>& image1,Image<T2>& image2) const;
202
+
203
+ // function to sample patch
204
+ template <class T1>
205
+ void getPatch(Image<T1>& patch,double x,double y,int fsize) const;
206
+
207
+ // function to crop the image
208
+ template <class T1>
209
+ void crop(Image<T1>& patch,int Left,int Top,int Width,int Height) const;
210
+
211
+ // basic numerics of images
212
+ template <class T1,class T2>
213
+ void Multiply(const Image<T1>& image1,const Image<T2>& image2);
214
+
215
+ template <class T1,class T2,class T3>
216
+ void Multiply(const Image<T1>& image1,const Image<T2>& image2,const Image<T3>& image3);
217
+
218
+ template <class T1>
219
+ void Multiplywith(const Image<T1>& image1);
220
+
221
+ void Multiplywith(double value);
222
+
223
+ template <class T1,class T2>
224
+ void Add(const Image<T1>& image1,const Image<T2>& image2);
225
+
226
+ template <class T1,class T2>
227
+ void Add(const Image<T1>& image1,const Image<T2>& image2,double ratio);
228
+
229
+ void Add(const T value);
230
+
231
+ template <class T1>
232
+ void Add(const Image<T1>& image1,const double value);
233
+
234
+ template <class T1>
235
+ void Add(const Image<T1>& image1);
236
+
237
+ template <class T1,class T2>
238
+ void Subtract(const Image<T1>& image1,const Image<T2>& image2);
239
+
240
+ // function to normalize an image
241
+ void normalize(Image<T>& image);
242
+
243
+ // function to compute the statistics of the image
244
+ double norm2() const;
245
+
246
+ template <class T1>
247
+ double innerproduct(Image<T1>& image) const;
248
+
249
+ // function to bilateral smooth flow field
250
+ template <class T1>
251
+ void BilateralFiltering(Image<T1>& other,int fsize,double filter_signa,double range_sigma);
252
+
253
+ // function to bilateral smooth an image
254
+ //Image<T> BilateralFiltering(int fsize,double filter_sigma,double range_sigma);
255
+ void imBilateralFiltering(Image<T>& result,int fsize,double filter_sigma,double range_sigma);
256
+
257
+ // file IO
258
+ #ifndef _MATLAB
259
+ //bool writeImage(QFile& file) const;
260
+ //bool readImage(QFile& file);
261
+ //bool writeImage(const QString& filename) const;
262
+ //bool readImage(const QString& filename);
263
+ #endif
264
+
265
+ #ifdef _MATLAB
266
+ bool LoadMatlabImage(const mxArray* image,bool IsImageScaleCovnersion=true);
267
+ template <class T1>
268
+ void LoadMatlabImageCore(const mxArray* image,bool IsImageScaleCovnersion=true);
269
+
270
+ template <class T1>
271
+ void ConvertFromMatlab(const T1* pMatlabPlane,int _width,int _height,int _nchannels);
272
+
273
+ void OutputToMatlab(mxArray*& matrix) const;
274
+
275
+ template <class T1>
276
+ void ConvertToMatlab(T1* pMatlabPlane) const;
277
+ #endif
278
+ };
279
+
280
+
281
+ typedef Image<unsigned char> BiImage;
282
+ typedef Image<unsigned char> UCImage;
283
+ typedef Image<short int> IntImage;
284
+ typedef Image<float> FImage;
285
+ typedef Image<double> DImage;
286
+
287
+ //------------------------------------------------------------------------------------------
288
+ // constructor
289
+ //------------------------------------------------------------------------------------------
290
+ template <class T>
291
+ Image<T>::Image()
292
+ {
293
+ pData=NULL;
294
+ imWidth=imHeight=nChannels=nPixels=nElements=0;
295
+ IsDerivativeImage=false;
296
+ }
297
+
298
+ //------------------------------------------------------------------------------------------
299
+ // constructor with specified dimensions
300
+ //------------------------------------------------------------------------------------------
301
+ template <class T>
302
+ Image<T>::Image(int width,int height,int nchannels)
303
+ {
304
+ imWidth=width;
305
+ imHeight=height;
306
+ nChannels=nchannels;
307
+ computeDimension();
308
+ pData=NULL;
309
+ pData=new T[nElements];
310
+ if(nElements>0)
311
+ memset(pData,0,sizeof(T)*nElements);
312
+ IsDerivativeImage=false;
313
+ }
314
+
315
+ template <class T>
316
+ Image<T>::Image(const T& value,int _width,int _height,int _nchannels)
317
+ {
318
+ pData=NULL;
319
+ allocate(_width,_height,_nchannels);
320
+ setValue(value);
321
+ }
322
+
323
+ #ifndef _MATLAB
324
+ //template <class T>
325
+ //Image<T>::Image(const QImage& image)
326
+ //{
327
+ // pData=NULL;
328
+ // imread(image);
329
+ //}
330
+ #endif
331
+
332
+ template <class T>
333
+ void Image<T>::allocate(int width,int height,int nchannels)
334
+ {
335
+ clear();
336
+ imWidth=width;
337
+ imHeight=height;
338
+ nChannels=nchannels;
339
+ computeDimension();
340
+ pData=NULL;
341
+
342
+ if(nElements>0)
343
+ {
344
+ pData=new T[nElements];
345
+ memset(pData,0,sizeof(T)*nElements);
346
+ }
347
+ }
348
+
349
+ template <class T>
350
+ template <class T1>
351
+ void Image<T>::allocate(const Image<T1> &other)
352
+ {
353
+ allocate(other.width(),other.height(),other.nchannels());
354
+ isDerivativeImage = other.isDerivativeImage;
355
+ colorType = other.colorType;
356
+ }
357
+
358
+ //------------------------------------------------------------------------------------------
359
+ // copy constructor
360
+ //------------------------------------------------------------------------------------------
361
+ template <class T>
362
+ Image<T>::Image(const Image<T>& other)
363
+ {
364
+ imWidth=imHeight=nChannels=nElements=0;
365
+ pData=NULL;
366
+ copyData(other);
367
+ }
368
+
369
+ //------------------------------------------------------------------------------------------
370
+ // destructor
371
+ //------------------------------------------------------------------------------------------
372
+ template <class T>
373
+ Image<T>::~Image()
374
+ {
375
+ if(pData!=NULL)
376
+ delete []pData;
377
+ }
378
+
379
+ //------------------------------------------------------------------------------------------
380
+ // clear the image
381
+ //------------------------------------------------------------------------------------------
382
+ template <class T>
383
+ void Image<T>::clear()
384
+ {
385
+ if(pData!=NULL)
386
+ delete []pData;
387
+ pData=NULL;
388
+ imWidth=imHeight=nChannels=nPixels=nElements=0;
389
+ }
390
+
391
+ //------------------------------------------------------------------------------------------
392
+ // reset the image (reset the buffer to zero)
393
+ //------------------------------------------------------------------------------------------
394
+ template <class T>
395
+ void Image<T>::reset()
396
+ {
397
+ if(pData!=NULL)
398
+ memset(pData,0,sizeof(T)*nElements);
399
+ }
400
+
401
+ template <class T>
402
+ void Image<T>::setValue(const T &value)
403
+ {
404
+ for(int i=0;i<nElements;i++)
405
+ pData[i]=value;
406
+ }
407
+
408
+ template <class T>
409
+ void Image<T>::setValue(const T& value,int _width,int _height,int _nchannels)
410
+ {
411
+ if(imWidth!=_width || imHeight!=_height || nChannels!=_nchannels)
412
+ allocate(_width,_height,_nchannels);
413
+ setValue(value);
414
+ }
415
+
416
+ //------------------------------------------------------------------------------------------
417
+ // copy from other image
418
+ //------------------------------------------------------------------------------------------
419
+ template <class T>
420
+ void Image<T>::copyData(const Image<T>& other)
421
+ {
422
+ imWidth=other.imWidth;
423
+ imHeight=other.imHeight;
424
+ nChannels=other.nChannels;
425
+ nPixels=other.nPixels;
426
+ IsDerivativeImage=other.IsDerivativeImage;
427
+ colorType = other.colorType;
428
+
429
+ if(nElements!=other.nElements)
430
+ {
431
+ nElements=other.nElements;
432
+ if(pData!=NULL)
433
+ delete []pData;
434
+ pData=NULL;
435
+ pData=new T[nElements];
436
+ }
437
+ if(nElements>0)
438
+ memcpy(pData,other.pData,sizeof(T)*nElements);
439
+ }
440
+
441
+ template <class T>
442
+ template <class T1>
443
+ void Image<T>::copy(const Image<T1>& other)
444
+ {
445
+ clear();
446
+
447
+ imWidth=other.width();
448
+ imHeight=other.height();
449
+ nChannels=other.nchannels();
450
+ computeDimension();
451
+
452
+ IsDerivativeImage=other.isDerivativeImage();
453
+ colorType = other.colortype();
454
+
455
+ pData=NULL;
456
+ pData=new T[nElements];
457
+ const T1*& srcData=other.data();
458
+ for(int i=0;i<nElements;i++)
459
+ pData[i]=srcData[i];
460
+ }
461
+
462
+ template <class T>
463
+ void Image<T>::im2double()
464
+ {
465
+ if(IsFloat())
466
+ for(int i=0;i<nElements;i++)
467
+ pData[i]/=255;
468
+ }
469
+
470
+ //------------------------------------------------------------------------------------------
471
+ // override equal operator
472
+ //------------------------------------------------------------------------------------------
473
+ template <class T>
474
+ Image<T>& Image<T>::operator=(const Image<T>& other)
475
+ {
476
+ copyData(other);
477
+ return *this;
478
+ }
479
+
480
+ template <class T>
481
+ bool Image<T>::IsFloat() const
482
+ {
483
+ if(typeid(T)==typeid(float) || typeid(T)==typeid(double) || typeid(T)==typeid(long double))
484
+ return true;
485
+ else
486
+ return false;
487
+ }
488
+
489
+ template <class T>
490
+ template <class T1>
491
+ bool Image<T>::matchDimension(const Image<T1>& image) const
492
+ {
493
+ if(imWidth==image.width() && imHeight==image.height() && nChannels==image.nchannels())
494
+ return true;
495
+ else
496
+ return false;
497
+ }
498
+
499
+ template <class T>
500
+ bool Image<T>::matchDimension(int width, int height, int nchannels) const
501
+ {
502
+ if(imWidth==width && imHeight==height && nChannels==nchannels)
503
+ return true;
504
+ else
505
+ return false;
506
+ }
507
+
508
+ //------------------------------------------------------------------------------------------
509
+ // function to move this image to a dest image at (x,y) with specified width and height
510
+ //------------------------------------------------------------------------------------------
511
+ template <class T>
512
+ template <class T1>
513
+ void Image<T>::moveto(Image<T1>& image,int x0,int y0,int width,int height)
514
+ {
515
+ if(width==0)
516
+ width=imWidth;
517
+ if(height==0)
518
+ height=imHeight;
519
+ int NChannels=__min(nChannels,image.nchannels());
520
+
521
+ int x,y;
522
+ for(int i=0;i<height;i++)
523
+ {
524
+ y=y0+i;
525
+ if(y>=image.height())
526
+ break;
527
+ for(int j=0;j<width;j++)
528
+ {
529
+ x=x0+j;
530
+ if(x>=image.width())
531
+ break;
532
+ for(int k=0;k<NChannels;k++)
533
+ image.data()[(y*image.width()+x)*image.nchannels()+k]=pData[(i*imWidth+j)*nChannels+k];
534
+ }
535
+ }
536
+ }
537
+
538
+
539
+ //------------------------------------------------------------------------------------------
540
+ // resize the image
541
+ //------------------------------------------------------------------------------------------
542
+ template <class T>
543
+ bool Image<T>::imresize(double ratio)
544
+ {
545
+ if(pData==NULL)
546
+ return false;
547
+
548
+ T* pDstData;
549
+ int DstWidth,DstHeight;
550
+ DstWidth=(double)imWidth*ratio;
551
+ DstHeight=(double)imHeight*ratio;
552
+ pDstData=new T[DstWidth*DstHeight*nChannels];
553
+
554
+ ImageProcessing::ResizeImage(pData,pDstData,imWidth,imHeight,nChannels,ratio);
555
+
556
+ delete []pData;
557
+ pData=pDstData;
558
+ imWidth=DstWidth;
559
+ imHeight=DstHeight;
560
+ computeDimension();
561
+ return true;
562
+ }
563
+
564
+ template <class T>
565
+ template <class T1>
566
+ void Image<T>::imresize(Image<T1>& result,double ratio) const
567
+ {
568
+ int DstWidth,DstHeight;
569
+ DstWidth=(double)imWidth*ratio;
570
+ DstHeight=(double)imHeight*ratio;
571
+ if(result.width()!=DstWidth || result.height()!=DstHeight || result.nchannels()!=nChannels)
572
+ result.allocate(DstWidth,DstHeight,nChannels);
573
+ ImageProcessing::ResizeImage(pData,result.data(),imWidth,imHeight,nChannels,ratio);
574
+ }
575
+
576
+ template <class T>
577
+ template <class T1>
578
+ void Image<T>::imresize(Image<T1>& result,int DstWidth,int DstHeight) const
579
+ {
580
+ if(result.width()!=DstWidth || result.height()!=DstHeight || result.nchannels()!=nChannels)
581
+ result.allocate(DstWidth,DstHeight,nChannels);
582
+ ImageProcessing::ResizeImage(pData,result.data(),imWidth,imHeight,nChannels,DstWidth,DstHeight);
583
+ }
584
+
585
+
586
+ template <class T>
587
+ void Image<T>::imresize(int dstWidth,int dstHeight)
588
+ {
589
+ DImage foo(dstWidth,dstHeight,nChannels);
590
+ ImageProcessing::ResizeImage(pData,foo.data(),imWidth,imHeight,nChannels,dstWidth,dstHeight);
591
+ copyData(foo);
592
+ }
593
+
594
+ //------------------------------------------------------------------------------------------
595
+ // function of reading or writing images (uncompressed)
596
+ //------------------------------------------------------------------------------------------
597
+ template <class T>
598
+ bool Image<T>::saveImage(const char *filename) const
599
+ {
600
+ ofstream myfile(filename,ios::out | ios::binary);
601
+ if(myfile.is_open())
602
+ {
603
+ char type[16];
604
+ sprintf(type,"%s",typeid(T).name());
605
+ myfile.write(type,16);
606
+ myfile.write((char *)&imWidth,sizeof(int));
607
+ myfile.write((char *)&imHeight,sizeof(int));
608
+ myfile.write((char *)&nChannels,sizeof(int));
609
+ myfile.write((char *)&IsDerivativeImage,sizeof(bool));
610
+ myfile.write((char *)pData,sizeof(T)*nElements);
611
+ myfile.close();
612
+ return true;
613
+ }
614
+ else
615
+ return false;
616
+ }
617
+
618
+ template <class T>
619
+ bool Image<T>::loadImage(const char *filename)
620
+ {
621
+ ifstream myfile(filename, ios::in | ios::binary);
622
+ if(myfile.is_open())
623
+ {
624
+ char type[16];
625
+ myfile.read(type,16);
626
+ #ifdef _LINUX_MAC
627
+ if(strcasecmp(type,typeid(T).name())!=0)
628
+ #else
629
+ if(_strcmpi(type,typeid(T).name())!=0)
630
+ #endif
631
+ {
632
+ cout<<"The type of the image is different from the type of the object!"<<endl;
633
+ return false;
634
+ }
635
+ int width,height,nchannels;
636
+ myfile.read((char *)&width,sizeof(int));
637
+ myfile.read((char *)&height,sizeof(int));
638
+ myfile.read((char *)&nchannels,sizeof(int));
639
+ if(!matchDimension(width,height,nchannels))
640
+ allocate(width,height,nchannels);
641
+ myfile.read((char *)&IsDerivativeImage,sizeof(bool));
642
+ myfile.read((char *)pData,sizeof(T)*nElements);
643
+ myfile.close();
644
+ return true;
645
+ }
646
+ else
647
+ return false;
648
+ }
649
+
650
+
651
+ //------------------------------------------------------------------------------------------
652
+ // function to load the image
653
+ //------------------------------------------------------------------------------------------
654
+ #ifndef _MATLAB
655
+
656
+ template <class T>
657
+ bool Image<T>::imread(const char* filename)
658
+ {
659
+ clear();
660
+ if(ImageIO::loadImage(filename,pData,imWidth,imHeight,nChannels))
661
+ {
662
+ computeDimension();
663
+ colorType = BGR; // when we use qt or opencv to load the image, it's often BGR
664
+ return true;
665
+ }
666
+ return false;
667
+ }
668
+
669
+
670
+ //template <class T>
671
+ //bool Image<T>::imread(const QString &filename)
672
+ //{
673
+ // clear();
674
+ // if(ImageIO::loadImage(filename,pData,imWidth,imHeight,nChannels))
675
+ // {
676
+ // computeDimension();
677
+ // return true;
678
+ // }
679
+ // return false;
680
+ //}
681
+ //
682
+ //template <class T>
683
+ //void Image<T>::imread(const QImage& image)
684
+ //{
685
+ // clear();
686
+ // ImageIO::loadImage(image,pData,imWidth,imHeight,nChannels);
687
+ // computeDimension();
688
+ //}
689
+ //
690
+ //------------------------------------------------------------------------------------------
691
+ // function to write the image
692
+ //------------------------------------------------------------------------------------------
693
+ template <class T>
694
+ bool Image<T>::imwrite(const char* filename) const
695
+ {
696
+ ImageIO::ImageType type;
697
+ if(IsDerivativeImage)
698
+ type=ImageIO::derivative;
699
+ else
700
+ type=ImageIO::standard;
701
+
702
+ return ImageIO::saveImage(filename,pData,imWidth,imHeight,nChannels,type);
703
+ }
704
+
705
+ template <class T>
706
+ bool Image<T>::imwrite(const char* filename,ImageIO::ImageType type) const
707
+ {
708
+ return ImageIO::saveImage(filename,pData,imWidth,imHeight,nChannels,type);
709
+ }
710
+
711
+ //template <class T>
712
+ //bool Image<T>::imwrite(const QString &filename, ImageIO::ImageType imagetype, int quality) const
713
+ //{
714
+ // return ImageIO::writeImage(filename,(const T*&)pData,imWidth,imHeight,nChannels,imagetype,quality);
715
+ //}
716
+ //
717
+ //template <class T>
718
+ //bool Image<T>::imwrite(const QString &filename, T min, T max, int quality) const
719
+ //{
720
+ // return ImageIO::writeImage(filename,(const T*&)pData,imWidth,imHeight,nChannels,min,max,quality);
721
+ //}
722
+
723
+ #endif
724
+
725
+ //------------------------------------------------------------------------------------------
726
+ // function to get x-derivative of the image
727
+ //------------------------------------------------------------------------------------------
728
+ template <class T>
729
+ template <class T1>
730
+ void Image<T>::dx(Image<T1>& result,bool IsAdvancedFilter) const
731
+ {
732
+ if(matchDimension(result)==false)
733
+ result.allocate(imWidth,imHeight,nChannels);
734
+ result.reset();
735
+ result.setDerivative();
736
+ T1*& data=result.data();
737
+ int i,j,k,offset;
738
+ if(IsAdvancedFilter==false)
739
+ for(i=0;i<imHeight;i++)
740
+ for(j=0;j<imWidth-1;j++)
741
+ {
742
+ offset=i*imWidth+j;
743
+ for(k=0;k<nChannels;k++)
744
+ data[offset*nChannels+k]=(T1)pData[(offset+1)*nChannels+k]-pData[offset*nChannels+k];
745
+ }
746
+ else
747
+ {
748
+ double xFilter[5]={1,-8,0,8,-1};
749
+ for(i=0;i<5;i++)
750
+ xFilter[i]/=12;
751
+ ImageProcessing::hfiltering(pData,data,imWidth,imHeight,nChannels,xFilter,2);
752
+ }
753
+ }
754
+
755
+ template <class T>
756
+ template <class T1>
757
+ Image<T1> Image<T>::dx(bool IsAdvancedFilter) const
758
+ {
759
+ Image<T1> result;
760
+ dx<T1>(result,IsAdvancedFilter);
761
+ return result;
762
+ }
763
+
764
+ //------------------------------------------------------------------------------------------
765
+ // function to get y-derivative of the image
766
+ //------------------------------------------------------------------------------------------
767
+ template <class T>
768
+ template <class T1>
769
+ void Image<T>::dy(Image<T1>& result,bool IsAdvancedFilter) const
770
+ {
771
+ if(matchDimension(result)==false)
772
+ result.allocate(imWidth,imHeight,nChannels);
773
+ result.setDerivative();
774
+ T1*& data=result.data();
775
+ int i,j,k,offset;
776
+ if(IsAdvancedFilter==false)
777
+ for(i=0;i<imHeight-1;i++)
778
+ for(j=0;j<imWidth;j++)
779
+ {
780
+ offset=i*imWidth+j;
781
+ for(k=0;k<nChannels;k++)
782
+ data[offset*nChannels+k]=(T1)pData[(offset+imWidth)*nChannels+k]-pData[offset*nChannels+k];
783
+ }
784
+ else
785
+ {
786
+ double yFilter[5]={1,-8,0,8,-1};
787
+ for(i=0;i<5;i++)
788
+ yFilter[i]/=12;
789
+ ImageProcessing::vfiltering(pData,data,imWidth,imHeight,nChannels,yFilter,2);
790
+ }
791
+ }
792
+
793
+ template <class T>
794
+ template <class T1>
795
+ Image<T1> Image<T>::dy(bool IsAdvancedFilter) const
796
+ {
797
+ Image<T1> result;
798
+ dy<T1>(result,IsAdvancedFilter);
799
+ return result;
800
+ }
801
+
802
+ //------------------------------------------------------------------------------------------
803
+ // function to compute the second order derivative
804
+ //------------------------------------------------------------------------------------------
805
+ template <class T>
806
+ template <class T1>
807
+ void Image<T>::dxx(Image<T1> &image) const
808
+ {
809
+ if(!matchDimension(image))
810
+ image.allocate(imWidth,imHeight,nChannels);
811
+ T1* pDstData=image.data();
812
+ if(nChannels==1) // if there is only one image channel
813
+ for(int i=0;i<imHeight;i++)
814
+ for(int j=0;j<imWidth;j++)
815
+ {
816
+ int offset=i*imWidth+j;
817
+ if(j==0)
818
+ {
819
+ pDstData[offset]=pData[offset]-pData[offset+1];
820
+ continue;
821
+ }
822
+ if(j==imWidth-1)
823
+ {
824
+ pDstData[offset]=pData[offset]-pData[offset-1];
825
+ continue;
826
+ }
827
+ pDstData[offset]=pData[offset]*2-pData[offset-1]-pData[offset+1];
828
+ }
829
+ else
830
+ for(int i=0;i<imHeight;i++)
831
+ for(int j=0;j<imWidth;j++)
832
+ {
833
+ int offset=(i*imWidth+j)*nChannels;
834
+ if(j==0)
835
+ {
836
+ for(int k=0;k<nChannels;k++)
837
+ pDstData[offset+k]=pData[offset+k]-pData[offset+nChannels+k];
838
+ continue;
839
+ }
840
+ if(j==imWidth-1)
841
+ {
842
+ for(int k=0;k<nChannels;k++)
843
+ pDstData[offset+k]=pData[offset+k]-pData[offset-nChannels+k];
844
+ continue;
845
+ }
846
+ for(int k=0;k<nChannels;k++)
847
+ pDstData[offset+k]=pData[offset+k]*2-pData[offset+nChannels+k]-pData[offset-nChannels+k];
848
+ }
849
+ }
850
+
851
+ template <class T>
852
+ template <class T1>
853
+ void Image<T>::dyy(Image<T1>& image) const
854
+ {
855
+ if(!matchDimension(image))
856
+ image.allocate(imWidth,imHeight,nChannels);
857
+ T1* pDstData=image.data();
858
+ if(nChannels==1)
859
+ for(int i=0;i<imHeight;i++)
860
+ for(int j=0;j<imWidth;j++)
861
+ {
862
+ int offset=i*imWidth+j;
863
+ if(i==0)
864
+ {
865
+ pDstData[offset]=pData[offset]-pData[offset+imWidth];
866
+ continue;
867
+ }
868
+ if(i==imHeight-1)
869
+ {
870
+ pDstData[offset]=pData[offset]-pData[offset-imWidth];
871
+ continue;
872
+ }
873
+ pDstData[offset]=pData[offset]*2-pData[offset+imWidth]-pData[offset-imWidth];
874
+ }
875
+ else
876
+ for(int i=0;i<imHeight;i++)
877
+ for(int j=0;j<imWidth;j++)
878
+ {
879
+ int offset=(i*imWidth+j)*nChannels;
880
+ if(i==0)
881
+ {
882
+ for(int k=0;k<nChannels;k++)
883
+ pDstData[offset+k]=pData[offset+k]-pData[offset+imWidth*nChannels+k];
884
+ continue;
885
+ }
886
+ if(i==imHeight-1)
887
+ {
888
+ for(int k=0;k<nChannels;k++)
889
+ pDstData[offset+k]=pData[offset+k]-pData[offset-imWidth*nChannels+k];
890
+ continue;
891
+ }
892
+ for(int k=0;k<nChannels;k++)
893
+ pDstData[offset+k]=pData[offset+k]*2-pData[offset+imWidth*nChannels+k]-pData[offset-imWidth*nChannels+k];
894
+ }
895
+ }
896
+
897
+ //------------------------------------------------------------------------------------------
898
+ // function for fast laplacian computation
899
+ //------------------------------------------------------------------------------------------
900
+ template <class T>
901
+ template <class T1>
902
+ void Image<T>::laplacian(Image<T1> &image) const
903
+ {
904
+ if(!matchDimension(image))
905
+ image.allocate(*this);
906
+ image.setDerivative(true);
907
+ ImageProcessing::Laplacian(pData,image.data(),imWidth,imHeight,nChannels);
908
+ }
909
+
910
+
911
+ //------------------------------------------------------------------------------------------
912
+ // function to compute the gradient magnitude of the image
913
+ //------------------------------------------------------------------------------------------
914
+ template <class T>
915
+ template <class T1>
916
+ void Image<T>::gradientmag(Image<T1> &image) const
917
+ {
918
+ if(image.width()!=imWidth || image.height()!=imHeight)
919
+ image.allocate(imWidth,imHeight);
920
+ DImage Ix,Iy;
921
+ dx(Ix,true);
922
+ dy(Iy,true);
923
+ double temp;
924
+ double* imagedata=image.data();
925
+ const double *Ixdata=Ix.data(),*Iydata=Iy.data();
926
+ for(int i=0;i<nPixels;i++)
927
+ {
928
+ temp=0;
929
+ int offset=i*nChannels;
930
+ for(int k=0;k<nChannels;k++)
931
+ {
932
+ temp+=Ixdata[offset+k]*Ixdata[offset+k];
933
+ temp+=Iydata[offset+k]*Iydata[offset+k];
934
+ }
935
+ imagedata[i]=sqrt(temp);
936
+ }
937
+ }
938
+
939
+ //------------------------------------------------------------------------------------------
940
+ // function to do Gaussian smoothing
941
+ //------------------------------------------------------------------------------------------
942
+ template <class T>
943
+ template <class T1>
944
+ void Image<T>::GaussianSmoothing(Image<T1>& image,double sigma,int fsize) const
945
+ {
946
+ Image<T1> foo;
947
+ // constructing the 1D gaussian filter
948
+ double* gFilter;
949
+ gFilter=new double[fsize*2+1];
950
+ double sum=0;
951
+ sigma=sigma*sigma*2;
952
+ for(int i=-fsize;i<=fsize;i++)
953
+ {
954
+ gFilter[i+fsize]=exp(-(double)(i*i)/sigma);
955
+ sum+=gFilter[i+fsize];
956
+ }
957
+ for(int i=0;i<2*fsize+1;i++)
958
+ gFilter[i]/=sum;
959
+
960
+ // apply filtering
961
+ imfilter_hv(image,gFilter,fsize,gFilter,fsize);
962
+
963
+ delete gFilter;
964
+ }
965
+
966
+ //------------------------------------------------------------------------------------------
967
+ // function to smooth the image using a simple 3x3 filter
968
+ // the filter is [1 factor 1]/(factor+2), applied horizontally and vertically
969
+ //------------------------------------------------------------------------------------------
970
+ template <class T>
971
+ template <class T1>
972
+ void Image<T>::smoothing(Image<T1>& image,double factor)
973
+ {
974
+ // build
975
+ double filter2D[9]={1,0,1,0, 0, 0,1, 0,1};
976
+ filter2D[1]=filter2D[3]=filter2D[5]=filter2D[7]=factor;
977
+ filter2D[4]=factor*factor;
978
+ for(int i=0;i<9;i++)
979
+ filter2D[i]/=(factor+2)*(factor+2);
980
+
981
+ if(matchDimension(image)==false)
982
+ image.allocate(imWidth,imHeight,nChannels);
983
+ imfilter<T1>(image,filter2D,1);
984
+ }
985
+
986
+ template <class T>
987
+ template <class T1>
988
+ Image<T1> Image<T>::smoothing(double factor)
989
+ {
990
+ Image<T1> result;
991
+ smoothing(result,factor);
992
+ return result;
993
+ }
994
+
995
+ template <class T>
996
+ void Image<T>::smoothing(double factor)
997
+ {
998
+ Image<T> result(imWidth,imHeight,nChannels);
999
+ smoothing(result,factor);
1000
+ copyData(result);
1001
+ }
1002
+
1003
+ //------------------------------------------------------------------------------------------
1004
+ // function of image filtering
1005
+ //------------------------------------------------------------------------------------------
1006
+ template <class T>
1007
+ template <class T1>
1008
+ void Image<T>::imfilter(Image<T1>& image,double* filter,int fsize) const
1009
+ {
1010
+ if(matchDimension(image)==false)
1011
+ image.allocate(imWidth,imHeight,nChannels);
1012
+ ImageProcessing::filtering(pData,image.data(),imWidth,imHeight,nChannels,filter,fsize);
1013
+ }
1014
+
1015
+ template <class T>
1016
+ template <class T1>
1017
+ Image<T1> Image<T>::imfilter(double *filter, int fsize)
1018
+ {
1019
+ Image<T1> result;
1020
+ imfilter(result,filter,fsize);
1021
+ return result;
1022
+ }
1023
+
1024
+ template <class T>
1025
+ template <class T1>
1026
+ void Image<T>::imfilter_h(Image<T1>& image,double* filter,int fsize) const
1027
+ {
1028
+ if(matchDimension(image)==false)
1029
+ image.allocate(imWidth,imHeight,nChannels);
1030
+ ImageProcessing::hfiltering(pData,image.data(),imWidth,imHeight,nChannels,filter,fsize);
1031
+ }
1032
+
1033
+ template <class T>
1034
+ template <class T1>
1035
+ void Image<T>::imfilter_v(Image<T1>& image,double* filter,int fsize) const
1036
+ {
1037
+ if(matchDimension(image)==false)
1038
+ image.allocate(imWidth,imHeight,nChannels);
1039
+ ImageProcessing::vfiltering(pData,image.data(),imWidth,imHeight,nChannels,filter,fsize);
1040
+ }
1041
+
1042
+
1043
+ template <class T>
1044
+ template <class T1>
1045
+ void Image<T>::imfilter_hv(Image<T1> &image, double *hfilter, int hfsize, double *vfilter, int vfsize) const
1046
+ {
1047
+ if(matchDimension(image)==false)
1048
+ image.allocate(imWidth,imHeight,nChannels);
1049
+ T1* pTempBuffer;
1050
+ pTempBuffer=new T1[nElements];
1051
+ ImageProcessing::hfiltering(pData,pTempBuffer,imWidth,imHeight,nChannels,hfilter,hfsize);
1052
+ ImageProcessing::vfiltering(pTempBuffer,image.data(),imWidth,imHeight,nChannels,vfilter,vfsize);
1053
+ delete pTempBuffer;
1054
+ }
1055
+
1056
+ //------------------------------------------------------------------------------------------
1057
+ // function for desaturation
1058
+ //------------------------------------------------------------------------------------------
1059
+ template <class T>
1060
+ template <class T1>
1061
+ void Image<T>::desaturate(Image<T1> &image) const
1062
+ {
1063
+ if(nChannels!=3)
1064
+ {
1065
+ collapse(image);
1066
+ return;
1067
+ }
1068
+ if(!(image.width()==imWidth && image.height()==imHeight && image.nChannels==1))
1069
+ image.allocate(imWidth,imHeight,1);
1070
+ T1* data=image.data();
1071
+ int offset;
1072
+ for(int i=0;i<nPixels;i++)
1073
+ {
1074
+ offset=i*3;
1075
+ if(colorType == RGB)
1076
+ data[i]=(double)pData[offset]*.299+pData[offset+1]*.587+pData[offset+2]*.114;
1077
+ else
1078
+ data[i]=(double)pData[offset]*.114+pData[offset+1]*.587+pData[offset+2]*.299;
1079
+ }
1080
+ }
1081
+
1082
+ template <class T>
1083
+ void Image<T>::desaturate()
1084
+ {
1085
+ Image<T> temp;
1086
+ desaturate(temp);
1087
+ copyData(temp);
1088
+ }
1089
+
1090
+ template <class T>
1091
+ template <class T1>
1092
+ void Image<T>::collapse(Image<T1> &image,collapse_type type) const
1093
+ {
1094
+ if(!(image.width()==imWidth && image.height()==imHeight && image.nChannels==1))
1095
+ image.allocate(imWidth,imHeight,1);
1096
+ image.IsDerivativeImage = IsDerivativeImage;
1097
+ if(nChannels == 1)
1098
+ {
1099
+ image.copy(*this);
1100
+ return;
1101
+ }
1102
+ T1* data=image.data();
1103
+ int offset;
1104
+ double temp;
1105
+ for(int i=0;i<nPixels;i++)
1106
+ {
1107
+ offset=i*nChannels;
1108
+ switch(type){
1109
+ case collapse_average:
1110
+ temp=0;
1111
+ for(int j=0;j<nChannels;j++)
1112
+ temp+=pData[offset+j];
1113
+ data[i]=temp/nChannels;
1114
+ break;
1115
+ case collapse_max:
1116
+ data[i] = pData[offset];
1117
+ for(int j=1;j<nChannels;j++)
1118
+ data[i] = __max(data[i],pData[offset+j]);
1119
+ break;
1120
+ case collapse_min:
1121
+ data[i] = pData[offset];
1122
+ for(int j = 1;j<nChannels;j++)
1123
+ data[i]=__min(data[i],pData[offset+j]);
1124
+ break;
1125
+ }
1126
+ }
1127
+ }
1128
+
1129
+ template <class T>
1130
+ void Image<T>::collapse(collapse_type type)
1131
+ {
1132
+ if(nChannels == 1)
1133
+ return;
1134
+ Image<T> result;
1135
+ collapse(result,type);
1136
+ copyData(result);
1137
+ }
1138
+
1139
+ //------------------------------------------------------------------------------------------
1140
+ // function to concatenate two images
1141
+ //------------------------------------------------------------------------------------------
1142
+ template <class T>
1143
+ template <class T1,class T2>
1144
+ void Image<T>::concatenate(Image<T1> &destImage, const Image<T2> &addImage) const
1145
+ {
1146
+ if(addImage.width()!=imWidth || addImage.height()!=imHeight)
1147
+ {
1148
+ destImage.copy(*this);
1149
+ return;
1150
+ }
1151
+ int extNChannels=nChannels+addImage.nchannels();
1152
+ if(destImage.width()!=imWidth || destImage.height()!=imHeight || destImage.nchannels()!=extNChannels)
1153
+ destImage.allocate(imWidth,imHeight,extNChannels);
1154
+ int offset;
1155
+ T1*& pDestData=destImage.data();
1156
+ const T2*& pAddData=addImage.data();
1157
+ for(int i=0;i<imHeight;i++)
1158
+ for(int j=0;j<imWidth;j++)
1159
+ {
1160
+ offset=i*imWidth+j;
1161
+ for(int k=0;k<nChannels;k++)
1162
+ pDestData[offset*extNChannels+k]=pData[offset*nChannels+k];
1163
+ for(int k=nChannels;k<extNChannels;k++)
1164
+ pDestData[offset*extNChannels+k]=pAddData[offset*addImage.nchannels()+k-nChannels];
1165
+ }
1166
+ }
1167
+
1168
+ template <class T>
1169
+ template <class T1,class T2>
1170
+ void Image<T>::concatenate(Image<T1> &destImage, const Image<T2> &addImage,double ratio) const
1171
+ {
1172
+ if(addImage.width()!=imWidth || addImage.height()!=imHeight)
1173
+ {
1174
+ destImage.copy(*this);
1175
+ return;
1176
+ }
1177
+ int extNChannels=nChannels+addImage.nchannels();
1178
+ if(destImage.width()!=imWidth || destImage.height()!=imHeight || destImage.nchannels()!=extNChannels)
1179
+ destImage.allocate(imWidth,imHeight,extNChannels);
1180
+ int offset;
1181
+ T1*& pDestData=destImage.data();
1182
+ const T2*& pAddData=addImage.data();
1183
+ for(int i=0;i<imHeight;i++)
1184
+ for(int j=0;j<imWidth;j++)
1185
+ {
1186
+ offset=i*imWidth+j;
1187
+ for(int k=0;k<nChannels;k++)
1188
+ pDestData[offset*extNChannels+k]=pData[offset*nChannels+k];
1189
+ for(int k=nChannels;k<extNChannels;k++)
1190
+ pDestData[offset*extNChannels+k]=pAddData[offset*addImage.nchannels()+k-nChannels]*ratio;
1191
+ }
1192
+ }
1193
+
1194
+
1195
+ template <class T>
1196
+ template <class T1>
1197
+ Image<T> Image<T>::concatenate(const Image<T1> &addImage) const
1198
+ {
1199
+ Image<T> destImage;
1200
+ concatenate(destImage,addImage);
1201
+ return destImage;
1202
+ }
1203
+
1204
+ //------------------------------------------------------------------------------------------
1205
+ // function to separate the image into two
1206
+ //------------------------------------------------------------------------------------------
1207
+ template <class T>
1208
+ template <class T1,class T2>
1209
+ void Image<T>::separate(unsigned int firstNChannels, Image<T1> &image1, Image<T2> &image2) const
1210
+ {
1211
+ image1.IsDerivativeImage=IsDerivativeImage;
1212
+ image2.IsDerivativeImage=IsDerivativeImage;
1213
+
1214
+ if(firstNChannels>=nChannels)
1215
+ {
1216
+ image1=*this;
1217
+ image2.allocate(imWidth,imHeight,0);
1218
+ return;
1219
+ }
1220
+ if(firstNChannels==0)
1221
+ {
1222
+ image1.allocate(imWidth,imHeight,0);
1223
+ image2=*this;
1224
+ return;
1225
+ }
1226
+ int secondNChannels=nChannels-firstNChannels;
1227
+ if(image1.width()!=imWidth || image1.height()!=imHeight || image1.nchannels()!=firstNChannels)
1228
+ image1.allocate(imWidth,imHeight,firstNChannels);
1229
+ if(image2.width()!=imWidth || image2.height()!=imHeight || image2.nchannels()!=secondNChannels)
1230
+ image2.allocate(imWidth,imHeight,secondNChannels);
1231
+
1232
+ for(int i=0;i<imHeight;i++)
1233
+ for(int j=0;j<imWidth;j++)
1234
+ {
1235
+ int offset=i*imWidth+j;
1236
+ for(int k=0;k<firstNChannels;k++)
1237
+ image1.pData[offset*firstNChannels+k]=pData[offset*nChannels+k];
1238
+ for(int k=firstNChannels;k<nChannels;k++)
1239
+ image2.pData[offset*secondNChannels+k-firstNChannels]=pData[offset*nChannels+k];
1240
+ }
1241
+ }
1242
+
1243
+ //------------------------------------------------------------------------------------------
1244
+ // function to separate the image into two
1245
+ //------------------------------------------------------------------------------------------
1246
+ template <class T>
1247
+ template <class T1>
1248
+ void Image<T>::getPatch(Image<T1>& patch,double x,double y,int wsize) const
1249
+ {
1250
+ int wlength=wsize*2+1;
1251
+ if(patch.width()!=wlength || patch.height()!=wlength || patch.nchannels()!=nChannels)
1252
+ patch.allocate(wlength,wlength,nChannels);
1253
+ else
1254
+ patch.reset();
1255
+ ImageProcessing::getPatch(pData,patch.data(),imWidth,imHeight,nChannels,x,y,wsize);
1256
+ }
1257
+
1258
+ //------------------------------------------------------------------------------------------
1259
+ // function to crop an image
1260
+ //------------------------------------------------------------------------------------------
1261
+ template <class T>
1262
+ template <class T1>
1263
+ void Image<T>::crop(Image<T1>& patch,int Left,int Top,int Width,int Height) const
1264
+ {
1265
+ if(patch.width()!=Width || patch.height()!=Height || patch.nchannels()!=nChannels)
1266
+ patch.allocate(Width,Height,nChannels);
1267
+ // make sure that the cropping is valid
1268
+ if(Left<0 || Top<0 || Left>=imWidth || Top>=imHeight)
1269
+ {
1270
+ cout<<"The cropping coordinate is outside the image boundary!"<<endl;
1271
+ return;
1272
+ }
1273
+ if(Width<0 || Height<0 || Width+Left>imWidth || Height+Top>imHeight)
1274
+ {
1275
+ cout<<"The patch to crop is invalid!"<<endl;
1276
+ return;
1277
+ }
1278
+ ImageProcessing::cropImage(pData,imWidth,imHeight,nChannels,patch.data(),Left,Top,Width,Height);
1279
+ }
1280
+
1281
+ //------------------------------------------------------------------------------------------
1282
+ // function to multiply image1, image2 and image3 to the current image
1283
+ //------------------------------------------------------------------------------------------
1284
+ template <class T>
1285
+ template <class T1,class T2,class T3>
1286
+ void Image<T>::Multiply(const Image<T1>& image1,const Image<T2>& image2,const Image<T3>& image3)
1287
+ {
1288
+ if(image1.matchDimension(image2)==false || image2.matchDimension(image3)==false)
1289
+ {
1290
+ cout<<"Error in image dimensions--function Image<T>::Multiply()!"<<endl;
1291
+ return;
1292
+ }
1293
+ if(matchDimension(image1)==false)
1294
+ allocate(image1);
1295
+
1296
+ const T1*& pData1=image1.data();
1297
+ const T2*& pData2=image2.data();
1298
+ const T3*& pData3=image3.data();
1299
+
1300
+ for(int i=0;i<nElements;i++)
1301
+ pData[i]=pData1[i]*pData2[i]*pData3[i];
1302
+ }
1303
+
1304
+ template <class T>
1305
+ template <class T1,class T2>
1306
+ void Image<T>::Multiply(const Image<T1>& image1,const Image<T2>& image2)
1307
+ {
1308
+ if(image1.matchDimension(image2)==false)
1309
+ {
1310
+ cout<<"Error in image dimensions--function Image<T>::Multiply()!"<<endl;
1311
+ return;
1312
+ }
1313
+ if(matchDimension(image1)==false)
1314
+ allocate(image1);
1315
+
1316
+ const T1*& pData1=image1.data();
1317
+ const T2*& pData2=image2.data();
1318
+
1319
+ for(int i=0;i<nElements;i++)
1320
+ pData[i]=pData1[i]*pData2[i];
1321
+ }
1322
+
1323
+ template <class T>
1324
+ template <class T1>
1325
+ void Image<T>::Multiplywith(const Image<T1> &image1)
1326
+ {
1327
+ if(matchDimension(image1)==false)
1328
+ {
1329
+ cout<<"Error in image dimensions--function Image<T>::Multiplywith()!"<<endl;
1330
+ return;
1331
+ }
1332
+ const T1*& pData1=image1.data();
1333
+ for(int i=0;i<nElements;i++)
1334
+ pData[i]*=pData1[i];
1335
+ }
1336
+
1337
+ template <class T>
1338
+ void Image<T>::Multiplywith(double value)
1339
+ {
1340
+ for(int i=0;i<nElements;i++)
1341
+ pData[i]*=value;
1342
+ }
1343
+
1344
+ //------------------------------------------------------------------------------------------
1345
+ // function to add image2 to image1 to the current image
1346
+ //------------------------------------------------------------------------------------------
1347
+ template <class T>
1348
+ template <class T1,class T2>
1349
+ void Image<T>::Add(const Image<T1>& image1,const Image<T2>& image2)
1350
+ {
1351
+ if(image1.matchDimension(image2)==false)
1352
+ {
1353
+ cout<<"Error in image dimensions--function Image<T>::Add()!"<<endl;
1354
+ return;
1355
+ }
1356
+ if(matchDimension(image1)==false)
1357
+ allocate(image1);
1358
+
1359
+ const T1*& pData1=image1.data();
1360
+ const T2*& pData2=image2.data();
1361
+ for(int i=0;i<nElements;i++)
1362
+ pData[i]=pData1[i]+pData2[i];
1363
+ }
1364
+
1365
+ template <class T>
1366
+ template <class T1,class T2>
1367
+ void Image<T>::Add(const Image<T1>& image1,const Image<T2>& image2,double ratio)
1368
+ {
1369
+ if(image1.matchDimension(image2)==false)
1370
+ {
1371
+ cout<<"Error in image dimensions--function Image<T>::Add()!"<<endl;
1372
+ return;
1373
+ }
1374
+ if(matchDimension(image1)==false)
1375
+ allocate(image1);
1376
+
1377
+ const T1*& pData1=image1.data();
1378
+ const T2*& pData2=image2.data();
1379
+ for(int i=0;i<nElements;i++)
1380
+ pData[i]=pData1[i]+pData2[i]*ratio;
1381
+ }
1382
+
1383
+ template <class T>
1384
+ template <class T1>
1385
+ void Image<T>::Add(const Image<T1>& image1,const double ratio)
1386
+ {
1387
+ if(matchDimension(image1)==false)
1388
+ {
1389
+ cout<<"Error in image dimensions--function Image<T>::Add()!"<<endl;
1390
+ return;
1391
+ }
1392
+ const T1*& pData1=image1.data();
1393
+ for(int i=0;i<nElements;i++)
1394
+ pData[i]+=pData1[i]*ratio;
1395
+ }
1396
+
1397
+ template <class T>
1398
+ template <class T1>
1399
+ void Image<T>::Add(const Image<T1>& image1)
1400
+ {
1401
+ if(matchDimension(image1)==false)
1402
+ {
1403
+ cout<<"Error in image dimensions--function Image<T>::Add()!"<<endl;
1404
+ return;
1405
+ }
1406
+ const T1*& pData1=image1.data();
1407
+ for(int i=0;i<nElements;i++)
1408
+ pData[i]+=pData1[i];
1409
+ }
1410
+
1411
+
1412
+ template <class T>
1413
+ void Image<T>::Add(const T value)
1414
+ {
1415
+ for(int i=0;i<nElements;i++)
1416
+ pData[i]+=value;
1417
+ }
1418
+
1419
+ //------------------------------------------------------------------------------------------
1420
+ // function to subtract image2 from image1
1421
+ //------------------------------------------------------------------------------------------
1422
+ template <class T>
1423
+ template <class T1,class T2>
1424
+ void Image<T>::Subtract(const Image<T1> &image1, const Image<T2> &image2)
1425
+ {
1426
+ if(image1.matchDimension(image2)==false)
1427
+ {
1428
+ cout<<"Error in image dimensions--function Image<T>::Add()!"<<endl;
1429
+ return;
1430
+ }
1431
+ if(matchDimension(image1)==false)
1432
+ allocate(image1);
1433
+
1434
+ const T1*& pData1=image1.data();
1435
+ const T2*& pData2=image2.data();
1436
+ for(int i=0;i<nElements;i++)
1437
+ pData[i]=pData1[i]-pData2[i];
1438
+ }
1439
+
1440
+ //------------------------------------------------------------------------------------------
1441
+ // normalize an image
1442
+ //------------------------------------------------------------------------------------------
1443
+ template <class T>
1444
+ void Image<T>::normalize(Image<T>& image)
1445
+ {
1446
+ if(image.width()!=imWidth || image.height()!=imHeight || image.nchannels()!=nChannels)
1447
+ image.allocate(imWidth,imHeight,nChannels);
1448
+ T Max =immax(),Min =immin();
1449
+ if(Max==Min)
1450
+ return;
1451
+ double ratio=1/(Max-Min);
1452
+ if(IsFloat()==false)
1453
+ ratio*=255;
1454
+ T* data=image.data();
1455
+ for(int i=0;i<nElements;i++)
1456
+ data[i]=(double)(pData[i]-Min)*ratio;
1457
+ }
1458
+
1459
+ template <class T>
1460
+ double Image<T>::norm2() const
1461
+ {
1462
+ double result=0;
1463
+ for(int i=0;i<nElements;i++)
1464
+ result+=pData[i]*pData[i];
1465
+ return result;
1466
+ }
1467
+
1468
+ template <class T>
1469
+ template <class T1>
1470
+ double Image<T>::innerproduct(Image<T1> &image) const
1471
+ {
1472
+ double result=0;
1473
+ const T1* pData1=image.data();
1474
+ for(int i=0;i<nElements;i++)
1475
+ result+=pData[i]*pData1[i];
1476
+ return result;
1477
+ }
1478
+
1479
+ #ifndef _MATLAB
1480
+ //template <class T>
1481
+ //bool Image<T>::writeImage(QFile &file) const
1482
+ //{
1483
+ // file.write((char *)&imWidth,sizeof(int));
1484
+ // file.write((char *)&imHeight,sizeof(int));
1485
+ // file.write((char *)&nChannels,sizeof(int));
1486
+ // file.write((char *)&IsDerivativeImage,sizeof(bool));
1487
+ // if(file.write((char *)pData,sizeof(T)*nElements)!=sizeof(T)*nElements)
1488
+ // return false;
1489
+ // return true;
1490
+ //}
1491
+ //
1492
+ //template <class T>
1493
+ //bool Image<T>::readImage(QFile& file)
1494
+ //{
1495
+ // clear();
1496
+ // file.read((char *)&imWidth,sizeof(int));
1497
+ // file.read((char *)&imHeight,sizeof(int));
1498
+ // file.read((char *)&nChannels,sizeof(int));
1499
+ // file.read((char *)&IsDerivativeImage,sizeof(bool));
1500
+ // if(imWidth<0 ||imWidth>100000 || imHeight<0 || imHeight>100000 || nChannels<0 || nChannels>10000)
1501
+ // return false;
1502
+ // allocate(imWidth,imHeight,nChannels);
1503
+ // if(file.read((char *)pData,sizeof(T)*nElements)!=sizeof(T)*nElements)
1504
+ // return false;
1505
+ // return true;
1506
+ //}
1507
+ //
1508
+ //template <class T>
1509
+ //bool Image<T>::writeImage(const QString &filename) const
1510
+ //{
1511
+ // QFile file(filename);
1512
+ // if(file.open(QIODevice::WriteOnly)==false)
1513
+ // return false;
1514
+ // if(!writeImage(file))
1515
+ // return false;
1516
+ // return true;
1517
+ //}
1518
+ //
1519
+ //template <class T>
1520
+ //bool Image<T>::readImage(const QString &filename)
1521
+ //{
1522
+ // QFile file(filename);
1523
+ // if(file.open(QIODevice::ReadOnly)==false)
1524
+ // return false;
1525
+ // if(!readImage(file))
1526
+ // return false;
1527
+ // return true;
1528
+ //}
1529
+ #endif
1530
+
1531
+
1532
+ template <class T>
1533
+ template <class T1>
1534
+ void Image<T>::BilateralFiltering(Image<T1>& other,int fsize,double filter_sigma,double range_sigma)
1535
+ {
1536
+ double *pBuffer;
1537
+ Image<T1> result(other);
1538
+ pBuffer=new double[other.nchannels()];
1539
+
1540
+ // set spatial weight to save time
1541
+ double *pSpatialWeight;
1542
+ int flength = fsize*2+1;
1543
+ pSpatialWeight = new double[flength*flength];
1544
+ for(int i=-fsize;i<=fsize;i++)
1545
+ for(int j=-fsize;j<=fsize;j++)
1546
+ pSpatialWeight[(i+fsize)*flength+j+fsize]=exp(-(double)(i*i+j*j)/(2*filter_sigma*filter_sigma));
1547
+
1548
+ for(int i=0;i<imHeight;i++)
1549
+ for(int j=0;j<imWidth;j++)
1550
+ {
1551
+ double totalWeight=0;
1552
+ for(int k=0;k<other.nchannels();k++)
1553
+ pBuffer[k]=0;
1554
+ for(int ii=-fsize;ii<=fsize;ii++)
1555
+ for(int jj=-fsize;jj<=fsize;jj++)
1556
+ {
1557
+ int x=j+jj;
1558
+ int y=i+ii;
1559
+ if(x<0 || x>=imWidth || y<0 || y>=imHeight)
1560
+ continue;
1561
+
1562
+ // compute weight
1563
+ int offset=(y*imWidth+x)*nChannels;
1564
+ double temp=0;
1565
+ for(int k=0;k<nChannels;k++)
1566
+ {
1567
+ double diff=pData[offset+k]-pData[(i*imWidth+j)*nChannels+k];
1568
+ temp+=diff*diff;
1569
+ }
1570
+ double weight=exp(-temp/(2*range_sigma*range_sigma));
1571
+ weight *= pSpatialWeight[(ii+fsize)*flength+jj+fsize];
1572
+ //weight*=exp(-(double)(ii*ii+jj*jj)/(2*filter_sigma*filter_sigma));
1573
+ totalWeight+=weight;
1574
+ for(int k=0;k<other.nchannels();k++)
1575
+ pBuffer[k]+=other.data()[(y*imWidth+x)*other.nchannels()+k]*weight;
1576
+ }
1577
+ for(int k=0;k<other.nchannels();k++)
1578
+ result.data()[(i*imWidth+j)*other.nchannels()]=pBuffer[k]/totalWeight;
1579
+ }
1580
+ other.copyData(result);
1581
+ delete pBuffer;
1582
+ delete pSpatialWeight;
1583
+ }
1584
+
1585
+
1586
+ template <class T>
1587
+ //Image<T> Image<T>::BilateralFiltering(int fsize,double filter_sigma,double range_sigma)
1588
+ void Image<T>::imBilateralFiltering(Image<T>& result,int fsize,double filter_sigma,double range_sigma)
1589
+ {
1590
+ //Image<T> result(*this);
1591
+ result.allocate(*this);
1592
+
1593
+ double *pBuffer;
1594
+ pBuffer=new double[nChannels];
1595
+
1596
+ // set spatial weight to save time
1597
+ double *pSpatialWeight;
1598
+ int flength = fsize*2+1;
1599
+ pSpatialWeight = new double[flength*flength];
1600
+ for(int i=-fsize;i<=fsize;i++)
1601
+ for(int j=-fsize;j<=fsize;j++)
1602
+ pSpatialWeight[(i+fsize)*flength+j+fsize]=exp(-(double)(i*i+j*j)/(2*filter_sigma*filter_sigma));
1603
+
1604
+ for(int i=0;i<imHeight;i++)
1605
+ for(int j=0;j<imWidth;j++)
1606
+ {
1607
+ double totalWeight=0;
1608
+ for(int k=0;k<nChannels;k++)
1609
+ pBuffer[k]=0;
1610
+ int offset0 = (i*imWidth+j)*nChannels;
1611
+ for(int ii=-fsize;ii<=fsize;ii++)
1612
+ for(int jj=-fsize;jj<=fsize;jj++)
1613
+ {
1614
+ int x=j+jj;
1615
+ int y=i+ii;
1616
+ if(x<0 || x>=imWidth || y<0 || y>=imHeight)
1617
+ continue;
1618
+
1619
+ // compute weight
1620
+ int offset=(y*imWidth+x)*nChannels;
1621
+ double temp=0;
1622
+ for(int k=0;k<nChannels;k++)
1623
+ {
1624
+ double diff=pData[offset+k]-pData[offset0+k];
1625
+ temp+=diff*diff;
1626
+ }
1627
+ double weight=exp(-temp/(2*range_sigma*range_sigma));
1628
+ weight *= pSpatialWeight[(ii+fsize)*flength+jj+fsize];
1629
+
1630
+ //weight*=exp(-(double)(ii*ii+jj*jj)/(2*filter_sigma*filter_sigma));
1631
+ totalWeight+=weight;
1632
+ for(int k=0;k<nChannels;k++)
1633
+ pBuffer[k]+=pData[offset+k]*weight;
1634
+ }
1635
+ for(int k=0;k<nChannels;k++)
1636
+ result.data()[offset0+k]=pBuffer[k]/totalWeight;
1637
+
1638
+ }
1639
+ delete pBuffer;
1640
+ delete pSpatialWeight;
1641
+ //return result;
1642
+ }
1643
+
1644
+ #ifdef _MATLAB
1645
+
1646
+ template <class T>
1647
+ template <class T1>
1648
+ void Image<T>::LoadMatlabImageCore(const mxArray *image,bool IsImageScaleCovnersion)
1649
+ {
1650
+ int nDim = mxGetNumberOfDimensions(image);
1651
+ const mwSize* imDim = mxGetDimensions(image);
1652
+ if(nDim==2)
1653
+ allocate(imDim[1],imDim[0]);
1654
+ else if(nDim==3)
1655
+ allocate(imDim[1],imDim[0],imDim[2]);
1656
+ else
1657
+ mexErrMsgTxt("The image doesn't have the appropriate dimension!");
1658
+ T1* pMatlabPlane=(T1*)mxGetData(image);
1659
+ bool IsMatlabFloat;
1660
+ if(typeid(T1)==typeid(float) || typeid(T1)==typeid(double) || typeid(T1)==typeid(long double))
1661
+ IsMatlabFloat=true;
1662
+ else
1663
+ IsMatlabFloat=false;
1664
+ bool isfloat=IsFloat();
1665
+ if(isfloat==IsMatlabFloat || IsImageScaleCovnersion==false)
1666
+ {
1667
+ ConvertFromMatlab<T1>(pMatlabPlane,imWidth,imHeight,nChannels);
1668
+ return;
1669
+ }
1670
+ int offset=0;
1671
+ if(isfloat==true)
1672
+ for(int i=0;i<imHeight;i++)
1673
+ for(int j=0;j<imWidth;j++)
1674
+ for(int k=0;k<nChannels;k++)
1675
+ pData[offset++]=(double)pMatlabPlane[k*nPixels+j*imHeight+i]/255;
1676
+ else
1677
+ for(int i=0;i<imHeight;i++)
1678
+ for(int j=0;j<imWidth;j++)
1679
+ for(int k=0;k<nChannels;k++)
1680
+ pData[offset++]=(double)pMatlabPlane[k*nPixels+j*imHeight+i]*255;
1681
+ }
1682
+
1683
+ template <class T>
1684
+ bool Image<T>::LoadMatlabImage(const mxArray* matrix,bool IsImageScaleCovnersion)
1685
+ {
1686
+ colorType = RGB; // the color is RGB when we use matlab to load the image
1687
+ if(mxIsClass(matrix,"uint8"))
1688
+ {
1689
+ LoadMatlabImageCore<unsigned char>(matrix,IsImageScaleCovnersion);
1690
+ return true;
1691
+ }
1692
+ if(mxIsClass(matrix,"int8"))
1693
+ {
1694
+ LoadMatlabImageCore<char>(matrix,IsImageScaleCovnersion);
1695
+ return true;
1696
+ }
1697
+ if(mxIsClass(matrix,"int32"))
1698
+ {
1699
+ LoadMatlabImageCore<int>(matrix,IsImageScaleCovnersion);
1700
+ return true;
1701
+ }
1702
+ if(mxIsClass(matrix,"uint32"))
1703
+ {
1704
+ LoadMatlabImageCore<unsigned int>(matrix,IsImageScaleCovnersion);
1705
+ return true;
1706
+ }
1707
+ if(mxIsClass(matrix,"int16"))
1708
+ {
1709
+ LoadMatlabImageCore<short int>(matrix,IsImageScaleCovnersion);
1710
+ return true;
1711
+ }
1712
+ if(mxIsClass(matrix,"uint16"))
1713
+ {
1714
+ LoadMatlabImageCore<unsigned short int>(matrix,IsImageScaleCovnersion);
1715
+ return true;
1716
+ }
1717
+ if(mxIsClass(matrix,"single"))
1718
+ {
1719
+ LoadMatlabImageCore<float>(matrix,IsImageScaleCovnersion);
1720
+ return true;
1721
+ }
1722
+ if(mxIsClass(matrix,"double"))
1723
+ {
1724
+ LoadMatlabImageCore<double>(matrix,IsImageScaleCovnersion);
1725
+ return true;
1726
+ }
1727
+ mexErrMsgTxt("Unknown type of the image!");
1728
+ return false;
1729
+ }
1730
+
1731
+
1732
+ template <class T>
1733
+ template <class T1>
1734
+ void Image<T>::ConvertFromMatlab(const T1 *pMatlabPlane, int _width, int _height, int _nchannels)
1735
+ {
1736
+ if(imWidth!=_width || imHeight!=_height || nChannels!=_nchannels)
1737
+ allocate(_width,_height,_nchannels);
1738
+ int offset=0;
1739
+ for(int i=0;i<imHeight;i++)
1740
+ for(int j=0;j<imWidth;j++)
1741
+ for(int k=0;k<nChannels;k++)
1742
+ pData[offset++]=pMatlabPlane[k*nPixels+j*imHeight+i];
1743
+ }
1744
+
1745
+ // convert image data to matlab matrix
1746
+ template <class T>
1747
+ template <class T1>
1748
+ void Image<T>::ConvertToMatlab(T1 *pMatlabPlane) const
1749
+ {
1750
+ int offset=0;
1751
+ for(int i=0;i<imHeight;i++)
1752
+ for(int j=0;j<imWidth;j++)
1753
+ for(int k=0;k<nChannels;k++)
1754
+ pMatlabPlane[k*nPixels+j*imHeight+i]=pData[offset++];
1755
+ }
1756
+
1757
+ template <class T>
1758
+ void Image<T>::OutputToMatlab(mxArray *&matrix) const
1759
+ {
1760
+ mwSize dims[3];
1761
+ dims[0]=imHeight;
1762
+ dims[1]=imWidth;
1763
+ dims[2]=nChannels;
1764
+ int nDims;
1765
+ nDims = (nChannels ==1)? 2:3;
1766
+ if(typeid(T) == typeid(unsigned char))
1767
+ matrix=mxCreateNumericArray(nDims, dims,mxUINT8_CLASS, mxREAL);
1768
+ if(typeid(T) == typeid(char))
1769
+ matrix=mxCreateNumericArray(nDims, dims,mxINT8_CLASS, mxREAL);
1770
+ if(typeid(T) == typeid(short int))
1771
+ matrix=mxCreateNumericArray(nDims, dims,mxINT16_CLASS, mxREAL);
1772
+ if(typeid(T) == typeid(unsigned short int))
1773
+ matrix=mxCreateNumericArray(nDims, dims,mxUINT16_CLASS, mxREAL);
1774
+ if(typeid(T) == typeid(int))
1775
+ matrix=mxCreateNumericArray(nDims, dims,mxINT32_CLASS, mxREAL);
1776
+ if(typeid(T) == typeid(unsigned int))
1777
+ matrix=mxCreateNumericArray(nDims, dims,mxUINT32_CLASS, mxREAL);
1778
+ if(typeid(T) == typeid(float))
1779
+ matrix=mxCreateNumericArray(nDims, dims,mxSINGLE_CLASS, mxREAL);
1780
+ if(typeid(T) == typeid(double))
1781
+ matrix=mxCreateNumericArray(nDims, dims,mxDOUBLE_CLASS, mxREAL);
1782
+
1783
+ ConvertToMatlab<T>((T*)mxGetData(matrix));
1784
+ }
1785
+
1786
+ #endif
1787
+
1788
+
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/ImageFeature.h ADDED
@@ -0,0 +1,283 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include "Image.h"
3
+ #include "math.h"
4
+ #include "memory.h"
5
+ #include <vector>
6
+
7
+ #ifndef M_PI
8
+ #define M_PI 3.1415926535897932384626433
9
+ #endif
10
+
11
+
12
+ class ImageFeature
13
+ {
14
+ public:
15
+ ImageFeature(void);
16
+ ~ImageFeature(void);
17
+
18
+ template <class T1,class T2>
19
+ static void imSIFT(const Image<T1> imsrc, Image<T2>& imsift, int cellSize = 2, int stepSize = 1,bool IsBoundaryIncluded = false,int nBins = 8);
20
+
21
+ template <class T1,class T2>
22
+ static void imSIFT(const Image<T1> imsrc, Image<T2>& imsift, const vector<int> cellSizeVect, int stepSize = 1,bool IsBoundaryIncluded = false, int nBins = 8);
23
+ };
24
+
25
+ template <class T1,class T2>
26
+ void ImageFeature::imSIFT(const Image<T1> imsrc, Image<T2> &imsift,int cellSize,int stepSize,bool IsBoundaryIncluded,int nBins)
27
+ {
28
+ if(cellSize<=0)
29
+ {
30
+ cout<<"The cell size must be positive!"<<endl;
31
+ return;
32
+ }
33
+
34
+ // this parameter controls decay of the gradient energy falls into a bin
35
+ // run SIFT_weightFunc.m to see why alpha = 9 is the best value
36
+ int alpha = 9;
37
+
38
+ int width=imsrc.width(),height=imsrc.height(),nchannels =imsrc.nchannels();
39
+ int nPixels = width*height;
40
+ DImage imdx,imdy;
41
+ // compute the derivatives;
42
+ imsrc.dx(imdx,true);
43
+ imsrc.dy(imdy,true);
44
+
45
+ // get the maximum gradient over the channels and estimate the normalized gradient
46
+ DImage magsrc(width,height,nchannels),mag(width,height),gradient(width,height,2);
47
+ double Max;
48
+ for(int i=0;i<nPixels;i++)
49
+ {
50
+ int offset = i*nchannels;
51
+ for(int j = 0;j<nchannels;j++)
52
+ magsrc.pData[offset+j] = sqrt(imdx.pData[offset+j]*imdx.pData[offset+j]+imdy.pData[offset+j]*imdy.pData[offset+j]);
53
+ Max = magsrc.pData[offset];
54
+ if(Max!=0)
55
+ {
56
+ gradient.pData[i*2] = imdx.pData[offset]/Max;
57
+ gradient.pData[i*2+1] = imdy.pData[offset]/Max;
58
+ }
59
+ for(int j = 1;j<nchannels;j++)
60
+ {
61
+ if(magsrc.pData[offset+j]>Max)
62
+ {
63
+ Max = magsrc.pData[offset+j];
64
+ gradient.pData[i*2] = imdx.pData[offset+j]/Max;
65
+ gradient.pData[i*2+1] = imdy.pData[offset+j]/Max;
66
+ }
67
+ }
68
+ mag.pData[i] = Max;
69
+ }
70
+
71
+ // get the pixel-wise energy for each orientation band
72
+ DImage imband(width,height,nBins);
73
+ double theta = M_PI*2/nBins;
74
+ double _cos,_sin,temp;
75
+ for(int k = 0;k<nBins;k++)
76
+ {
77
+ _sin = sin(theta*k);
78
+ _cos = cos(theta*k);
79
+ for(int i = 0;i<nPixels; i++)
80
+ {
81
+ temp = __max(gradient.pData[i*2]*_cos + gradient.pData[i*2+1]*_sin,0);
82
+ if(alpha>1)
83
+ temp = pow(temp,alpha);
84
+ imband.pData[i*nBins+k] = temp*mag.pData[i];
85
+ }
86
+ }
87
+
88
+ // filter out the SIFT feature
89
+ DImage filter(cellSize*2+1,1);
90
+ filter[0] = filter[cellSize+1] = 0.25;
91
+ for(int i = 1;i<cellSize+1;i++)
92
+ filter[i+1] = 1;
93
+ for(int i = cellSize+2;i<cellSize*2+1;i++)
94
+ filter[i] = 0;
95
+
96
+ DImage imband_cell;
97
+ imband.imfilter_hv(imband_cell,filter.data(),cellSize,filter.data(),cellSize);
98
+
99
+ // allocate buffer for the sift image
100
+ int siftdim = nBins*16;
101
+ int sift_width,sift_height,x_shift=0,y_shift=0;
102
+
103
+ sift_width = width/stepSize;
104
+ sift_height = height/stepSize;
105
+
106
+ if(IsBoundaryIncluded == false)
107
+ {
108
+ sift_width = (width-4*cellSize)/stepSize;
109
+ sift_height= (height-4*cellSize)/stepSize;
110
+ x_shift = 2*cellSize;
111
+ y_shift = 2*cellSize;
112
+ }
113
+
114
+ if(!imsift.matchDimension(sift_width,sift_height,siftdim))
115
+ imsift.allocate(sift_width,sift_height,siftdim);
116
+
117
+ // now sample to get SIFT image
118
+ DImage sift_cell(siftdim,1);
119
+ for(int i=0;i<sift_height;i++)
120
+ for(int j =0;j<sift_width;j++)
121
+ {
122
+ int count = 0;
123
+ for(int ii = -1;ii<=2;ii++)
124
+ for(int jj=-1;jj<=2;jj++)
125
+ {
126
+ int y = __min(__max(y_shift+i*stepSize+ii*cellSize,0),height-1);
127
+ int x = __min(__max(x_shift+j*stepSize+jj*cellSize,0),width-1);
128
+
129
+ // the following code is the same as the above two for debugging purposes
130
+ //int y = y_shift+i*stepSize+ii*cellSize;
131
+ //int x = x_shift+j*stepSize+jj*cellSize;
132
+ //if (x<0 || x>=width)
133
+ // x = __min(__max(x,0),width-1);
134
+ //if (y<0 || y>=height)
135
+ // y= __min(__max(y,0),height-1);
136
+
137
+ memcpy(sift_cell.pData+count*nBins,imband_cell.pData+(y*width+x)*nBins,sizeof(double)*nBins);
138
+ count++;
139
+ }
140
+ // normalize the SIFT descriptor
141
+ double mag = sqrt(sift_cell.norm2());
142
+ int offset = (i*sift_width+j)*siftdim;
143
+ //memcpy(imsift.pData+offset,sift_cell.pData,sizeof(double)*siftdim);
144
+ for(int k = 0;k<siftdim;k++)
145
+ imsift.pData[offset+k] = (unsigned char)__min(sift_cell.pData[k]/(mag+0.01)*255,255);//(unsigned char) __min(sift_cell.pData[k]/mag*512,255);
146
+ }//*/
147
+ }
148
+
149
+
150
+ //--------------------------------------------------------------------------------------------------
151
+ // multi-scale SIFT features
152
+ //--------------------------------------------------------------------------------------------------
153
+ template <class T1,class T2>
154
+ void ImageFeature::imSIFT(const Image<T1> imsrc, Image<T2> &imsift,const vector<int> cellSizeVect,int stepSize,bool IsBoundaryIncluded,int nBins)
155
+ {
156
+ // this parameter controls decay of the gradient energy falls into a bin
157
+ // run SIFT_weightFunc.m to see why alpha = 9 is the best value
158
+ int alpha = 9;
159
+
160
+ int width=imsrc.width(),height=imsrc.height(),nchannels =imsrc.nchannels();
161
+ int nPixels = width*height;
162
+ DImage imdx,imdy;
163
+ // compute the derivatives;
164
+ imsrc.dx(imdx,true);
165
+ imsrc.dy(imdy,true);
166
+
167
+ // get the maximum gradient over the channels and estimate the normalized gradient
168
+ DImage magsrc(width,height,nchannels),mag(width,height),gradient(width,height,2);
169
+ double Max;
170
+ for(int i=0;i<nPixels;i++)
171
+ {
172
+ int offset = i*nchannels;
173
+ for(int j = 0;j<nchannels;j++)
174
+ magsrc.pData[offset+j] = sqrt(imdx.pData[offset+j]*imdx.pData[offset+j]+imdy.pData[offset+j]*imdy.pData[offset+j]);
175
+ Max = magsrc.pData[offset];
176
+ if(Max!=0)
177
+ {
178
+ gradient.pData[i*2] = imdx.pData[offset]/Max;
179
+ gradient.pData[i*2+1] = imdy.pData[offset]/Max;
180
+ }
181
+ for(int j = 1;j<nchannels;j++)
182
+ {
183
+ if(magsrc.pData[offset+j]>Max)
184
+ {
185
+ Max = magsrc.pData[offset+j];
186
+ gradient.pData[i*2] = imdx.pData[offset+j]/Max;
187
+ gradient.pData[i*2+1] = imdy.pData[offset+j]/Max;
188
+ }
189
+ }
190
+ mag.pData[i] = Max;
191
+ }
192
+
193
+ // get the pixel-wise energy for each orientation band
194
+ DImage imband(width,height,nBins);
195
+ double theta = M_PI*2/nBins;
196
+ double _cos,_sin,temp;
197
+ for(int k = 0;k<nBins;k++)
198
+ {
199
+ _sin = sin(theta*k);
200
+ _cos = cos(theta*k);
201
+ for(int i = 0;i<nPixels; i++)
202
+ {
203
+ temp = __max(gradient.pData[i*2]*_cos + gradient.pData[i*2+1]*_sin,0);
204
+ if(alpha>1)
205
+ temp = pow(temp,alpha);
206
+ imband.pData[i*nBins+k] = temp*mag.pData[i];
207
+ }
208
+ }
209
+ // get the maximum cell size
210
+ int maxCellSize = cellSizeVect[0];
211
+ int nScales = cellSizeVect.size();
212
+ for(int h=1;h<nScales;h++)
213
+ maxCellSize = __max(maxCellSize,cellSizeVect[h]);
214
+
215
+ // allocate buffer for the sift image
216
+ int siftdim = nBins*16;
217
+ int sift_width,sift_height,x_shift=0,y_shift=0;
218
+
219
+ sift_width = width/stepSize;
220
+ sift_height = height/stepSize;
221
+
222
+ if(IsBoundaryIncluded == false)
223
+ {
224
+ sift_width = (width-4*maxCellSize)/stepSize;
225
+ sift_height= (height-4*maxCellSize)/stepSize;
226
+ x_shift = 2*maxCellSize;
227
+ y_shift = 2*maxCellSize;
228
+ }
229
+
230
+ if(!imsift.matchDimension(sift_width,sift_height,siftdim*nScales))
231
+ imsift.allocate(sift_width,sift_height,siftdim*nScales);
232
+
233
+ for(int h=0;h<nScales;h++)
234
+ {
235
+ int cellSize = cellSizeVect[h];
236
+ if(cellSize<=0)
237
+ {
238
+ cout<<"The cell size must be positive!"<<endl;
239
+ return;
240
+ }
241
+ // filter out the SIFT feature
242
+ DImage filter(cellSize*2+1,1);
243
+ filter[0] = filter[cellSize+1] = 0.25;
244
+ for(int i = 1;i<cellSize+1;i++)
245
+ filter[i+1] = 1;
246
+ for(int i = cellSize+2;i<cellSize*2+1;i++)
247
+ filter[i] = 0;
248
+
249
+ DImage imband_cell;
250
+ imband.imfilter_hv(imband_cell,filter.data(),cellSize,filter.data(),cellSize);
251
+
252
+ // now sample to get SIFT image
253
+ DImage sift_cell(siftdim,1);
254
+ for(int i=0;i<sift_height;i++)
255
+ for(int j =0;j<sift_width;j++)
256
+ {
257
+ int count = 0;
258
+ for(int ii = -1;ii<=2;ii++)
259
+ for(int jj=-1;jj<=2;jj++)
260
+ {
261
+ int y = __min(__max(y_shift+i*stepSize+ii*cellSize,0),height-1);
262
+ int x = __min(__max(x_shift+j*stepSize+jj*cellSize,0),width-1);
263
+
264
+ // the following code is the same as the above two for debugging purposes
265
+ //int y = y_shift+i*stepSize+ii*cellSize;
266
+ //int x = x_shift+j*stepSize+jj*cellSize;
267
+ //if (x<0 || x>=width)
268
+ // x = __min(__max(x,0),width-1);
269
+ //if (y<0 || y>=height)
270
+ // y= __min(__max(y,0),height-1);
271
+
272
+ memcpy(sift_cell.pData+count*nBins,imband_cell.pData+(y*width+x)*nBins,sizeof(double)*nBins);
273
+ count++;
274
+ }
275
+ // normalize the SIFT descriptor
276
+ double mag = sqrt(sift_cell.norm2());
277
+ int offset = (i*sift_width+j)*siftdim*nScales+h*siftdim;
278
+ //memcpy(imsift.pData+offset,sift_cell.pData,sizeof(double)*siftdim);
279
+ for(int k = 0;k<siftdim;k++)
280
+ imsift.pData[offset+k] = (unsigned char)__min(sift_cell.pData[k]/(mag+0.01)*255,255);//(unsigned char) __min(sift_cell.pData[k]/mag*512,255);
281
+ }//*/
282
+ }
283
+ }
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/ImageIO.h ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef _ImageIO_h
2
+ #define _ImageIO_h
3
+
4
+ #include "cv.h"
5
+ #include "highgui.h"
6
+
7
+ using namespace cv;
8
+
9
+ class ImageIO
10
+ {
11
+ public:
12
+ enum ImageType{standard, derivative, normalized};
13
+ ImageIO(void);
14
+ ~ImageIO(void);
15
+ public:
16
+ template <class T>
17
+ static bool loadImage(const char* filename,T*& pImagePlane,int& width,int& height, int& nchannels);
18
+ template <class T>
19
+ static bool saveImage(const char* filename,const T* pImagePlane,int width,int height, int nchannels,ImageType imtype = standard);
20
+
21
+ };
22
+
23
+ template <class T>
24
+ bool ImageIO::loadImage(const char *filename, T *&pImagePlane, int &width, int &height, int &nchannels)
25
+ {
26
+ Mat im = imread(filename);
27
+ if(im.data == NULL) // if allocation fails
28
+ return false;
29
+ if(im.type()!=CV_8UC1 && im.type()!=CV_8UC3 && im.type()!=CV_8UC4) // we only support three types of image information for now
30
+ return false;
31
+ width = im.size().width;
32
+ height = im.size().height;
33
+ nchannels = im.channels();
34
+ pImagePlane = new T[width*height*nchannels];
35
+
36
+ if(typeid(T) == typeid(unsigned char))
37
+ {
38
+ for(int i = 0;i<height;i++)
39
+ memcpy(pImagePlane+i*im.step,im.data+i*im.step,width*nchannels);
40
+ return true;
41
+ }
42
+
43
+ // check whether the type is float point
44
+ bool IsFloat=false;
45
+ if(typeid(T)==typeid(double) || typeid(T)==typeid(float) || typeid(T)==typeid(long double))
46
+ IsFloat=true;
47
+
48
+ for(int i =0;i<height;i++)
49
+ {
50
+ int offset1 = i*width*nchannels;
51
+ int offset2 = i*im.step;
52
+ for(int j=0;j<im.step;j++)
53
+ {
54
+ if(IsFloat)
55
+ pImagePlane[offset1+j] = (T)im.data[offset2+j]/255;
56
+ else
57
+ pImagePlane[offset1+j] = im.data[offset2+j];
58
+ }
59
+ }
60
+ return true;
61
+ }
62
+
63
+ template <class T>
64
+ bool ImageIO::saveImage(const char* filename,const T* pImagePlane,int width,int height, int nchannels,ImageType imtype)
65
+ {
66
+ Mat im;
67
+ switch(nchannels){
68
+ case 1:
69
+ im.create(height,width,CV_8UC1);
70
+ break;
71
+ case 3:
72
+ im.create(height,width,CV_8UC3);
73
+ break;
74
+ default:
75
+ return -1;
76
+ }
77
+ // check whether the type is float point
78
+ bool IsFloat=false;
79
+ if(typeid(T)==typeid(double) || typeid(T)==typeid(float) || typeid(T)==typeid(long double))
80
+ IsFloat=true;
81
+
82
+ T Max,Min;
83
+ int nElements = width*height*nchannels;
84
+ switch(imtype){
85
+ case standard:
86
+ break;
87
+ case derivative:
88
+ // find the max of the absolute value
89
+ Max = pImagePlane[0];
90
+ if(!IsFloat)
91
+ for(int i = 0;i<nElements;i++)
92
+ Max = __max(Max,abs(pImagePlane[i]));
93
+ else
94
+ for(int i=0;i<nElements;i++)
95
+ Max = __max(Max,fabs((double)pImagePlane[i]));
96
+ Max*=2;
97
+ break;
98
+ case normalized:
99
+ Max = Min = pImagePlane[0];
100
+ for(int i = 0;i<nElements;i++)
101
+ {
102
+ Max = __max(Max,pImagePlane[i]);
103
+ Min = __min(Min,pImagePlane[i]);
104
+ }
105
+ break;
106
+ }
107
+ if(typeid(T) == typeid(unsigned char) && imtype == standard)
108
+ {
109
+ for(int i = 0;i<height;i++)
110
+ memcpy(im.data+i*im.step,pImagePlane+i*im.step,width*nchannels);
111
+ }
112
+ else
113
+ {
114
+ for(int i =0;i<height;i++)
115
+ {
116
+ int offset1 = i*width*nchannels;
117
+ int offset2 = i*im.step;
118
+ for(int j=0;j<im.step;j++)
119
+ {
120
+ switch(imtype){
121
+ case standard:
122
+ if(IsFloat)
123
+ im.data[offset2+j] = pImagePlane[offset1+j]*255;
124
+ else
125
+ im.data[offset2+j] = pImagePlane[offset1+j];
126
+ break;
127
+ case derivative:
128
+
129
+ if(IsFloat)
130
+ im.data[offset2+j] = (double)(pImagePlane[offset1+j]/Max+0.5)*255;
131
+ else
132
+ im.data[offset2+j] = ((double)pImagePlane[offset1+j]/Max+0.5)*255;
133
+ break;
134
+ case normalized:
135
+ im.data[offset2+j] = (double)(pImagePlane[offset1+j]-Min)/(Max-Min)*255;
136
+ break;
137
+ }
138
+ }
139
+ }
140
+ }
141
+ return imwrite(filename,im);
142
+ }
143
+
144
+
145
+
146
+ /*
147
+ #include <QVector>
148
+ #include <QImage>
149
+ #include <QString>
150
+ #include "math.h"
151
+ //-----------------------------------------------------------------------------------------
152
+ // this class is a wrapper to use QImage to load image into image planes
153
+ //-----------------------------------------------------------------------------------------
154
+
155
+ class ImageIO
156
+ {
157
+ public:
158
+ enum ImageType{standard, derivative, normalized};
159
+ ImageIO(void);
160
+ ~ImageIO(void);
161
+ public:
162
+ template <class T>
163
+ static void loadImage(const QImage& image,T*& pImagePlane,int& width,int& height,int& nchannels);
164
+ template <class T>
165
+ static bool loadImage(const QString& filename,T*& pImagePlane,int& width,int& height,int& nchannels);
166
+
167
+ template <class T>
168
+ static unsigned char convertPixel(const T& value,bool IsFloat,ImageType type,T& _Max,T& _Min);
169
+
170
+ template <class T>
171
+ static bool writeImage(const QString& filename, const T*& pImagePlane,int width,int height,int nchannels,ImageType type=standard,int quality=-1);
172
+
173
+ template <class T>
174
+ static bool writeImage(const QString& filename,const T* pImagePlane,int width,int height,int nchannels,T min, T max,int quality=-1);
175
+
176
+ };
177
+
178
+ template <class T>
179
+ void ImageIO::loadImage(const QImage& image, T*& pImagePlane,int& width,int& height,int& nchannels)
180
+ {
181
+ // get the image information
182
+ width=image.width();
183
+ height=image.height();
184
+ nchannels=3;
185
+ pImagePlane=new T[width*height*nchannels];
186
+
187
+ // check whether the type is float point
188
+ bool IsFloat=false;
189
+ if(typeid(T)==typeid(double) || typeid(T)==typeid(float) || typeid(T)==typeid(long double))
190
+ IsFloat=true;
191
+
192
+ const unsigned char* plinebuffer;
193
+ for(int i=0;i<height;i++)
194
+ {
195
+ plinebuffer=image.scanLine(i);
196
+ for(int j=0;j<width;j++)
197
+ {
198
+ if(IsFloat)
199
+ {
200
+ pImagePlane[(i*width+j)*3]=(T)plinebuffer[j*4]/255;
201
+ pImagePlane[(i*width+j)*3+1]=(T)plinebuffer[j*4+1]/255;
202
+ pImagePlane[(i*width+j)*3+2]=(T)plinebuffer[j*4+2]/255;
203
+ }
204
+ else
205
+ {
206
+ pImagePlane[(i*width+j)*3]=plinebuffer[j*4];
207
+ pImagePlane[(i*width+j)*3+1]=plinebuffer[j*4+1];
208
+ pImagePlane[(i*width+j)*3+2]=plinebuffer[j*4+2];
209
+ }
210
+ }
211
+ }
212
+ }
213
+
214
+ template <class T>
215
+ bool ImageIO::loadImage(const QString&filename, T*& pImagePlane,int& width,int& height,int& nchannels)
216
+ {
217
+ QImage image;
218
+ if(image.load(filename)==false)
219
+ return false;
220
+ if(image.format()!=QImage::Format_RGB32)
221
+ {
222
+ QImage temp=image.convertToFormat(QImage::Format_RGB32);
223
+ image=temp;
224
+ }
225
+ loadImage(image,pImagePlane,width,height,nchannels);
226
+ return true;
227
+ }
228
+
229
+ template <class T>
230
+ bool ImageIO::writeImage(const QString& filename, const T*& pImagePlane,int width,int height,int nchannels,ImageType type,int quality)
231
+ {
232
+ int nPixels=width*height,nElements;
233
+ nElements=nPixels*nchannels;
234
+ unsigned char* pTempBuffer;
235
+ pTempBuffer=new unsigned char[nPixels*4];
236
+ memset(pTempBuffer,0,nPixels*4);
237
+
238
+ // check whether the type is float point
239
+ bool IsFloat=false;
240
+ if(typeid(T)==typeid(double) || typeid(T)==typeid(float) || typeid(T)==typeid(long double))
241
+ IsFloat=true;
242
+
243
+ T _Max=0,_Min=0;
244
+ switch(type){
245
+ case standard:
246
+ break;
247
+ case derivative:
248
+ _Max=0;
249
+ for(int i=0;i<nPixels;i++)
250
+ {
251
+ if(IsFloat)
252
+ _Max=__max(_Max,fabs((double)pImagePlane[i]));
253
+ else
254
+ _Max=__max(_Max,abs(pImagePlane[i]));
255
+ }
256
+ break;
257
+ case normalized:
258
+ _Min=_Max=pImagePlane[0];
259
+ for(int i=1;i<nElements;i++)
260
+ {
261
+ _Min=__min(_Min,pImagePlane[i]);
262
+ _Max=__max(_Max,pImagePlane[i]);
263
+ }
264
+ break;
265
+ }
266
+
267
+ for(int i=0;i<nPixels;i++)
268
+ {
269
+ if(nchannels>=3)
270
+ {
271
+ pTempBuffer[i*4]=convertPixel(pImagePlane[i*nchannels],IsFloat,type,_Max,_Min);
272
+ pTempBuffer[i*4+1]=convertPixel(pImagePlane[i*nchannels+1],IsFloat,type,_Max,_Min);
273
+ pTempBuffer[i*4+2]=convertPixel(pImagePlane[i*nchannels+2],IsFloat,type,_Max,_Min);
274
+ }
275
+ else
276
+ for (int j=0;j<3;j++)
277
+ pTempBuffer[i*4+j]=convertPixel(pImagePlane[i*nchannels],IsFloat,type,_Max,_Min);
278
+ pTempBuffer[i*4+3]=255;
279
+ }
280
+ QImage *pQImage=new QImage(pTempBuffer,width,height,QImage::Format_RGB32);
281
+ bool result= pQImage->save(filename,0,quality);
282
+ delete pQImage;
283
+ delete pTempBuffer;
284
+ return result;
285
+ }
286
+
287
+ template <class T>
288
+ bool ImageIO::writeImage(const QString& filename, const T* pImagePlane,int width,int height,int nchannels,T min,T max,int quality)
289
+ {
290
+ int nPixels=width*height,nElements;
291
+ nElements=nPixels*nchannels;
292
+ unsigned char* pTempBuffer;
293
+ pTempBuffer=new unsigned char[nPixels*4];
294
+ memset(pTempBuffer,0,nPixels*4);
295
+
296
+ // check whether the type is float point
297
+ bool IsFloat=false;
298
+ if(typeid(T)==typeid(double) || typeid(T)==typeid(float) || typeid(T)==typeid(long double))
299
+ IsFloat=true;
300
+
301
+ T _Max=max,_Min=min;
302
+
303
+ for(int i=0;i<nPixels;i++)
304
+ {
305
+ if(nchannels>=3)
306
+ {
307
+ pTempBuffer[i*4]=convertPixel(pImagePlane[i*nchannels],IsFloat,normalized,_Max,_Min);
308
+ pTempBuffer[i*4+1]=convertPixel(pImagePlane[i*nchannels+1],IsFloat,normalized,_Max,_Min);
309
+ pTempBuffer[i*4+2]=convertPixel(pImagePlane[i*nchannels+2],IsFloat,normalized,_Max,_Min);
310
+ }
311
+ else
312
+ for (int j=0;j<3;j++)
313
+ pTempBuffer[i*4+j]=convertPixel(pImagePlane[i*nchannels],IsFloat,normalized,_Max,_Min);
314
+ pTempBuffer[i*4+3]=255;
315
+ }
316
+ QImage *pQImage=new QImage(pTempBuffer,width,height,QImage::Format_RGB32);
317
+ bool result= pQImage->save(filename,0,quality);
318
+ delete pQImage;
319
+ delete pTempBuffer;
320
+ return result;
321
+ }
322
+
323
+ template <class T>
324
+ unsigned char ImageIO::convertPixel(const T& value,bool IsFloat,ImageType type,T& _Max,T& _Min)
325
+ {
326
+ switch(type){
327
+ case standard:
328
+ if(IsFloat)
329
+ return __max(__min(value*255,255),0);
330
+ else
331
+ return __max(__min(value,255),0);
332
+ break;
333
+ case derivative:
334
+ return (double)((double)value/_Max+1)/2*255;
335
+ break;
336
+ case normalized:
337
+ return (double)(value-_Min)/(_Max-_Min)*255;
338
+ break;
339
+ }
340
+ return 0;
341
+ }
342
+ //*/
343
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/ImageProcessing.h ADDED
@@ -0,0 +1,414 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef _ImageProcessing_h
2
+ #define _ImageProcessing_h
3
+
4
+ #include "math.h"
5
+ #include "stdio.h"
6
+ #include "stdlib.h"
7
+ #include <typeinfo>
8
+
9
+ //----------------------------------------------------------------------------------
10
+ // class to handle basic image processing functions
11
+ // this is a collection of template functions. These template functions are
12
+ // used in other image classes such as BiImage, IntImage and FImage
13
+ //----------------------------------------------------------------------------------
14
+
15
+ class ImageProcessing
16
+ {
17
+ public:
18
+ ImageProcessing(void);
19
+ ~ImageProcessing(void);
20
+ public:
21
+ // basic functions
22
+ template <class T>
23
+ static inline T EnforceRange(const T& x,const int& MaxValue) {return __min(__max(x,0),MaxValue-1);};
24
+
25
+ //---------------------------------------------------------------------------------
26
+ // function to interpolate the image plane
27
+ //---------------------------------------------------------------------------------
28
+ template <class T1,class T2>
29
+ static inline void BilinearInterpolate(const T1* pImage,int width,int height,int nChannels,double x,double y,T2* result);
30
+
31
+ template <class T1>
32
+ static inline T1 BilinearInterpolate(const T1* pImage,int width,int height,double x,double y);
33
+
34
+ template <class T1,class T2>
35
+ static void ResizeImage(const T1* pSrcImage,T2* pDstImage,int SrcWidth,int SrcHeight,int nChannels,double Ratio);
36
+
37
+ template <class T1,class T2>
38
+ static void ResizeImage(const T1* pSrcImage,T2* pDstImage,int SrcWidth,int SrcHeight,int nChannels,int DstWidth,int DstHeight);
39
+
40
+ //---------------------------------------------------------------------------------
41
+ // functions for 1D filtering
42
+ //---------------------------------------------------------------------------------
43
+ template <class T1,class T2>
44
+ static void hfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter1D,int fsize);
45
+
46
+ template <class T1,class T2>
47
+ static void vfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter1D,int fsize);
48
+
49
+ //---------------------------------------------------------------------------------
50
+ // functions for 2D filtering
51
+ //---------------------------------------------------------------------------------
52
+ template <class T1,class T2>
53
+ static void filtering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter2D,int fsize);
54
+
55
+ template <class T1,class T2>
56
+ static void Laplacian(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels);
57
+
58
+ //---------------------------------------------------------------------------------
59
+ // functions for sample a patch from the image
60
+ //---------------------------------------------------------------------------------
61
+ template <class T1,class T2>
62
+ static void getPatch(const T1* pSrcImgae,T2* pPatch,int width,int height,int nChannels,double x,double y,int wsize);
63
+
64
+ //---------------------------------------------------------------------------------
65
+ // function to warp image
66
+ //---------------------------------------------------------------------------------
67
+ template <class T1,class T2>
68
+ static void warpImage(T1* pWarpIm2,const T1* pIm1,const T1* pIm2,const T2* pVx,const T2* pVy,int width,int height,int nChannels);
69
+
70
+ template <class T1,class T2,class T3>
71
+ static void warpImage(T1 *pWarpIm2, T3* pMask,const T1 *pIm1, const T1 *pIm2, const T2 *pVx, const T2 *pVy, int width, int height, int nChannels);
72
+
73
+
74
+ //---------------------------------------------------------------------------------
75
+ // function to crop an image
76
+ //---------------------------------------------------------------------------------
77
+ template <class T1,class T2>
78
+ static void cropImage(const T1* pSrcImage,int SrcWidth,int SrcHeight,int nChannels,T2* pDstImage,int Left,int Top,int DstWidth,int DstHeight);
79
+ //---------------------------------------------------------------------------------
80
+
81
+ //---------------------------------------------------------------------------------
82
+ // function to generate a 2D Gaussian
83
+ //---------------------------------------------------------------------------------
84
+ template <class T>
85
+ static void generate2DGaussian(T*& pImage,int wsize,double sigma=-1);
86
+ };
87
+
88
+ //--------------------------------------------------------------------------------------------------
89
+ // function to interplate multi-channel image plane for (x,y)
90
+ // --------------------------------------------------------------------------------------------------
91
+ template <class T1,class T2>
92
+ inline void ImageProcessing::BilinearInterpolate(const T1* pImage,int width,int height,int nChannels,double x,double y,T2* result)
93
+ {
94
+ int xx,yy,m,n,u,v,l,offset;
95
+ xx=x;
96
+ yy=y;
97
+ double dx,dy,s;
98
+ dx=__max(__min(x-xx,1),0);
99
+ dy=__max(__min(y-yy,1),0);
100
+
101
+ memset(result,0,sizeof(T2)*nChannels);
102
+
103
+ for(m=0;m<=1;m++)
104
+ for(n=0;n<=1;n++)
105
+ {
106
+ u=EnforceRange(xx+m,width);
107
+ v=EnforceRange(yy+n,height);
108
+ offset=(v*width+u)*nChannels;
109
+ s=fabs(1-m-dx)*fabs(1-n-dy);
110
+ for(l=0;l<nChannels;l++)
111
+ result[l]+=pImage[offset+l]*s;
112
+ }
113
+ }
114
+
115
+ template <class T1>
116
+ inline T1 ImageProcessing::BilinearInterpolate(const T1* pImage,int width,int height,double x,double y)
117
+ {
118
+ int xx,yy,m,n,u,v,l,offset;
119
+ xx=x;
120
+ yy=y;
121
+ double dx,dy,s;
122
+ dx=__max(__min(x-xx,1),0);
123
+ dy=__max(__min(y-yy,1),0);
124
+
125
+ T1 result=0;
126
+ for(m=0;m<=1;m++)
127
+ for(n=0;n<=1;n++)
128
+ {
129
+ u=EnforceRange(xx+m,width);
130
+ v=EnforceRange(yy+n,height);
131
+ offset=v*width+u;
132
+ s=fabs(1-m-dx)*fabs(1-n-dy);
133
+ result+=pImage[offset]*s;
134
+ }
135
+ return result;
136
+ }
137
+ //------------------------------------------------------------------------------------------------------------
138
+ // this is the most general function for reszing an image with a varying nChannels
139
+ // bilinear interpolation is used for now. It might be replaced by other (bicubic) interpolation methods
140
+ //------------------------------------------------------------------------------------------------------------
141
+ template <class T1,class T2>
142
+ void ImageProcessing::ResizeImage(const T1* pSrcImage,T2* pDstImage,int SrcWidth,int SrcHeight,int nChannels,double Ratio)
143
+ {
144
+ int DstWidth,DstHeight;
145
+ DstWidth=(double)SrcWidth*Ratio;
146
+ DstHeight=(double)SrcHeight*Ratio;
147
+ memset(pDstImage,sizeof(T2)*DstWidth*DstHeight*nChannels,0);
148
+
149
+ double x,y;
150
+
151
+ for(int i=0;i<DstHeight;i++)
152
+ for(int j=0;j<DstWidth;j++)
153
+ {
154
+ x=(double)(j+1)/Ratio-1;
155
+ y=(double)(i+1)/Ratio-1;
156
+
157
+ // bilinear interpolation
158
+ BilinearInterpolate(pSrcImage,SrcWidth,SrcHeight,nChannels,x,y,pDstImage+(i*DstWidth+j)*nChannels);
159
+ }
160
+ }
161
+
162
+ template <class T1,class T2>
163
+ void ImageProcessing::ResizeImage(const T1 *pSrcImage, T2 *pDstImage, int SrcWidth, int SrcHeight, int nChannels, int DstWidth, int DstHeight)
164
+ {
165
+ double xRatio=(double)DstWidth/SrcWidth;
166
+ double yRatio=(double)DstHeight/SrcHeight;
167
+ memset(pDstImage,sizeof(T2)*DstWidth*DstHeight*nChannels,0);
168
+
169
+ double x,y;
170
+
171
+ for(int i=0;i<DstHeight;i++)
172
+ for(int j=0;j<DstWidth;j++)
173
+ {
174
+ x=(double)(j+1)/xRatio-1;
175
+ y=(double)(i+1)/yRatio-1;
176
+
177
+ // bilinear interpolation
178
+ BilinearInterpolate(pSrcImage,SrcWidth,SrcHeight,nChannels,x,y,pDstImage+(i*DstWidth+j)*nChannels);
179
+ }
180
+ }
181
+
182
+ //------------------------------------------------------------------------------------------------------------
183
+ // horizontal direction filtering
184
+ //------------------------------------------------------------------------------------------------------------
185
+ template <class T1,class T2>
186
+ void ImageProcessing::hfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter1D,int fsize)
187
+ {
188
+ memset(pDstImage,0,sizeof(T2)*width*height*nChannels);
189
+ T2* pBuffer;
190
+ double w;
191
+ int i,j,l,k,offset,jj;
192
+ for(i=0;i<height;i++)
193
+ for(j=0;j<width;j++)
194
+ {
195
+ offset=i*width*nChannels;
196
+ pBuffer=pDstImage+offset+j*nChannels;
197
+ for(l=-fsize;l<=fsize;l++)
198
+ {
199
+ w=pfilter1D[l+fsize];
200
+ jj=EnforceRange(j+l,width);
201
+ for(k=0;k<nChannels;k++)
202
+ pBuffer[k]+=pSrcImage[offset+jj*nChannels+k]*w;
203
+ }
204
+ }
205
+ }
206
+
207
+ //------------------------------------------------------------------------------------------------------------
208
+ // fast filtering algorithm for laplacian
209
+ //------------------------------------------------------------------------------------------------------------
210
+ template <class T1,class T2>
211
+ void ImageProcessing::Laplacian(const T1 *pSrcImage, T2 *pDstImage, int width, int height, int nChannels)
212
+ {
213
+ int LineWidth=width*nChannels;
214
+ int nElements=width*height*nChannels;
215
+ // first treat the corners
216
+ for(int k=0;k<nChannels;k++)
217
+ {
218
+ pDstImage[k]=pSrcImage[k]*2-pSrcImage[nChannels+k]-pSrcImage[LineWidth+k];
219
+ pDstImage[LineWidth-nChannels+k]=pSrcImage[LineWidth-nChannels+k]*2-pSrcImage[LineWidth-2*nChannels+k]-pSrcImage[2*LineWidth-nChannels+k];
220
+ pDstImage[nElements-LineWidth+k]=pSrcImage[nElements-LineWidth+k]*2-pSrcImage[nElements-LineWidth+nChannels+k]-pSrcImage[nElements-2*LineWidth+k];
221
+ pDstImage[nElements-nChannels+k]=pSrcImage[nElements-nChannels+k]*2-pSrcImage[nElements-2*nChannels+k]-pSrcImage[nElements-LineWidth-nChannels+k];
222
+ }
223
+ // then treat the borders
224
+ for(int i=1;i<width-1;i++)
225
+ for(int k=0;k<nChannels;k++)
226
+ {
227
+ pDstImage[i*nChannels+k]=pSrcImage[i*nChannels+k]*3-pSrcImage[(i-1)*nChannels+k]-pSrcImage[(i+1)*nChannels+k]-pSrcImage[i*nChannels+LineWidth+k];
228
+ pDstImage[nElements-LineWidth+i*nChannels+k]=pSrcImage[nElements-LineWidth+i*nChannels+k]*3-pSrcImage[nElements-LineWidth+(i-1)*nChannels+k]-pSrcImage[nElements-LineWidth+(i+1)*nChannels+k]-pSrcImage[nElements-2*LineWidth+i*nChannels+k];
229
+ }
230
+ for(int i=1;i<height-1;i++)
231
+ for(int k=0;k<nChannels;k++)
232
+ {
233
+ pDstImage[i*LineWidth+k]=pSrcImage[i*LineWidth+k]*3-pSrcImage[i*LineWidth+nChannels+k]-pSrcImage[(i-1)*LineWidth+k]-pSrcImage[(i+1)*LineWidth+k];
234
+ pDstImage[(i+1)*LineWidth-nChannels+k]=pSrcImage[(i+1)*LineWidth-nChannels+k]*3-pSrcImage[(i+1)*LineWidth-2*nChannels+k]-pSrcImage[i*LineWidth-nChannels+k]-pSrcImage[(i+2)*LineWidth-nChannels+k];
235
+ }
236
+ // now the interior
237
+ for(int i=1;i<height-1;i++)
238
+ for(int j=1;j<width-1;j++)
239
+ {
240
+ int offset=(i*width+j)*nChannels;
241
+ for(int k=0;k<nChannels;k++)
242
+ pDstImage[offset+k]=pSrcImage[offset+k]*4-pSrcImage[offset+nChannels+k]-pSrcImage[offset-nChannels+k]-pSrcImage[offset-LineWidth+k]-pSrcImage[offset+LineWidth+k];
243
+ }
244
+ }
245
+
246
+
247
+ //------------------------------------------------------------------------------------------------------------
248
+ // vertical direction filtering
249
+ //------------------------------------------------------------------------------------------------------------
250
+ template <class T1,class T2>
251
+ void ImageProcessing::vfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter1D,int fsize)
252
+ {
253
+ memset(pDstImage,0,sizeof(T2)*width*height*nChannels);
254
+ T2* pBuffer;
255
+ double w;
256
+ int i,j,l,k,offset,ii;
257
+ for(i=0;i<height;i++)
258
+ for(j=0;j<width;j++)
259
+ {
260
+ pBuffer=pDstImage+(i*width+j)*nChannels;
261
+ for(l=-fsize;l<=fsize;l++)
262
+ {
263
+ w=pfilter1D[l+fsize];
264
+ ii=EnforceRange(i+l,height);
265
+ for(k=0;k<nChannels;k++)
266
+ pBuffer[k]+=pSrcImage[(ii*width+j)*nChannels+k]*w;
267
+ }
268
+ }
269
+ }
270
+
271
+ //------------------------------------------------------------------------------------------------------------
272
+ // 2d filtering
273
+ //------------------------------------------------------------------------------------------------------------
274
+ template <class T1,class T2>
275
+ void ImageProcessing::filtering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter2D,int fsize)
276
+ {
277
+ double w;
278
+ int i,j,u,v,k,ii,jj,wsize,offset;
279
+ wsize=fsize*2+1;
280
+ double* pBuffer=new double[nChannels];
281
+ for(i=0;i<height;i++)
282
+ for(j=0;j<width;j++)
283
+ {
284
+ for(k=0;k<nChannels;k++)
285
+ pBuffer[k]=0;
286
+ for(u=-fsize;u<=fsize;u++)
287
+ for(v=-fsize;v<=fsize;v++)
288
+ {
289
+ w=pfilter2D[(u+fsize)*wsize+v+fsize];
290
+ ii=EnforceRange(i+u,height);
291
+ jj=EnforceRange(j+v,width);
292
+ offset=(ii*width+jj)*nChannels;
293
+ for(k=0;k<nChannels;k++)
294
+ pBuffer[k]+=pSrcImage[offset+k]*w;
295
+ }
296
+ offset=(i*width+j)*nChannels;
297
+ for(k=0;k<nChannels;k++)
298
+ pDstImage[offset+k]=pBuffer[k];
299
+ }
300
+ delete pBuffer;
301
+ }
302
+
303
+ //------------------------------------------------------------------------------------------------------------
304
+ // function to sample a patch from the source image
305
+ //------------------------------------------------------------------------------------------------------------
306
+ template <class T1,class T2>
307
+ void ImageProcessing::getPatch(const T1* pSrcImage,T2* pPatch,int width,int height,int nChannels,double x0,double y0,int wsize)
308
+ {
309
+ // suppose pPatch has been allocated and cleared before calling the function
310
+ int wlength=wsize*2+1;
311
+ double x,y;
312
+ for(int i=-wsize;i<=wsize;i++)
313
+ for(int j=-wsize;j<=wsize;j++)
314
+ {
315
+ y=y0+i;
316
+ x=x0+j;
317
+ if(x<0 || x>width-1 || y<0 || y>height-1)
318
+ continue;
319
+ BilinearInterpolate(pSrcImage,width,height,nChannels,x,y,pPatch+((i+wsize)*wlength+j+wsize)*nChannels);
320
+ }
321
+ }
322
+
323
+ //------------------------------------------------------------------------------------------------------------
324
+ // function to warp an image with respect to flow field
325
+ // pWarpIm2 has to be allocated before hands
326
+ //------------------------------------------------------------------------------------------------------------
327
+ template <class T1,class T2>
328
+ void ImageProcessing::warpImage(T1 *pWarpIm2, const T1 *pIm1, const T1 *pIm2, const T2 *pVx, const T2 *pVy, int width, int height, int nChannels)
329
+ {
330
+ for(int i=0;i<height;i++)
331
+ for(int j=0;j<width;j++)
332
+ {
333
+ int offset=i*width+j;
334
+ double x,y;
335
+ y=i+pVy[offset];
336
+ x=j+pVx[offset];
337
+ offset*=nChannels;
338
+ if(x<0 || x>width-1 || y<0 || y>height-1)
339
+ {
340
+ for(int k=0;k<nChannels;k++)
341
+ pWarpIm2[offset+k]=pIm1[offset+k];
342
+ continue;
343
+ }
344
+ BilinearInterpolate(pIm2,width,height,nChannels,x,y,pWarpIm2+offset);
345
+ }
346
+ }
347
+
348
+ template <class T1,class T2,class T3>
349
+ void ImageProcessing::warpImage(T1 *pWarpIm2, T3* pMask,const T1 *pIm1, const T1 *pIm2, const T2 *pVx, const T2 *pVy, int width, int height, int nChannels)
350
+ {
351
+ for(int i=0;i<height;i++)
352
+ for(int j=0;j<width;j++)
353
+ {
354
+ int offset=i*width+j;
355
+ double x,y;
356
+ y=i+pVy[offset];
357
+ x=j+pVx[offset];
358
+ offset*=nChannels;
359
+ if(x<0 || x>width-1 || y<0 || y>height-1)
360
+ {
361
+ for(int k=0;k<nChannels;k++)
362
+ pWarpIm2[offset+k]=pIm1[offset+k];
363
+ pMask[i*width+j]=0;
364
+ continue;
365
+ }
366
+ pMask[i*width+j]=1;
367
+ BilinearInterpolate(pIm2,width,height,nChannels,x,y,pWarpIm2+offset);
368
+ }
369
+ }
370
+
371
+ //------------------------------------------------------------------------------------------------------------
372
+ // function to crop an image from the source
373
+ // assume that pDstImage has been allocated
374
+ // also Left and Top must be valid, DstWidth and DstHeight should ensure that the image lies
375
+ // inside the image boundary
376
+ //------------------------------------------------------------------------------------------------------------
377
+ template <class T1,class T2>
378
+ void ImageProcessing::cropImage(const T1 *pSrcImage, int SrcWidth, int SrcHeight, int nChannels, T2 *pDstImage, int Left, int Top, int DstWidth, int DstHeight)
379
+ {
380
+ if(typeid(T1)==typeid(T2))
381
+ {
382
+ for(int i=0;i<DstHeight;i++)
383
+ memcpy(pDstImage+i*DstWidth*nChannels,pSrcImage+((i+Top)*SrcWidth+Left)*nChannels,sizeof(T1)*DstWidth*nChannels);
384
+ return;
385
+ }
386
+ int offsetSrc,offsetDst;
387
+ for(int i=0;i<DstHeight;i++)
388
+ for(int j=0;j<DstWidth;j++)
389
+ {
390
+ offsetSrc=((i+Top)*SrcWidth+Left+j)*nChannels;
391
+ offsetDst=(i*DstWidth+j)*nChannels;
392
+ for(int k=0;k<nChannels;k++)
393
+ pDstImage[offsetDst+k]=pSrcImage[offsetSrc+k];
394
+ }
395
+ }
396
+
397
+ //------------------------------------------------------------------------------------------------------------
398
+ // function to generate a 2D Gaussian image
399
+ // pImage must be allocated before calling the function
400
+ //------------------------------------------------------------------------------------------------------------
401
+ template <class T>
402
+ void ImageProcessing::generate2DGaussian(T*& pImage, int wsize, double sigma)
403
+ {
404
+ if(sigma==-1)
405
+ sigma=wsize;
406
+ double alpha=1/(2*sigma*sigma);
407
+ int winlength=wsize*2+1;
408
+ if(pImage==NULL)
409
+ pImage=new T[winlength*winlength];
410
+ for(int i=-wsize;i<=wsize;i++)
411
+ for(int j=-wsize;j<=wsize;j++)
412
+ pImage[(i+wsize)*winlength+j+wsize]=exp(-(double)(i*i+j*j)*alpha);
413
+ }
414
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/Matrix.cpp ADDED
@@ -0,0 +1,419 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "Matrix.h"
2
+ #include "memory.h"
3
+ #include <iostream>
4
+
5
+ using namespace std;
6
+
7
+ bool Matrix::IsDispInfo=false;
8
+
9
+ Matrix::Matrix(void)
10
+ {
11
+ nRow=nCol=0;
12
+ pData=NULL;
13
+ }
14
+
15
+ Matrix::Matrix(int nrow,int ncol,double* data)
16
+ {
17
+ nRow=nrow;
18
+ nCol=ncol;
19
+ pData=new double[nRow*nCol];
20
+ if(data==NULL)
21
+ memset(pData,0,sizeof(double)*nRow*nCol);
22
+ else
23
+ memcpy(pData,data,sizeof(double)*nRow*nCol);
24
+ }
25
+
26
+ Matrix::Matrix(const Matrix& matrix)
27
+ {
28
+ nRow=nCol=0;
29
+ pData=NULL;
30
+ copyData(matrix);
31
+ }
32
+
33
+ Matrix::~Matrix(void)
34
+ {
35
+ releaseData();
36
+ }
37
+
38
+ void Matrix::releaseData()
39
+ {
40
+ if(pData!=NULL)
41
+ delete pData;
42
+ pData=NULL;
43
+ nRow=nCol=0;
44
+ }
45
+
46
+ void Matrix::copyData(const Matrix &matrix)
47
+ {
48
+ if(!dimMatch(matrix))
49
+ allocate(matrix);
50
+ memcpy(pData,matrix.pData,sizeof(double)*nRow*nCol);
51
+ }
52
+
53
+ bool Matrix::dimMatch(const Matrix& matrix) const
54
+ {
55
+ if(nCol==matrix.nCol && nRow==matrix.nRow)
56
+ return true;
57
+ else
58
+ return false;
59
+ }
60
+
61
+ bool Matrix::dimcheck(const Matrix& matrix) const
62
+ {
63
+ if(!dimMatch(matrix))
64
+ {
65
+ cout<<"The dimensions of the matrices don't match!"<<endl;
66
+ return false;
67
+ }
68
+ return true;
69
+ }
70
+
71
+ void Matrix::reset()
72
+ {
73
+ if(pData!=NULL)
74
+ memset(pData,0,sizeof(double)*nRow*nCol);
75
+ }
76
+
77
+ void Matrix::allocate(int nrow,int ncol)
78
+ {
79
+ releaseData();
80
+ nRow=nrow;
81
+ nCol=ncol;
82
+ if(nRow*nCol>0)
83
+ pData=new double[nRow*nCol];
84
+ }
85
+
86
+ void Matrix::allocate(const Matrix& matrix)
87
+ {
88
+ allocate(matrix.nRow,matrix.nCol);
89
+ }
90
+
91
+ void Matrix::loadData(int _nrow, int _ncol, double *data)
92
+ {
93
+ if(!matchDimension(_nrow,_ncol))
94
+ allocate(_nrow,_ncol);
95
+ memcpy(pData,data,sizeof(double)*nRow*nCol);
96
+ }
97
+
98
+ void Matrix::printMatrix()
99
+ {
100
+ for(int i=0;i<nRow;i++)
101
+ {
102
+ for(int j=0;j<nCol;j++)
103
+ cout<<pData[i*nCol+j]<<" ";
104
+ cout<<endl;
105
+ }
106
+ }
107
+
108
+ void Matrix::identity(int ndim)
109
+ {
110
+ allocate(ndim,ndim);
111
+ reset();
112
+ for(int i=0;i<ndim;i++)
113
+ pData[i*ndim+i]=1;
114
+ }
115
+
116
+ //--------------------------------------------------------------------------------------------------
117
+ // functions to check dimensionalities
118
+ //--------------------------------------------------------------------------------------------------
119
+ bool Matrix::checkDimRight(const Vector& vect) const
120
+ {
121
+ if(nCol==vect.dim())
122
+ return true;
123
+ else
124
+ {
125
+ cout<<"The matrix and vector don't match in multiplication!"<<endl;
126
+ return false;
127
+ }
128
+ }
129
+
130
+ bool Matrix::checkDimRight(const Matrix &matrix) const
131
+ {
132
+ if(nCol==matrix.nrow())
133
+ return true;
134
+ else
135
+ {
136
+ cout<<"The matrix and matrix don't match in multiplication!"<<endl;
137
+ return false;
138
+ }
139
+ }
140
+
141
+ bool Matrix::checkDimLeft(const Vector& vect) const
142
+ {
143
+ if(nRow==vect.dim())
144
+ return true;
145
+ else
146
+ {
147
+ cout<<"The vector and matrix don't match in multiplication!"<<endl;
148
+ return false;
149
+ }
150
+ }
151
+
152
+ bool Matrix::checkDimLeft(const Matrix &matrix) const
153
+ {
154
+ if(nRow==matrix.ncol())
155
+ return true;
156
+ else
157
+ {
158
+ cout<<"The matrix and matrix don't match in multiplication!"<<endl;
159
+ return false;
160
+ }
161
+ }
162
+
163
+ //--------------------------------------------------------------------------------------------------
164
+ // functions for numerical computation
165
+ //--------------------------------------------------------------------------------------------------
166
+ void Matrix::Multiply(Vector &result, const Vector &vect) const
167
+ {
168
+ checkDimRight(vect);
169
+ if(result.dim()!=nRow)
170
+ result.allocate(nRow);
171
+ for(int i=0;i<nRow;i++)
172
+ {
173
+ double temp=0;
174
+ for(int j=0;j<nCol;j++)
175
+ temp+=pData[i*nCol+j]*vect.data()[j];
176
+ result.data()[i]=temp;
177
+ }
178
+ }
179
+
180
+ void Matrix::Multiply(Matrix &result, const Matrix &matrix) const
181
+ {
182
+ checkDimRight(matrix);
183
+ if(!result.matchDimension(nRow,matrix.nCol))
184
+ result.allocate(nRow,matrix.nCol);
185
+ for(int i=0;i<nRow;i++)
186
+ for(int j=0;j<matrix.nCol;j++)
187
+ {
188
+ double temp=0;
189
+ for(int k=0;k<nCol;k++)
190
+ temp+=pData[i*nCol+k]*matrix.pData[k*matrix.nCol+j];
191
+ result.pData[i*matrix.nCol+j]=temp;
192
+ }
193
+ }
194
+
195
+ void Matrix::transpose(Matrix &result) const
196
+ {
197
+ if(!result.matchDimension(nCol,nRow))
198
+ result.allocate(nCol,nRow);
199
+ for(int i=0;i<nCol;i++)
200
+ for(int j=0;j<nRow;j++)
201
+ result.pData[i*nRow+j]=pData[j*nCol+i];
202
+ }
203
+
204
+ void Matrix::fromVector(const Vector &vect)
205
+ {
206
+ if(!matchDimension(vect.dim(),1))
207
+ allocate(vect.dim(),1);
208
+ memcpy(pData,vect.data(),sizeof(double)*vect.dim());
209
+ }
210
+
211
+ double Matrix::norm2() const
212
+ {
213
+ if(pData==NULL)
214
+ return 0;
215
+ double temp=0;
216
+ for(int i=0;i<nCol*nRow;i++)
217
+ temp+=pData[i]*pData[i];
218
+ return temp;
219
+ }
220
+
221
+ //--------------------------------------------------------------------------------------------------
222
+ // operators
223
+ //--------------------------------------------------------------------------------------------------
224
+ Matrix& Matrix::operator=(const Matrix& matrix)
225
+ {
226
+ copyData(matrix);
227
+ return *this;
228
+ }
229
+
230
+ Matrix& Matrix::operator +=(double val)
231
+ {
232
+ for(int i=0;i<nCol*nRow;i++)
233
+ pData[i]+=val;
234
+ return *this;
235
+ }
236
+
237
+ Matrix& Matrix::operator -=(double val)
238
+ {
239
+ for(int i=0;i<nCol*nRow;i++)
240
+ pData[i]-=val;
241
+ return *this;
242
+ }
243
+
244
+ Matrix& Matrix::operator *=(double val)
245
+ {
246
+ for(int i=0;i<nCol*nRow;i++)
247
+ pData[i]*=val;
248
+ return *this;
249
+ }
250
+
251
+ Matrix& Matrix::operator /=(double val)
252
+ {
253
+ for(int i=0;i<nCol*nRow;i++)
254
+ pData[i]/=val;
255
+ return *this;
256
+ }
257
+
258
+ Matrix& Matrix::operator +=(const Matrix &matrix)
259
+ {
260
+ dimcheck(matrix);
261
+ for(int i=0;i<nCol*nRow;i++)
262
+ pData[i]+=matrix.pData[i];
263
+ return *this;
264
+ }
265
+
266
+ Matrix& Matrix::operator -=(const Matrix &matrix)
267
+ {
268
+ dimcheck(matrix);
269
+ for(int i=0;i<nCol*nRow;i++)
270
+ pData[i]-=matrix.pData[i];
271
+ return *this;
272
+ }
273
+
274
+ Matrix& Matrix::operator *=(const Matrix &matrix)
275
+ {
276
+ dimcheck(matrix);
277
+ for(int i=0;i<nCol*nRow;i++)
278
+ pData[i]*=matrix.pData[i];
279
+ return *this;
280
+ }
281
+
282
+ Matrix& Matrix::operator /=(const Matrix &matrix)
283
+ {
284
+ dimcheck(matrix);
285
+ for(int i=0;i<nCol*nRow;i++)
286
+ pData[i]/=matrix.pData[i];
287
+ return *this;
288
+ }
289
+
290
+ Vector operator*(const Matrix& matrix,const Vector& vect)
291
+ {
292
+ Vector result;
293
+ matrix.Multiply(result,vect);
294
+ return result;
295
+ }
296
+
297
+ Matrix operator*(const Matrix& matrix1,const Matrix& matrix2)
298
+ {
299
+ Matrix result;
300
+ matrix1.Multiply(result,matrix2);
301
+ return result;
302
+ }
303
+
304
+ //--------------------------------------------------------------------------------------------------
305
+ // function for conjugate gradient method
306
+ //--------------------------------------------------------------------------------------------------
307
+ void Matrix::ConjugateGradient(Vector &result, const Vector &b) const
308
+ {
309
+ if(nCol!=nRow)
310
+ {
311
+ cout<<"Error: when solving Ax=b, A is not square!"<<endl;
312
+ return;
313
+ }
314
+ checkDimRight(b);
315
+ if(!result.matchDimension(b))
316
+ result.allocate(b);
317
+
318
+ Vector r(b),p,q;
319
+ result.reset();
320
+
321
+ int nIterations=nRow*5;
322
+ Vector rou(nIterations);
323
+ for(int k=0;k<nIterations;k++)
324
+ {
325
+ rou[k]=r.norm2();
326
+ if(IsDispInfo)
327
+ cout<<rou[k]<<endl;
328
+
329
+ if(rou[k]<1E-20)
330
+ break;
331
+ if(k==0)
332
+ p=r;
333
+ else
334
+ {
335
+ double ratio=rou[k]/rou[k-1];
336
+ p=r+p*ratio;
337
+ }
338
+ Multiply(q,p);
339
+ double alpha=rou[k]/innerproduct(p,q);
340
+ result+=p*alpha;
341
+ r-=q*alpha;
342
+ }
343
+ }
344
+
345
+ void Matrix::SolveLinearSystem(Vector &result, const Vector &b) const
346
+ {
347
+ if(nCol==nRow)
348
+ {
349
+ ConjugateGradient(result,b);
350
+ return;
351
+ }
352
+ if(nRow<nCol)
353
+ {
354
+ cout<<"Not enough observations for parameter estimation!"<<endl;
355
+ return;
356
+ }
357
+ Matrix AT,ATA;
358
+ transpose(AT);
359
+ AT.Multiply(ATA,*this);
360
+ Vector ATb;
361
+ AT.Multiply(ATb,b);
362
+ ATA.ConjugateGradient(result,ATb);
363
+ }
364
+
365
+ #ifdef _QT
366
+
367
+ bool Matrix::writeMatrix(QFile &file) const
368
+ {
369
+ file.write((char *)&nRow,sizeof(int));
370
+ file.write((char *)&nCol,sizeof(int));
371
+ if(file.write((char *)pData,sizeof(double)*nRow*nCol)!=sizeof(double)*nRow*nCol)
372
+ return false;
373
+ return true;
374
+ }
375
+
376
+ bool Matrix::readMatrix(QFile &file)
377
+ {
378
+ releaseData();
379
+ file.read((char *)&nRow,sizeof(int));
380
+ file.read((char *)&nCol,sizeof(int));
381
+ if(nRow*nCol>0)
382
+ {
383
+ allocate(nRow,nCol);
384
+ if(file.read((char *)pData,sizeof(double)*nRow*nCol)!=sizeof(double)*nRow*nCol)
385
+ return false;
386
+ }
387
+ return true;
388
+ }
389
+ #endif
390
+
391
+ #ifdef _MATLAB
392
+
393
+ void Matrix::readMatrix(const mxArray* prhs)
394
+ {
395
+ if(pData!=NULL)
396
+ delete pData;
397
+ int nElements = mxGetNumberOfDimensions(prhs);
398
+ if(nElements>2)
399
+ mexErrMsgTxt("A matrix is expected to be loaded!");
400
+ const mwSize* dims = mxGetDimensions(prhs);
401
+ allocate(dims[0],dims[1]);
402
+ double* data = (double*)mxGetData(prhs);
403
+ for(int i =0; i<nRow; i++)
404
+ for(int j =0; j<nCol; j++)
405
+ pData[i*nCol+j] = data[j*nRow+i];
406
+ }
407
+
408
+ void Matrix::writeMatrix(mxArray*& plhs) const
409
+ {
410
+ mwSize dims[2];
411
+ dims[0]=nRow;dims[1]=nCol;
412
+ plhs=mxCreateNumericArray(2, dims,mxDOUBLE_CLASS, mxREAL);
413
+ double* data = (double *)mxGetData(plhs);
414
+ for(int i =0; i<nRow; i++)
415
+ for(int j =0; j<nCol; j++)
416
+ data[j*nRow+i] = pData[i*nCol+j];
417
+ }
418
+
419
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/Matrix.h ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef _Matrix_h
2
+ #define _Matrix_h
3
+
4
+ #include "stdio.h"
5
+ #include "Vector.h"
6
+ #include "project.h"
7
+ #ifdef _QT
8
+ #include <QFile>
9
+ #endif
10
+
11
+ class Matrix
12
+ {
13
+ private:
14
+ int nRow,nCol;
15
+ double* pData;
16
+ static bool IsDispInfo;
17
+ public:
18
+ Matrix(void);
19
+ Matrix(int _nrow,int _ncol,double* data=NULL);
20
+ Matrix(const Matrix& matrix);
21
+ ~Matrix(void);
22
+ void releaseData();
23
+ void copyData(const Matrix& matrix);
24
+ void allocate(const Matrix& matrix);
25
+ void allocate(int _nrow,int _ncol);
26
+ void reset();
27
+ bool dimMatch(const Matrix& matrix) const;
28
+ bool dimcheck(const Matrix& matrix) const;
29
+ void loadData(int _nrow,int _ncol,double* data);
30
+ static void enableDispInfo(bool dispInfo=false){IsDispInfo=dispInfo;};
31
+ // display the matrix
32
+ void printMatrix();
33
+ void identity(int ndim);
34
+
35
+ // function to access the member variables
36
+ inline int nrow() const{return nRow;};
37
+ inline int ncol() const{return nCol;};
38
+ inline double* data() {return pData;};
39
+ inline const double* data() const {return (const double*)pData;};
40
+ inline double operator [](int index) const{return pData[index];};
41
+ inline double& operator[](int index) {return pData[index];};
42
+ inline double data(int row,int col)const {return pData[row*nCol+col];};
43
+ inline double& data(int row,int col) {return pData[row*nCol+col];};
44
+ bool matchDimension(int _nrow,int _ncol) const {if(nRow==_nrow && nCol==_ncol) return true; else return false;};
45
+ bool matchDimension(const Matrix& matrix) const {return matchDimension(matrix.nrow(),matrix.ncol());};
46
+
47
+ // functions to check dimensions
48
+ bool checkDimRight(const Vector& vector) const;
49
+ bool checkDimRight(const Matrix& matrix) const;
50
+ bool checkDimLeft(const Vector& vector) const;
51
+ bool checkDimLeft(const Matrix& matrix) const;
52
+
53
+ // functions for matrix computation
54
+ void Multiply(Vector& result,const Vector& vect) const;
55
+ void Multiply(Matrix& result,const Matrix& matrix) const;
56
+
57
+ void transpose(Matrix& result) const;
58
+ void fromVector(const Vector& vect);
59
+ double norm2() const;
60
+
61
+ // operators
62
+ Matrix& operator=(const Matrix& matrix);
63
+
64
+ Matrix& operator+=(double val);
65
+ Matrix& operator-=(double val);
66
+ Matrix& operator*=(double val);
67
+ Matrix& operator/=(double val);
68
+
69
+ Matrix& operator+=(const Matrix& matrix);
70
+ Matrix& operator-=(const Matrix& matrix);
71
+ Matrix& operator*=(const Matrix& matrix);
72
+ Matrix& operator/=(const Matrix& matrix);
73
+
74
+ friend Vector operator*(const Matrix& matrix,const Vector& vect);
75
+ friend Matrix operator*(const Matrix& matrix1,const Matrix& matrix2);
76
+
77
+
78
+ // solve linear systems
79
+ void SolveLinearSystem(Vector& result,const Vector& b) const;
80
+ void ConjugateGradient(Vector& result,const Vector& b) const;
81
+
82
+ #ifdef _QT
83
+ bool writeMatrix(QFile& file) const;
84
+ bool readMatrix(QFile& file);
85
+ #endif
86
+ #ifdef _MATLAB
87
+ void readMatrix(const mxArray* prhs);
88
+ void writeMatrix(mxArray*& prhs) const;
89
+ #endif
90
+ };
91
+
92
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/Vector.cpp ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "Vector.h"
2
+ #include "memory.h"
3
+ #include <iostream>
4
+
5
+ using namespace std;
6
+
7
+ Vector::Vector(void)
8
+ {
9
+ nDim=0;
10
+ pData=NULL;
11
+ }
12
+
13
+ Vector::Vector(int ndim, double *data)
14
+ {
15
+ nDim=ndim;
16
+ pData=new double[nDim];
17
+ if(data!=NULL)
18
+ memcpy(pData,data,sizeof(double)*nDim);
19
+ else
20
+ memset(pData,0,sizeof(double)*nDim);
21
+ }
22
+
23
+ Vector::Vector(const Vector& vect)
24
+ {
25
+ nDim=0;
26
+ pData=NULL;
27
+ copyData(vect);
28
+ }
29
+
30
+ Vector::~Vector(void)
31
+ {
32
+ releaseData();
33
+ }
34
+
35
+ void Vector::releaseData()
36
+ {
37
+ if(pData!=NULL)
38
+ delete pData;
39
+ pData=NULL;
40
+ nDim=0;
41
+ }
42
+
43
+ void Vector::allocate(int ndim)
44
+ {
45
+ releaseData();
46
+ nDim=ndim;
47
+ if(nDim>0)
48
+ pData=new double[nDim];
49
+ }
50
+
51
+ void Vector::copyData(const Vector &vect)
52
+ {
53
+ if(nDim!=vect.nDim)
54
+ {
55
+ releaseData();
56
+ nDim=vect.nDim;
57
+ pData=new double[nDim];
58
+ }
59
+ memcpy(pData,vect.pData,sizeof(double)*nDim);
60
+ }
61
+
62
+ void Vector::dimcheck(const Vector &vect) const
63
+ {
64
+ if(nDim!=vect.nDim)
65
+ cout<<"The dimensions of the vectors don't match!"<<endl;
66
+ }
67
+
68
+ void Vector::reset()
69
+ {
70
+ if(pData!=NULL)
71
+ memset(pData,0,sizeof(double)*nDim);
72
+ }
73
+
74
+ double Vector::sum() const
75
+ {
76
+ double total = 0;
77
+ for(int i=0;i<nDim;i++)
78
+ total += pData[i];
79
+ return total;
80
+ }
81
+
82
+ double Vector::norm2() const
83
+ {
84
+ double temp=0;
85
+ for(int i=0;i<nDim;i++)
86
+ temp+=pData[i]*pData[i];
87
+ return temp;
88
+ }
89
+
90
+ void Vector::printVector()
91
+ {
92
+ for(int i=0;i<nDim;i++)
93
+ printf("%.6f ",pData[i]);
94
+ printf("\n");
95
+ }
96
+
97
+ //----------------------------------------------------------------------------------
98
+ // operators
99
+ //----------------------------------------------------------------------------------
100
+ Vector& Vector::operator =(const Vector &vect)
101
+ {
102
+ copyData(vect);
103
+ return *this;
104
+ }
105
+
106
+ Vector& Vector::operator +=(const Vector &vect)
107
+ {
108
+ dimcheck(vect);
109
+ for(int i=0;i<nDim;i++)
110
+ pData[i]+=vect.data()[i];
111
+ return *this;
112
+ }
113
+
114
+ Vector& Vector::operator *=(const Vector &vect)
115
+ {
116
+ dimcheck(vect);
117
+ for(int i=0;i<nDim;i++)
118
+ pData[i]*=vect.data()[i];
119
+ return *this;
120
+ }
121
+
122
+ Vector& Vector::operator -=(const Vector &vect)
123
+ {
124
+ dimcheck(vect);
125
+ for(int i=0;i<nDim;i++)
126
+ pData[i]-=vect.data()[i];
127
+ return *this;
128
+ }
129
+
130
+ Vector& Vector::operator /=(const Vector &vect)
131
+ {
132
+ dimcheck(vect);
133
+ for(int i=0;i<nDim;i++)
134
+ pData[i]/=vect.data()[i];
135
+ return *this;
136
+ }
137
+
138
+ Vector& Vector::operator +=(double val)
139
+ {
140
+ for(int i=0;i<nDim;i++)
141
+ pData[i]+=val;
142
+ return *this;
143
+ }
144
+
145
+ Vector& Vector::operator *=(double val)
146
+ {
147
+ for(int i=0;i<nDim;i++)
148
+ pData[i]*=val;
149
+ return *this;
150
+ }
151
+
152
+ Vector& Vector::operator -=(double val)
153
+ {
154
+ for(int i=0;i<nDim;i++)
155
+ pData[i]-=val;
156
+ return *this;
157
+ }
158
+
159
+ Vector& Vector::operator /=(double val)
160
+ {
161
+ for(int i=0;i<nDim;i++)
162
+ pData[i]/=val;
163
+ return *this;
164
+ }
165
+
166
+ const Vector operator+(const Vector& vect1,const Vector& vect2)
167
+ {
168
+ vect1.dimcheck(vect2);
169
+ Vector result(vect1);
170
+ result+=vect2;
171
+ return result;
172
+ }
173
+
174
+ const Vector operator-(const Vector& vect1,const Vector& vect2)
175
+ {
176
+ vect1.dimcheck(vect2);
177
+ Vector result(vect1);
178
+ result-=vect2;
179
+ return result;
180
+ }
181
+
182
+ const Vector operator*(const Vector& vect1,const Vector& vect2)
183
+ {
184
+ vect1.dimcheck(vect2);
185
+ Vector result(vect1);
186
+ result*=vect2;
187
+ return result;
188
+ }
189
+
190
+ const Vector operator/(const Vector& vect1,const Vector& vect2)
191
+ {
192
+ vect1.dimcheck(vect2);
193
+ Vector result(vect1);
194
+ result/=vect2;
195
+ return result;
196
+ }
197
+
198
+ const Vector operator+(const Vector& vect,double val)
199
+ {
200
+ Vector result(vect);
201
+ result+=val;
202
+ return result;
203
+ }
204
+
205
+ const Vector operator-(const Vector& vect,double val)
206
+ {
207
+ Vector result(vect);
208
+ result-=val;
209
+ return result;
210
+ }
211
+
212
+ const Vector operator*(const Vector& vect,double val)
213
+ {
214
+ Vector result(vect);
215
+ result*=val;
216
+ return result;
217
+ }
218
+
219
+ const Vector operator/(const Vector& vect,double val)
220
+ {
221
+ Vector result(vect);
222
+ result/=val;
223
+ return result;
224
+ }
225
+
226
+ double innerproduct(const Vector& vect1,const Vector& vect2)
227
+ {
228
+ vect1.dimcheck(vect2);
229
+ double result=0;
230
+ for(int i=0;i<vect1.nDim;i++)
231
+ result+=vect1.pData[i]*vect2.pData[i];
232
+ return result;
233
+ }
234
+
235
+ #ifdef _QT
236
+
237
+ bool Vector::writeVector(QFile& file) const
238
+ {
239
+ file.write((char *)&nDim,sizeof(int));
240
+ if(file.write((char *)pData,sizeof(double)*nDim)!=sizeof(double)*nDim)
241
+ return false;
242
+ return true;
243
+ }
244
+
245
+ bool Vector::readVector(QFile &file)
246
+ {
247
+ releaseData();
248
+ file.read((char *)&nDim,sizeof(int));
249
+ if(nDim<0)
250
+ return false;
251
+ if(nDim>0)
252
+ {
253
+ allocate(nDim);
254
+ if(file.read((char *)pData,sizeof(double)*nDim)!=sizeof(double)*nDim)
255
+ return false;
256
+ }
257
+ return true;
258
+ }
259
+
260
+ #endif
261
+
262
+ #ifdef _MATLAB
263
+
264
+ void Vector::readVector(const mxArray* prhs)
265
+ {
266
+ if(pData!=NULL)
267
+ delete pData;
268
+ int nElements = mxGetNumberOfDimensions(prhs);
269
+ if(nElements>2)
270
+ mexErrMsgTxt("A vector is expected to be loaded!");
271
+ const mwSize* dims = mxGetDimensions(prhs);
272
+ nDim = dims[0]*dims[1];
273
+ pData = new double[nDim];
274
+ memcpy(pData,(double*)mxGetData(prhs),sizeof(double)*nDim);
275
+ }
276
+
277
+ void Vector::writeVector(mxArray*& plhs) const
278
+ {
279
+ mwSize dims[2];
280
+ dims[0]=nDim;dims[1]=1;
281
+ plhs=mxCreateNumericArray(2, dims,mxDOUBLE_CLASS, mxREAL);
282
+ memcpy((double *)mxGetData(plhs),pData,sizeof(double)*nDim);
283
+ }
284
+
285
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/Vector.h ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef _Vector_h
2
+ #define _Vector_h
3
+
4
+ #include "stdio.h"
5
+ #include "project.h"
6
+ #ifdef _QT
7
+ #include <QFile>
8
+ #endif
9
+
10
+ class Vector
11
+ {
12
+ private:
13
+ int nDim;
14
+ double* pData;
15
+ public:
16
+ Vector(void);
17
+ Vector(int ndim,double *data=NULL);
18
+ Vector(const Vector& vect);
19
+ ~Vector(void);
20
+ void releaseData();
21
+ void allocate(int ndim);
22
+ void allocate(const Vector& vect){allocate(vect.nDim);};
23
+ void copyData(const Vector& vect);
24
+ void dimcheck(const Vector& vect) const;
25
+ void reset();
26
+ double norm2() const;
27
+ double sum() const;
28
+ void printVector();
29
+
30
+ // access the members
31
+ const double* data() const{return (const double*)pData;};
32
+ double* data() {return pData;};
33
+ int dim() const {return nDim;};
34
+ inline bool matchDimension(int _ndim) const {if(nDim==_ndim) return true;else return false;};
35
+ inline bool matchDimension(const Vector& vect) const {return matchDimension(vect.nDim);};
36
+
37
+ // operators
38
+ inline double operator[](int index) const {return pData[index];};
39
+ inline double& operator[](int index){return *(pData+index);};
40
+ Vector& operator=(const Vector& vect);
41
+
42
+ Vector& operator+=(const Vector& vect);
43
+ Vector& operator*=(const Vector& vect);
44
+ Vector& operator-=(const Vector& vect);
45
+ Vector& operator/=(const Vector& vect);
46
+
47
+ Vector& operator+=(double val);
48
+ Vector& operator*=(double val);
49
+ Vector& operator-=(double val);
50
+ Vector& operator/=(double val);
51
+
52
+ friend const Vector operator+(const Vector& vect1,const Vector& vect2);
53
+ friend const Vector operator*(const Vector& vect1,const Vector& vect2);
54
+ friend const Vector operator-(const Vector& vect1,const Vector& vect2);
55
+ friend const Vector operator/(const Vector& vect1,const Vector& vect2);
56
+
57
+ friend const Vector operator+(const Vector& vect1,double val);
58
+ friend const Vector operator*(const Vector& vect1,double val);
59
+ friend const Vector operator-(const Vector& vect1,double val);
60
+ friend const Vector operator/(const Vector& vect1,double val);
61
+
62
+ friend double innerproduct(const Vector& vect1,const Vector& vect2);
63
+ #ifdef _QT
64
+ bool writeVector(QFile& file) const;
65
+ bool readVector(QFile& file);
66
+ #endif
67
+ #ifdef _MATLAB
68
+ void readVector(const mxArray* prhs);
69
+ void writeVector(mxArray*& prhs) const;
70
+ #endif
71
+ };
72
+
73
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/dir.cpp ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "dir.h"
2
+
3
+ //------------------------------------------------------------------------------------
4
+ // function to load all sub folders for a given directory
5
+ //------------------------------------------------------------------------------------
6
+ vector<string> dir::getSubfolders(LPCSTR path)
7
+ {
8
+ // make sure that the path has an ok format
9
+ string Path(path);
10
+ if(Path[Path.size()-1]!='*')
11
+ {
12
+ if(Path[Path.size()-1]!='\\')
13
+ Path.push_back('\\');
14
+ Path.push_back('*');
15
+ }
16
+ vector<string> subfolders;
17
+ WIN32_FIND_DATA FindFileData;
18
+ HANDLE hFind;
19
+
20
+ hFind = FindFirstFile(Path.data(), &FindFileData);
21
+ if (hFind == INVALID_HANDLE_VALUE)
22
+ {
23
+ printf ("FindFirstFile failed (%d)\n", GetLastError());
24
+ return subfolders;
25
+ }
26
+ bool IsFound;
27
+ do{
28
+ if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)== FILE_ATTRIBUTE_DIRECTORY &&
29
+ (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) != FILE_ATTRIBUTE_SYSTEM)
30
+ {
31
+ if(strcmp(FindFileData.cFileName,".") != 0 && strcmp(FindFileData.cFileName,"..") != 0)
32
+ {
33
+ //wcout<<FindFileData.dwFileAttributes << "\t" << FindFileData.cFileName <<endl;
34
+ subfolders.push_back(string(FindFileData.cFileName));
35
+ }
36
+ }
37
+
38
+ IsFound = FindNextFile(hFind,&FindFileData);
39
+ }while(IsFound);
40
+ FindClose(hFind);
41
+ return subfolders;
42
+ }
43
+
44
+ //------------------------------------------------------------------------------------
45
+ // function to load all sub folders for a given directory
46
+ //------------------------------------------------------------------------------------
47
+ vector<string> dir::readFiles(LPCSTR path)
48
+ {
49
+ vector<string> subfolders;
50
+ WIN32_FIND_DATA FindFileData;
51
+ HANDLE hFind;
52
+
53
+ hFind = FindFirstFile(path, &FindFileData);
54
+ if (hFind == INVALID_HANDLE_VALUE)
55
+ {
56
+ //printf ("FindFirstFile failed (%d)\n", GetLastError());
57
+ return subfolders;
58
+ }
59
+ bool IsFound;
60
+ do{
61
+ subfolders.push_back(string(FindFileData.cFileName));
62
+ //wcout<<FindFileData.dwFileAttributes << "\t" << FindFileData.cFileName <<endl;
63
+ IsFound = FindNextFile(hFind,&FindFileData);
64
+ }while(IsFound);
65
+ FindClose(hFind);
66
+ return subfolders;
67
+ }
68
+
69
+ //------------------------------------------------------------------------------------
70
+ // function to load all images in a given folder
71
+ //------------------------------------------------------------------------------------
72
+ vector<string> dir::readImages(LPCSTR path)
73
+ {
74
+ string Path(path);
75
+ if(Path[Path.size()-1]!='\\')
76
+ Path.push_back('\\');
77
+
78
+ vector<string> filelist;
79
+ LPCSTR imgformats[4]={"*.jpg","*.jpeg","*.bmp","*.png"};//,L"*.gif"};
80
+ for(int i=0;i<4;i++)
81
+ {
82
+ vector<string> templist;
83
+ string search(Path);
84
+ search+= imgformats[i];
85
+ //wcout<<search.data() <<endl;
86
+ templist = readFiles(search.data());
87
+
88
+ for(int j = 0;j<templist.size(); j++)
89
+ filelist.push_back(templist[j]);
90
+ }
91
+ return filelist;
92
+ }
93
+
94
+ //------------------------------------------------------------------------------------
95
+ // function to convert wstring to string
96
+ //------------------------------------------------------------------------------------
97
+ string dir::wstring2string(const wstring& wstr)
98
+ {
99
+ string s(wstr.begin(),wstr.end());
100
+ s.assign(wstr.begin(),wstr.end());
101
+ return s;
102
+ }
103
+
104
+ wstring dir::string2wstring(const string& str)
105
+ {
106
+ wstring ws(str.begin(),str.end());
107
+ ws.assign(str.begin(),str.end());
108
+ return ws;
109
+ }
110
+
111
+ //------------------------------------------------------------------------------------
112
+ // function to change file extension
113
+ //------------------------------------------------------------------------------------
114
+ string dir::changeFileExt(const string& path,const string& ext)
115
+ {
116
+ string newpath;
117
+ int dot = path.find_last_of('.');
118
+ newpath = path.substr(0,dot+1);
119
+ newpath+=ext;
120
+ return newpath;
121
+ }
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/dir.h ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include "stdlib.h"
3
+ #include <windows.h>
4
+ #include <tchar.h>
5
+ #include <stdio.h>
6
+ #include <iostream>
7
+ #include <vector>
8
+ #include <string>
9
+
10
+
11
+ using namespace std;
12
+
13
+ namespace dir
14
+ {
15
+ vector<string> getSubfolders( LPCSTR path);
16
+ vector<string> readFiles( LPCSTR path);
17
+
18
+ vector<string> readImages(LPCSTR path);
19
+
20
+ wstring string2wstring(const string& str);
21
+ string wstring2string(const wstring& wstr);
22
+
23
+ string changeFileExt(const string& path,const string& ext);
24
+ };
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/mexDenseSIFT.cpp ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "mex.h"
2
+ #include "Image.h"
3
+ #include "ImageFeature.h"
4
+ #include "Vector.h"
5
+ #include <vector>
6
+
7
+ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
8
+ {
9
+ DImage im;
10
+ im.LoadMatlabImage(prhs[0]);
11
+
12
+ bool IsMultiScale = false;
13
+ vector<int> cellSizeVect;
14
+ int cellSize = 3;
15
+ int stepSize = 1;
16
+ bool IsBoundaryIncluded = true;
17
+
18
+ Vector para;
19
+ if(nrhs>1) // if cell size is inputed
20
+ {
21
+ para.readVector(prhs[1]);
22
+ if(para.dim()>1)
23
+ {
24
+ IsMultiScale = true;
25
+ for(int i = 0;i<para.dim();i++)
26
+ cellSizeVect.push_back(para[i]);
27
+ }
28
+ else
29
+ cellSize = para[0];
30
+ }
31
+ if(nrhs>2)
32
+ {
33
+ para.readVector(prhs[2]);
34
+ stepSize = para[0];
35
+ }
36
+ if(nrhs>3)
37
+ {
38
+ para.readVector(prhs[3]);
39
+ IsBoundaryIncluded = para[0]>0;
40
+ }
41
+ UCImage imsift;
42
+ if(IsMultiScale)
43
+ ImageFeature::imSIFT(im,imsift,cellSizeVect,stepSize,IsBoundaryIncluded);
44
+ else
45
+ ImageFeature::imSIFT(im,imsift,cellSize,stepSize,IsBoundaryIncluded);
46
+ imsift.OutputToMatlab(plhs[0]);
47
+ }
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/mexDenseSIFT.m ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ % The wrapper of mex function mexDenseSIFT.m. See demo_mexDenseSIFT.m for an example of usage.
2
+ %
3
+ % sift = mexDenseSIFT(im,cellSize,stepSize,IsBoundary);
4
+ %
5
+ % Input arguments
6
+ % im -- an RGB or grayscale image (either uint8 or double)
7
+ % cellSize -- (default: 3) a vector of cell size. If a scale is input, then the SIFT descriptor of one cell size is
8
+ % computed; if a vector is input, then multi-scale SIFT is computed and concatenated.
9
+ % stepSize -- (default: 1) a scale of step size in sampling image grid. If an integer larger than 1 is input, then
10
+ % sparse sampling of image grid is performed
11
+ % IsBoundary-- (default: true) a boolean variable indicating whether boundary is included.
12
+ %
13
+ % Output
14
+ % sift -- an image (with multiple channels, typicallly 128) of datatype UINT8 despite the type of the input.
15
+ % The maximum element wise value of sift is 255. This datatype is consistent with the byte-based
16
+ % SIFT flow algorithm
17
+ %
18
+ % Ce Liu
19
+ % June 29, 2010
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/mexDenseSIFT.mexa64 ADDED
Binary file (64.7 kB). View file
 
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/mexDenseSIFT.mexmaci64 ADDED
Binary file (62.4 kB). View file
 
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/mexDenseSIFT.mexw64 ADDED
Binary file (46.1 kB). View file
 
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/project.h ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include "stdio.h"
3
+
4
+ // if the files are compiled in linux or mac os then uncomment the following line, otherwise comment it if you compile using visual studio in windows
5
+ #define _LINUX_MAC
6
+ #define _OPENCV
7
+
8
+ template <class T>
9
+ void _Release1DBuffer(T* pBuffer)
10
+ {
11
+ if(pBuffer!=NULL)
12
+ delete []pBuffer;
13
+ pBuffer=NULL;
14
+ }
15
+
16
+ template <class T>
17
+ void _Rlease2DBuffer(T** pBuffer,size_t nElements)
18
+ {
19
+ for(size_t i=0;i<nElements;i++)
20
+ delete [](pBuffer[i]);
21
+ delete []pBuffer;
22
+ pBuffer=NULL;
23
+ }
24
+
25
+
26
+ #define _MATLAB
27
+
28
+ #ifdef _MATLAB
29
+ #include "mex.h"
30
+ #endif
31
+
32
+
33
+ #ifdef _LINUX_MAC
34
+
35
+ template <class T1,class T2>
36
+ T1 __min(T1 a, T2 b)
37
+ {
38
+ return (a>b)?b:a;
39
+ }
40
+
41
+ template <class T1,class T2>
42
+ T1 __max(T1 a, T2 b)
43
+ {
44
+ return (a<b)?b:a;
45
+ }
46
+
47
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/readme.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The *.cpp and *.h files in this folder are used to mex a matlab dll file for computing dense SIFT features. Use the following command to compile in Matlab (tested on version 7.6 or later)
2
+
3
+ mex mexDenseSIFT.cpp Matrix.cpp Vector.cpp
4
+
5
+ It has been tested in Windows 7 x64, Linux x64 and Mac OS 10.6. Precompiled versions of Windows 7 x64 and Mac OS 10.6 are included in the folder.
6
+
7
+
8
+ ------------------------- Important -------------------------
9
+
10
+ You must change one line in order to compile correctly. On line 5 of project.h, you should comment this line if you are compiling using visual studio in windows, or uncomment if you are in linux or mac os.
11
+
12
+ -------------------------------------------------------------
UVDoc_official/eval/eval_code/SIFTflow/mexDenseSIFT/showColorSIFT.m ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function SIFTcolor=showColorSIFT(SIFT)
2
+ %
3
+ % It reduces the dimensionality of SIFT to 3 dimensions and outputs a color
4
+ % coded image
5
+ %
6
+ % It will map the first PCA dimension to luminance (R+G+B), then it will
7
+ % map the second to R-G and the third one to (R+G)/2-B
8
+
9
+ load ('pcSIFT', 'pcSIFT')
10
+
11
+ [nrows ncols nfeatures] = size(SIFT);
12
+ SIFTpca = pcSIFT(:,1:3)'*double(reshape(SIFT, [nrows*ncols nfeatures]))';
13
+
14
+ A = inv([1 1 1; 1 -1 0; .5 .5 -1]);
15
+ %A = eye(3,3);
16
+
17
+ SIFTcolor = A * SIFTpca(1:3,:);
18
+ SIFTcolor = reshape(SIFTcolor', [nrows ncols 3]);
19
+ SIFTcolor = SIFTcolor - min(SIFTcolor(:));
20
+ SIFTcolor = SIFTcolor / max(SIFTcolor(:));
21
+ %SIFTcolor = uint8(255*SIFTcolor / max(SIFTcolor(:)));
22
+ %imshow(SIFTcolor)
23
+
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/BPFlow.cpp ADDED
@@ -0,0 +1,1084 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "stdio.h"
2
+ #include "project.h"
3
+ #include "BPFlow.h"
4
+ #include "memory.h"
5
+ #include "math.h"
6
+ #include "stdlib.h"
7
+ #include "Stochastic.h"
8
+
9
+ BPFlow::BPFlow(void)
10
+ {
11
+ #ifdef _MATLAB
12
+ IsDisplay=false;
13
+ #else
14
+ IsDisplay=true;
15
+ #endif
16
+ IsDataTermTruncated=false;
17
+ IsTRW=false;
18
+ CTRW=(double)1/2;
19
+ //CTRW=0.55;
20
+ Width=Height=Area=0;
21
+ pIm1=pIm2=NULL;
22
+ for(int i=0;i<2;i++)
23
+ {
24
+ pOffset[i]=NULL;
25
+ pWinSize[i]=NULL;
26
+ }
27
+ pDataTerm=NULL;
28
+ ptrDataTerm=NULL;
29
+ for(int i=0;i<2;i++)
30
+ {
31
+ pRangeTerm[i]=pSpatialMessage[i]=pDualMessage[i]=pBelief[i]=NULL;
32
+ ptrRangeTerm[i]=ptrSpatialMessage[i]=ptrDualMessage[i]=ptrBelief[i]=NULL;
33
+ }
34
+ pX=NULL;
35
+ nNeighbors=4;
36
+ }
37
+
38
+ BPFlow::~BPFlow(void)
39
+ {
40
+ ReleaseBuffer();
41
+ }
42
+
43
+ void BPFlow::ReleaseBuffer()
44
+ {
45
+ _Release1DBuffer(pIm1);
46
+ _Release1DBuffer(pIm2);
47
+
48
+ for(int i=0;i<2;i++)
49
+ {
50
+ _Release1DBuffer(pOffset[i]); // release the buffer of the offset
51
+ _Release1DBuffer(pWinSize[i]); // release the buffer of the size
52
+ }
53
+
54
+ _Release1DBuffer(pDataTerm);
55
+ _Release1DBuffer(ptrDataTerm);
56
+ for(int i=0;i<2;i++)
57
+ {
58
+ _Release1DBuffer(pRangeTerm[i]);
59
+ _Release1DBuffer(ptrRangeTerm[i]);
60
+ _Release1DBuffer(pSpatialMessage[i]);
61
+ _Release1DBuffer(ptrSpatialMessage[i]);
62
+ _Release1DBuffer(pDualMessage[i]);
63
+ _Release1DBuffer(ptrDualMessage[i]);
64
+ _Release1DBuffer(pBelief[i]);
65
+ _Release1DBuffer(ptrBelief[i]);
66
+ }
67
+ _Release1DBuffer(pX);
68
+ }
69
+
70
+ //---------------------------------------------------------------------------------
71
+ // set the parameter of the model
72
+ // the regularization is a truncated L1 norm: __min(s|v(x,y)-v(x+1,y)|,d)
73
+ // sigma is used to penalize large displacement
74
+ //---------------------------------------------------------------------------------
75
+ void BPFlow::setPara(double _s,double _d)
76
+ {
77
+ s=_s;
78
+ d=_d;
79
+ //printf("s: %f, d: %f\n",s,d);
80
+ if(Width>0)
81
+ {
82
+ Im_s.allocate(Width,Height,2);
83
+ Im_d.allocate(Width,Height,2);
84
+ Im_s.setValue(s);
85
+ Im_d.setValue(d);
86
+ }
87
+ else
88
+ printf("The image dimension has not been specified! Call LoadImages() first\n");
89
+ }
90
+
91
+ //----------------------------------------------------------------------
92
+ // function to load images
93
+ //----------------------------------------------------------------------
94
+ void BPFlow::LoadImages(int _width, int _height, int _nchannels, const T_input *pImage1, const T_input *pImage2)
95
+ {
96
+ Width=_width;
97
+ Height=_height;
98
+ Area=Width*Height;
99
+ nChannels=_nchannels;
100
+
101
+ _Release1DBuffer(pIm1);
102
+ _Release1DBuffer(pIm2);
103
+ pIm1=new T_input[Width*Height*nChannels];
104
+ pIm2=new T_input[Width*Height*nChannels];
105
+
106
+ memcpy(pIm1,pImage1,sizeof(T_input)*Width*Height*nChannels);
107
+ memcpy(pIm2,pImage2,sizeof(T_input)*Width*Height*nChannels);
108
+
109
+ Width2=Width;
110
+ Height2=Height;
111
+ }
112
+
113
+
114
+ void BPFlow::LoadImages(int _width, int _height, int _nchannels, const T_input *pImage1,
115
+ int _width2,int _height2, const T_input *pImage2)
116
+ {
117
+ Width=_width;
118
+ Height=_height;
119
+ Area=Width*Height;
120
+ nChannels=_nchannels;
121
+ Width2=_width2;
122
+ Height2=_height2;
123
+
124
+ _Release1DBuffer(pIm1);
125
+ _Release1DBuffer(pIm2);
126
+ pIm1=new T_input[Width*Height*nChannels];
127
+ pIm2=new T_input[Width2*Height2*nChannels];
128
+
129
+ memcpy(pIm1,pImage1,sizeof(T_input)*Width*Height*nChannels);
130
+ memcpy(pIm2,pImage2,sizeof(T_input)*Width2*Height2*nChannels);
131
+ }
132
+
133
+ //------------------------------------------------------------------------------------------------
134
+ // function to set the homogeneous MRF parameters
135
+ // There is no offset, and the window size is identical for each pixel (winSize)
136
+ //------------------------------------------------------------------------------------------------
137
+ void BPFlow::setHomogeneousMRF(int winSize)
138
+ {
139
+ for(int i=0;i<2;i++)
140
+ {
141
+ _Release1DBuffer(pOffset[i]); // release the buffer of the offset
142
+ _Release1DBuffer(pWinSize[i]); // release the buffer of the size
143
+ pOffset[i]=new T_state[Area];
144
+ memset(pOffset[i],0,sizeof(T_state)*Area);
145
+
146
+ pWinSize[i]=new T_state[Area];
147
+ for(size_t j=0;j<Area;j++)
148
+ pWinSize[i][j]=winSize;//+CStochastic::UniformSampling(3)-1;
149
+ }
150
+ // add some disturbance
151
+ for(int i=0;i<2;i++)
152
+ for(int j=0;j<Area;j++)
153
+ pOffset[i][j]=CStochastic::UniformSampling(5)-2;
154
+ }
155
+
156
+
157
+ //------------------------------------------------------------------------------------------------
158
+ // function to verify whether a poit is inside image boundary or not
159
+ //------------------------------------------------------------------------------------------------
160
+ template <class T>
161
+ bool BPFlow::InsideImage(T x,T y)
162
+ {
163
+ if(x>=0 && x<Width2 && y>=0 && y<Height2)
164
+ return true;
165
+ else
166
+ return false;
167
+ }
168
+
169
+ //------------------------------------------------------------------------------------------------
170
+ // function to compute range term
171
+ //------------------------------------------------------------------------------------------------
172
+ void BPFlow::ComputeRangeTerm(double _gamma)
173
+ {
174
+ gamma=_gamma;
175
+ for(int i=0;i<2;i++)
176
+ {
177
+ _Release1DBuffer(pRangeTerm[i]);
178
+ _Release1DBuffer(ptrRangeTerm[i]);
179
+ AllocateBuffer(pRangeTerm[i],1,ptrRangeTerm[i],pWinSize[i]);
180
+ }
181
+ for(ptrdiff_t offset=0;offset<Area;offset++)
182
+ {
183
+ for(ptrdiff_t plane=0;plane<2;plane++)
184
+ {
185
+ int winsize=pWinSize[plane][offset];
186
+ for(ptrdiff_t j=-winsize;j<=winsize;j++)
187
+ pRangeTerm[plane][offset].data()[j+winsize]=gamma*fabs((double)j+pOffset[plane][offset]);
188
+ }
189
+ }
190
+ }
191
+
192
+ //------------------------------------------------------------------------------------------------
193
+ // function to compute data term
194
+ //------------------------------------------------------------------------------------------------
195
+ void BPFlow::ComputeDataTerm()
196
+ {
197
+ // allocate the buffer for data term
198
+ nTotalMatches=AllocateBuffer<PixelBuffer2D<T_message>,T_message>(pDataTerm,ptrDataTerm,pWinSize[0],pWinSize[1]);
199
+
200
+ T_message HistMin,HistMax;
201
+ double HistInterval;
202
+ double* pHistogramBuffer;
203
+ int nBins=20000;
204
+ int total=0; // total is the total number of plausible matches, used to normalize the histogram
205
+ pHistogramBuffer=new double[nBins];
206
+ memset(pHistogramBuffer,0,sizeof(double)*nBins);
207
+ HistMin= 32767;
208
+ HistMax=0;
209
+ //--------------------------------------------------------------------------------------------------
210
+ // step 1. the first sweep to compute the data term for the visible matches
211
+ //--------------------------------------------------------------------------------------------------
212
+ for(ptrdiff_t i=0;i<Height;i++) // index over y
213
+ for(ptrdiff_t j=0;j<Width;j++) // index over x
214
+ {
215
+ size_t index=i*Width+j;
216
+ int XWinLength=pWinSize[0][index]*2+1;
217
+ // loop over a local window
218
+ for(ptrdiff_t k=-pWinSize[1][index];k<=pWinSize[1][index];k++) // index over y
219
+ for(ptrdiff_t l=-pWinSize[0][index];l<=pWinSize[0][index];l++) // index over x
220
+ {
221
+ ptrdiff_t x=j+pOffset[0][index]+l;
222
+ ptrdiff_t y=i+pOffset[1][index]+k;
223
+
224
+ // if the point is outside the image boundary then continue
225
+ if(!InsideImage(x,y))
226
+ continue;
227
+ ptrdiff_t index2=y*Width2+x;
228
+ T_message foo=0;
229
+ for(int n=0;n<nChannels;n++)
230
+ foo+=abs(pIm1[index*nChannels+n]-pIm2[index2*nChannels+n]); // L1 norm
231
+ //#ifdef INTMESSAGE
232
+ // foo+=abs(pIm1[index*nChannels+n]-pIm2[index2*nChannels+n]); // L1 norm
233
+ //#else
234
+ // foo+=fabs(pIm1[index*nChannels+n]-pIm2[index2*nChannels+n]); // L1 norm
235
+ //#endif
236
+
237
+
238
+ pDataTerm[index][(k+pWinSize[1][index])*XWinLength+l+pWinSize[0][index]]=foo;
239
+ HistMin=__min(HistMin,foo);
240
+ HistMax=__max(HistMax,foo);
241
+ total++;
242
+ }
243
+ }
244
+ // compute the histogram info
245
+ HistInterval=(double)(HistMax-HistMin)/nBins;
246
+ //HistInterval/=21;
247
+
248
+ //--------------------------------------------------------------------------------------------------
249
+ // step 2. get the histogram of the matching
250
+ //--------------------------------------------------------------------------------------------------
251
+ for(ptrdiff_t i=0;i<Height;i++) // index over y
252
+ for(ptrdiff_t j=0;j<Width;j++) // index over x
253
+ {
254
+ size_t index=i*Width+j;
255
+ int XWinLength=pWinSize[0][index]*2+1;
256
+ // loop over a local window
257
+ for(ptrdiff_t k=-pWinSize[1][index];k<=pWinSize[1][index];k++) // index over y
258
+ for(ptrdiff_t l=-pWinSize[0][index];l<=pWinSize[0][index];l++) // index over x
259
+ {
260
+ ptrdiff_t x=j+pOffset[0][index]+l;
261
+ ptrdiff_t y=i+pOffset[1][index]+k;
262
+
263
+ // if the point is outside the image boundary then continue
264
+ if(!InsideImage(x,y))
265
+ continue;
266
+ int foo=__min(pDataTerm[index][(k+pWinSize[1][index])*XWinLength+l+pWinSize[0][index]]/HistInterval,nBins-1);
267
+ pHistogramBuffer[foo]++;
268
+ }
269
+ }
270
+ for(size_t i=0;i<nBins;i++) // normalize the histogram
271
+ pHistogramBuffer[i]/=total;
272
+
273
+ T_message DefaultMatchingScore;
274
+ double Prob=0;
275
+ for(size_t i=0;i<nBins;i++)
276
+ {
277
+ Prob+=pHistogramBuffer[i];
278
+ if(Prob>=0.5)//(double)Area/nTotalMatches) // find the matching score
279
+ {
280
+ DefaultMatchingScore=__max(i,1)*HistInterval+HistMin;
281
+ break;
282
+ }
283
+ }
284
+ //DefaultMatchingScore=__min(100*DefaultMatchingScore,HistMax/10);
285
+ if(IsDisplay)
286
+ #ifdef INTMESSAGE
287
+ printf("Min: %d, Default: %d, Max: %d\n",HistMin,DefaultMatchingScore,HistMax);
288
+ #else
289
+ printf("Min: %f, Default: %f, Max: %f\n",HistMin,DefaultMatchingScore,HistMax);
290
+ #endif
291
+
292
+ //DefaultMatchingScore=0.1;
293
+ //--------------------------------------------------------------------------------------------------
294
+ // step 3. assigning the default matching score to the outside matches
295
+ //--------------------------------------------------------------------------------------------------
296
+ for(ptrdiff_t i=0;i<Height;i++) // index over y
297
+ for(ptrdiff_t j=0;j<Width;j++) // index over x
298
+ {
299
+ size_t index=i*Width+j;
300
+ int XWinLength=pWinSize[0][index]*2+1;
301
+ // loop over a local window
302
+ for(ptrdiff_t k=-pWinSize[1][index];k<=pWinSize[1][index];k++) // index over y
303
+ for(ptrdiff_t l=-pWinSize[0][index];l<=pWinSize[0][index];l++) // index over x
304
+ {
305
+ ptrdiff_t x=j+pOffset[0][index]+l;
306
+ ptrdiff_t y=i+pOffset[1][index]+k;
307
+
308
+ int _ptr=(k+pWinSize[1][index])*XWinLength+l+pWinSize[0][index];
309
+ // if the point is outside the image boundary then continue
310
+ if(!InsideImage(x,y))
311
+ pDataTerm[index][_ptr]=DefaultMatchingScore;
312
+ else if (IsDataTermTruncated) // put truncaitons to the data term
313
+ pDataTerm[index][_ptr]=__min(pDataTerm[index][_ptr],DefaultMatchingScore);
314
+ }
315
+ }
316
+ delete pHistogramBuffer;
317
+ }
318
+
319
+ //------------------------------------------------------------------------------------------------
320
+ // function to allocate buffer for the messages
321
+ //------------------------------------------------------------------------------------------------
322
+ template <class T1,class T2>
323
+ size_t BPFlow::AllocateBuffer(T1*& pBuffer,size_t factor,T2*& ptrData,const int* pWinSize)
324
+ {
325
+ pBuffer=new T1[Area*factor];
326
+ size_t totalElements=0;
327
+ for(ptrdiff_t i=0;i<Area;i++)
328
+ {
329
+ totalElements+=pWinSize[i]*2+1;
330
+ for(ptrdiff_t j=0;j<factor;j++)
331
+ pBuffer[i*factor+j].allocate(pWinSize[i]*2+1);
332
+ }
333
+ totalElements*=factor;
334
+ ptrData=new T2[totalElements];
335
+ memset(ptrData,0,sizeof(T2)*totalElements);
336
+
337
+ T2* ptrDynamic=ptrData;
338
+ size_t total=0;
339
+ for(ptrdiff_t i=0;i<Area*factor;i++)
340
+ {
341
+ pBuffer[i].data()=ptrDynamic;
342
+ ptrDynamic+=pBuffer[i].nElements();
343
+ total+=pBuffer[i].nElements();
344
+ }
345
+ return total;
346
+ }
347
+
348
+ template<class T1,class T2>
349
+ size_t BPFlow::AllocateBuffer(T1*& pBuffer,T2*& ptrData,const int* pWinSize1,const int* pWinSize2)
350
+ {
351
+ pBuffer=new T1[Area];
352
+ size_t totalElements=0;
353
+ for(ptrdiff_t i=0;i<Area;i++)
354
+ {
355
+ totalElements+=(pWinSize1[i]*2+1)*(pWinSize2[i]*2+1);
356
+ pBuffer[i].allocate(pWinSize1[i]*2+1,pWinSize2[i]*2+1);
357
+ }
358
+ ptrData=new T2[totalElements];
359
+ memset(ptrData,0,sizeof(T2)*totalElements);
360
+
361
+ T2* ptrDynamic=ptrData;
362
+ size_t total=0;
363
+ for(ptrdiff_t i=0;i<Area;i++)
364
+ {
365
+ pBuffer[i].data()=ptrDynamic;
366
+ ptrDynamic+=pBuffer[i].nElements();
367
+ total+=pBuffer[i].nElements();
368
+ }
369
+ return total;
370
+ }
371
+
372
+ void BPFlow::AllocateMessage()
373
+ {
374
+ // delete the buffers for the messages
375
+ for(int i=0;i<2;i++)
376
+ {
377
+ _Release1DBuffer(pSpatialMessage[i]);
378
+ _Release1DBuffer(ptrSpatialMessage[i]);
379
+ _Release1DBuffer(pDualMessage[i]);
380
+ _Release1DBuffer(ptrDualMessage[i]);
381
+ _Release1DBuffer(pBelief[i]);
382
+ _Release1DBuffer(ptrBelief[i]);
383
+ }
384
+ // allocate the buffers for the messages
385
+ for(int i=0;i<2;i++)
386
+ {
387
+ nTotalSpatialElements[i]=AllocateBuffer(pSpatialMessage[i],nNeighbors,ptrSpatialMessage[i],pWinSize[i]);
388
+ nTotalDualElements[i]=AllocateBuffer(pDualMessage[i],1,ptrDualMessage[i],pWinSize[i]);
389
+ nTotalBelifElements[i]=AllocateBuffer(pBelief[i],1,ptrBelief[i],pWinSize[i]);
390
+ }
391
+ }
392
+
393
+ //------------------------------------------------------------------------------------------------
394
+ // function for belief propagation
395
+ //------------------------------------------------------------------------------------------------
396
+ double BPFlow::MessagePassing(int nIterations,int nHierarchy,double* pEnergyList)
397
+ {
398
+ AllocateMessage();
399
+ if(nHierarchy>0)
400
+ {
401
+ BPFlow bp;
402
+ generateCoarserLevel(bp);
403
+ bp.MessagePassing(20,nHierarchy-1);
404
+ bp.propagateFinerLevel(*this);
405
+ }
406
+ if(pX!=NULL)
407
+ _Release1DBuffer(pX);
408
+ pX=new int[Area*2];
409
+ double energy;
410
+ for(int count=0;count<nIterations;count++)
411
+ {
412
+ //Bipartite(count);
413
+ BP_S(count);
414
+ //TRW_S(count);
415
+
416
+ //FindOptimalSolutionSequential();
417
+ ComputeBelief();
418
+ FindOptimalSolution();
419
+
420
+ energy=GetEnergy();
421
+ if(IsDisplay)
422
+ printf("No. %d energy: %f...\n",count,energy);
423
+ if(pEnergyList!=NULL)
424
+ pEnergyList[count]=energy;
425
+ }
426
+ return energy;
427
+ }
428
+
429
+ //------------------------------------------------------------------------------------------------
430
+ // bipartite message update
431
+ //------------------------------------------------------------------------------------------------
432
+ void BPFlow::Bipartite(int count)
433
+ {
434
+ // loop over vx and vy planes to update the message within each grid
435
+ for (int k=0; k<2; k++)
436
+ for (int i=0; i<Height; i++)
437
+ for (int j=0; j<Width; j++)
438
+ {
439
+ // the bipartite update
440
+ if (count%2==0 && (i+j)%2==k) // the even count
441
+ continue;
442
+ if (count%2==1 && (i+j)%2==1-k) // the odd count
443
+ continue;
444
+
445
+ //------------------------------------------------------------------------------------------------
446
+ // update the message from (j,i,k) to the neighbors on the same plane
447
+ //------------------------------------------------------------------------------------------------
448
+ // the encoding of the direction
449
+ // 0: left to right
450
+ // 1: right to left
451
+ // 2: top down
452
+ // 3: bottom up
453
+ for (int direction = 0; direction<4; direction++)
454
+ UpdateSpatialMessage(j,i,k,direction);
455
+
456
+ //-----------------------------------------------------------------------------------------------------
457
+ // update the message from (j,i,k) to the dual node (j,i,1-k)
458
+ //-----------------------------------------------------------------------------------------------------
459
+ if(count%4<2)
460
+ UpdateDualMessage(j,i,k);
461
+ }
462
+ }
463
+
464
+ void BPFlow::BP_S(int count)
465
+ {
466
+ int k=count%2;
467
+ if (count%4<2) //forward update
468
+ for(int i=0;i<Height;i++)
469
+ for(int j=0;j<Width;j++)
470
+ {
471
+ UpdateSpatialMessage(j,i,k,0);
472
+ UpdateSpatialMessage(j,i,k,2);
473
+ if(count%8<4)
474
+ UpdateDualMessage(j,i,k);
475
+ }
476
+ else // backward upate
477
+ for(int i=Height-1;i>=0;i--)
478
+ for(int j=Width-1;j>=0;j--)
479
+ {
480
+ UpdateSpatialMessage(j,i,k,1);
481
+ UpdateSpatialMessage(j,i,k,3);
482
+ if(count%8<4)
483
+ UpdateDualMessage(j,i,k);
484
+ }
485
+ }
486
+
487
+ void BPFlow::TRW_S(int count)
488
+ {
489
+ int k=count%2;
490
+ if (k==0) //forward update
491
+ for(int i=0;i<Height;i++)
492
+ for(int j=0;j<Width;j++)
493
+ {
494
+ for(int l=0;l<2;l++)
495
+ {
496
+ UpdateDualMessage(j,i,l);
497
+ UpdateSpatialMessage(j,i,l,0);
498
+ UpdateSpatialMessage(j,i,l,2);
499
+ }
500
+ }
501
+ else // backward upate
502
+ for(int i=Height-1;i>=0;i--)
503
+ for(int j=Width-1;j>=0;j--)
504
+ {
505
+ for(int l=0;l<2;l++)
506
+ {
507
+ UpdateDualMessage(j,i,l);
508
+ UpdateSpatialMessage(j,i,l,1);
509
+ UpdateSpatialMessage(j,i,l,3);
510
+ }
511
+ }
512
+ }
513
+
514
+
515
+ //------------------------------------------------------------------------------------------------
516
+ // update the message from (x0,y0,plane) to the neighbors on the same plane
517
+ // the encoding of the direction
518
+ // 2 |
519
+ // v
520
+ // 0 ------> <------- 1
521
+ // ^
522
+ // 3 |
523
+ //------------------------------------------------------------------------------------------------
524
+ void BPFlow::UpdateSpatialMessage(int x, int y, int plane, int direction)
525
+ {
526
+ // eliminate impossible messages
527
+ if (direction==0 && x==Width-1)
528
+ return;
529
+ if (direction==1 && x==0)
530
+ return;
531
+ if (direction==2 && y==Height-1)
532
+ return;
533
+ if (direction==3 && y==0)
534
+ return;
535
+
536
+ int offset=y*Width+x;
537
+ int nStates=pWinSize[plane][offset]*2+1;
538
+
539
+
540
+
541
+ T_message* message_org;
542
+ message_org=new T_message[nStates];
543
+
544
+ int x1=x,y1=y; // get the destination
545
+ switch(direction){
546
+ case 0:
547
+ x1++;
548
+ s=Im_s.data()[offset*2+plane];
549
+ d=Im_d.data()[offset*2+plane];
550
+ break;
551
+ case 1:
552
+ x1--;
553
+ s=Im_s.data()[(offset-1)*2+plane];
554
+ d=Im_d.data()[(offset-1)*2+plane];
555
+ break;
556
+ case 2:
557
+ y1++;
558
+ s=Im_s.data()[offset*2+plane];
559
+ d=Im_d.data()[offset*2+plane];
560
+ break;
561
+ case 3:
562
+ y1--;
563
+ s=Im_s.data()[(offset-Width)*2+plane];
564
+ d=Im_d.data()[(offset-Width)*2+plane];
565
+ break;
566
+ }
567
+ //s=m_s;
568
+ //d=m_d;
569
+ int offset1=y1*Width+x1;
570
+ int nStates1=pWinSize[plane][offset1]*2+1; // get the number of states for the destination node
571
+ int wsize=pWinSize[plane][offset];
572
+ int wsize1=pWinSize[plane][offset1];
573
+
574
+ T_message*& message=pSpatialMessage[plane][offset1*nNeighbors+direction].data();
575
+
576
+ // initialize the message from the dual plane
577
+ if(!IsTRW)
578
+ memcpy(message_org,pDualMessage[plane][offset].data(),sizeof(T_message)*nStates);
579
+ else
580
+ {
581
+ memset(message_org,0,sizeof(T_message)*nStates);
582
+ Add2Message(message_org,pDualMessage[plane][offset].data(),nStates,CTRW);
583
+ }
584
+
585
+ // add the range term
586
+ if(!IsTRW)
587
+ Add2Message(message_org,pRangeTerm[plane][offset].data(),nStates);
588
+ else
589
+ Add2Message(message_org,pRangeTerm[plane][offset].data(),nStates,CTRW);
590
+
591
+ // add spatial messages
592
+ if(!IsTRW)
593
+ {
594
+ if(x>0 && direction!=1) // add left to right
595
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors].data(),nStates);
596
+ if(x<Width-1 && direction!=0) // add right to left
597
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+1].data(),nStates);
598
+ if(y>0 && direction!=3) // add top down
599
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+2].data(),nStates);
600
+ if(y<Height-1 && direction!=2) // add bottom up
601
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+3].data(),nStates);
602
+ }
603
+ else
604
+ {
605
+ if(x>0) // add left to right
606
+ if(direction==1)
607
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors].data(),nStates,CTRW-1);
608
+ else
609
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors].data(),nStates,CTRW);
610
+ if(x<Width-1) // add right to left
611
+ if(direction==0)
612
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+1].data(),nStates,CTRW-1);
613
+ else
614
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+1].data(),nStates,CTRW);
615
+ if(y>0) // add top down
616
+ if(direction==3)
617
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+2].data(),nStates,CTRW-1);
618
+ else
619
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+2].data(),nStates,CTRW);
620
+ if(y<Height-1) // add bottom up
621
+ if(direction==2)
622
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+3].data(),nStates,CTRW-1);
623
+ else
624
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+3].data(),nStates,CTRW);
625
+ }
626
+ // use distance transform function to impose smoothness compatibility
627
+ T_message Min=CStochastic::Min(nStates,message_org)+d;
628
+ for(ptrdiff_t l=1;l<nStates;l++)
629
+ message_org[l]=__min(message_org[l],message_org[l-1]+s);
630
+ for(ptrdiff_t l=nStates-2;l>=0;l--)
631
+ message_org[l]=__min(message_org[l],message_org[l+1]+s);
632
+
633
+
634
+ // transform the compatibility
635
+ int shift=pOffset[plane][offset1]-pOffset[plane][offset];
636
+ if(abs(shift)>wsize+wsize1) // the shift is too big that there is no overlap
637
+ {
638
+ if(offset>0)
639
+ for(ptrdiff_t l=0;l<nStates1;l++)
640
+ message[l]=l*s;
641
+ else
642
+ for(ptrdiff_t l=0;l<nStates1;l++)
643
+ message[l]=-l*s;
644
+ }
645
+ else
646
+ {
647
+ int start=__max(-wsize,shift-wsize1);
648
+ int end=__min(wsize,shift+wsize1);
649
+ for(ptrdiff_t i=start;i<=end;i++)
650
+ message[i-shift+wsize1]=message_org[i+wsize];
651
+ if(start-shift+wsize1>0)
652
+ for(ptrdiff_t i=start-shift+wsize1-1;i>=0;i--)
653
+ message[i]=message[i+1]+s;
654
+ if(end-shift+wsize1<nStates1)
655
+ for(ptrdiff_t i=end-shift+wsize1+1;i<nStates1;i++)
656
+ message[i]=message[i-1]+s;
657
+ }
658
+
659
+ // put back the threshold
660
+ for(ptrdiff_t l=0;l<nStates1;l++)
661
+ message[l]=__min(message[l],Min);
662
+
663
+ // normalize the message by subtracting the minimum value
664
+ Min=CStochastic::Min(nStates1,message);
665
+ for(ptrdiff_t l=0;l<nStates1;l++)
666
+ message[l]-=Min;
667
+
668
+ delete message_org;
669
+ }
670
+
671
+ template<class T>
672
+ void BPFlow::Add2Message(T* message,const T* other,int nstates)
673
+ {
674
+ for(size_t i=0;i<nstates;i++)
675
+ message[i]+=other[i];
676
+ }
677
+
678
+ template<class T>
679
+ void BPFlow::Add2Message(T* message,const T* other,int nstates,double Coeff)
680
+ {
681
+ for(size_t i=0;i<nstates;i++)
682
+ message[i]+=other[i]*Coeff;
683
+ }
684
+
685
+ //------------------------------------------------------------------------------------------------
686
+ // update dual message passing from one plane to the other
687
+ //------------------------------------------------------------------------------------------------
688
+ void BPFlow::UpdateDualMessage(int x, int y, int plane)
689
+ {
690
+ int offset=y*Width+x;
691
+ int offset1=offset;
692
+ int wsize=pWinSize[plane][offset];
693
+ int nStates=wsize*2+1;
694
+ int wsize1=pWinSize[1-plane][offset];
695
+ int nStates1=wsize1*2+1;
696
+
697
+ s=Im_s.data()[offset*2+plane];
698
+ d=Im_d.data()[offset*2+plane];
699
+ //s=m_s;
700
+ //d=m_d;
701
+
702
+ T_message* message_org;
703
+ message_org=new T_message[nStates];
704
+ memset(message_org,0,sizeof(T_message)*nStates);
705
+
706
+ // add the range term
707
+ if(!IsTRW)
708
+ Add2Message(message_org,pRangeTerm[plane][offset].data(),nStates);
709
+ else
710
+ Add2Message(message_org,pRangeTerm[plane][offset].data(),nStates,CTRW);
711
+
712
+ // add spatial messages
713
+ if(x>0) //add left to right
714
+ {
715
+ if(!IsTRW)
716
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors].data(),nStates);
717
+ else
718
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors].data(),nStates,CTRW);
719
+ }
720
+ if(x<Width-1) // add right to left
721
+ {
722
+ if(!IsTRW)
723
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+1].data(),nStates);
724
+ else
725
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+1].data(),nStates,CTRW);
726
+ }
727
+ if(y>0) // add top down
728
+ {
729
+ if(!IsTRW)
730
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+2].data(),nStates);
731
+ else
732
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+2].data(),nStates,CTRW);
733
+ }
734
+ if(y<Height-1) // add bottom up
735
+ {
736
+ if(!IsTRW)
737
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+3].data(),nStates);
738
+ else
739
+ Add2Message(message_org,pSpatialMessage[plane][offset*nNeighbors+2].data(),nStates,CTRW);
740
+ }
741
+
742
+ if(IsTRW)
743
+ Add2Message(message_org,pDualMessage[plane][offset1].data(),nStates,CTRW-1);
744
+
745
+ T_message*& message=pDualMessage[1-plane][offset1].data();
746
+
747
+ T_message Min;
748
+ // use the data term
749
+ if(plane==0) // from vx plane to vy plane
750
+ for(size_t l=0;l<nStates1;l++)
751
+ message[l]=CStochastic::Min(nStates,pDataTerm[offset].data()+l*nStates,message_org);
752
+ else // from vy plane to vx plane
753
+ for(size_t l=0;l<nStates1;l++)
754
+ {
755
+ Min=message_org[0]+pDataTerm[offset].data()[l];
756
+ for(size_t h=0;h<nStates;h++)
757
+ Min=__min(Min,message_org[h]+pDataTerm[offset].data()[h*nStates1+l]);
758
+ message[l]=Min;
759
+ }
760
+
761
+ // normalize the message
762
+ Min=CStochastic::Min(nStates1,message);
763
+ for(size_t l=0;l<nStates;l++)
764
+ message[l]-=Min;
765
+
766
+ delete message_org;
767
+ }
768
+
769
+ //------------------------------------------------------------------------------------------------
770
+ // compute belief
771
+ //------------------------------------------------------------------------------------------------
772
+ void BPFlow::ComputeBelief()
773
+ {
774
+ for(size_t plane=0;plane<2;plane++)
775
+ {
776
+ memset(ptrBelief[plane],0,sizeof(T_message)*nTotalBelifElements[plane]);
777
+ for(size_t i=0;i<Height;i++)
778
+ for(size_t j=0;j<Width;j++)
779
+ {
780
+ size_t offset=i*Width+j;
781
+ T_message* belief=pBelief[plane][offset].data();
782
+ int nStates=pWinSize[plane][offset]*2+1;
783
+ // add range term
784
+ Add2Message(belief,pRangeTerm[plane][offset].data(),nStates);
785
+ // add message from the dual layer
786
+ Add2Message(belief,pDualMessage[plane][offset].data(),nStates);
787
+ if(j>0)
788
+ Add2Message(belief,pSpatialMessage[plane][offset*nNeighbors].data(),nStates);
789
+ if(j<Width-1)
790
+ Add2Message(belief,pSpatialMessage[plane][offset*nNeighbors+1].data(),nStates);
791
+ if(i>0)
792
+ Add2Message(belief,pSpatialMessage[plane][offset*nNeighbors+2].data(),nStates);
793
+ if(i<Height-1)
794
+ Add2Message(belief,pSpatialMessage[plane][offset*nNeighbors+3].data(),nStates);
795
+ }
796
+ }
797
+ }
798
+
799
+ void BPFlow::FindOptimalSolution()
800
+ {
801
+ for(size_t plane=0;plane<2;plane++)
802
+ for(size_t i=0;i<Area;i++)
803
+ {
804
+ int nStates=pWinSize[plane][i]*2+1;
805
+ double Min;
806
+ int index=0;
807
+ T_message* belief=pBelief[plane][i].data();
808
+ Min=belief[0];
809
+ for(int l=1;l<nStates;l++)
810
+ if(Min>belief[l])
811
+ {
812
+ Min=belief[l];
813
+ index=l;
814
+ }
815
+ pX[i*2+plane]=index;
816
+ }
817
+ }
818
+
819
+ //void BPFlow::FindOptimalSolutionSequential()
820
+ //{
821
+ // for(size_t plane=0;plane<2;plane++)
822
+ // memset(ptrBelief[plane],0,sizeof(T_message)*nTotalBelifElements[plane]);
823
+ //
824
+ // for(size_t i=0;i<Height;i++)
825
+ // for(size_t j=0;j<Width;j++)
826
+ // for(size_t plane=0;plane<2;plane++)
827
+ // {
828
+ // int nStates=pWinSize[plane][i]*2+1;
829
+ // size_t offset=i*Width+j;
830
+ // T_message* belief=pBelief[plane][offset].data();
831
+ //
832
+ // // add range term
833
+ // Add2Message(belief,pRangeTerm[plane][offset].data(),nStates);
834
+ // // add message from the dual layer
835
+ // Add2Message(belief,pDualMessage[plane][offset].data(),nStates);
836
+ //
837
+ // if(j>0) // horizontal energy
838
+ // for(int l=0;l<nStates;l++)
839
+ // belief[l]+=__min((double)abs(l-pWinSize[plane][offset]+pOffset[plane][offset]-pX[(offset-1)*2+plane]+pWinSize[plane][offset-1]-pOffset[plane][offset+1])*s,d);
840
+ // if(i>0) // vertical energy
841
+ // for(int l=0;l<nStates;l++)
842
+ // belief[l]+=__min((double)abs(l-pWinSize[plane][offset]+pOffset[plane][offset]-pX[(offset-Width)*2+plane]+pWinSize[plane][offset-Width]-pOffset[plane][offset-Width])*s,d);
843
+ // if(j<Width-1)
844
+ // Add2Message(belief,pSpatialMessage[plane][offset*nNeighbors+1].data(),nStates);
845
+ // if(i<Height-1)
846
+ // Add2Message(belief,pSpatialMessage[plane][offset*nNeighbors+3].data(),nStates);
847
+ //
848
+ // // find the minimum
849
+ // int index=0;
850
+ // double Min=belief[0];
851
+ // for(int l=1;l<nStates;l++)
852
+ // if(Min>belief[l])
853
+ // {
854
+ // Min=belief[l];
855
+ // index=l;
856
+ // }
857
+ // pX[offset*2+plane]=index;
858
+ // }
859
+ //}
860
+
861
+ void BPFlow::FindOptimalSolutionSequential()
862
+ {
863
+ for(size_t plane=0;plane<2;plane++)
864
+ memset(ptrBelief[plane],0,sizeof(T_message)*nTotalBelifElements[plane]);
865
+
866
+ for(size_t i=0;i<Height;i++)
867
+ for(size_t j=0;j<Width;j++)
868
+ for(size_t k=0;k<2;k++)
869
+ {
870
+ size_t plane;
871
+ if(j%2==0)
872
+ plane=k;
873
+ else
874
+ plane=1-k;
875
+
876
+ size_t offset=i*Width+j;
877
+ int nStates=pWinSize[plane][offset]*2+1;
878
+ T_message* belief=pBelief[plane][offset].data();
879
+
880
+ // add range term
881
+ Add2Message(belief,pRangeTerm[plane][offset].data(),nStates);
882
+
883
+ if (k==0)
884
+ // add message from the dual layer
885
+ Add2Message(belief,pDualMessage[plane][offset].data(),nStates);
886
+ else
887
+ for(int l=0;l<nStates;l++)
888
+ {
889
+ if(plane==0) // if the current is horizontal plane
890
+ belief[l]+=pDataTerm[offset].data()[pX[offset*2+1]*nStates+l];
891
+ else // if the current is vertical plane
892
+ {
893
+ int nStates1=pWinSize[1-plane][offset]*2+1;
894
+ belief[l]+=pDataTerm[offset].data()[l*nStates1+pX[offset*2]];
895
+ }
896
+ }
897
+
898
+ if(j>0) // horizontal energy
899
+ for(int l=0;l<nStates;l++)
900
+ belief[l]+=__min((double)abs(l-pWinSize[plane][offset]+pOffset[plane][offset]-pX[(offset-1)*2+plane]+pWinSize[plane][offset-1]-pOffset[plane][offset+1])*s,d);
901
+ if(i>0) // vertical energy
902
+ for(int l=0;l<nStates;l++)
903
+ belief[l]+=__min((double)abs(l-pWinSize[plane][offset]+pOffset[plane][offset]-pX[(offset-Width)*2+plane]+pWinSize[plane][offset-Width]-pOffset[plane][offset-Width])*s,d);
904
+ if(j<Width-1)
905
+ Add2Message(belief,pSpatialMessage[plane][offset*nNeighbors+1].data(),nStates);
906
+ if(i<Height-1)
907
+ Add2Message(belief,pSpatialMessage[plane][offset*nNeighbors+3].data(),nStates);
908
+
909
+ // find the minimum
910
+ int index=0;
911
+ double Min=belief[0];
912
+ for(int l=1;l<nStates;l++)
913
+ if(Min>belief[l])
914
+ {
915
+ Min=belief[l];
916
+ index=l;
917
+ }
918
+ pX[offset*2+plane]=index;
919
+ }
920
+ }
921
+
922
+ //------------------------------------------------------------------------------------------------
923
+ // function to get energy
924
+ //------------------------------------------------------------------------------------------------
925
+ double BPFlow::GetEnergy()
926
+ {
927
+ double energy=0;
928
+ for(size_t i=0;i<Height;i++)
929
+ for(size_t j=0;j<Width;j++)
930
+ {
931
+ size_t offset=i*Width+j;
932
+ for(size_t k=0;k<2;k++)
933
+ {
934
+ if(j<Width-1)
935
+ {
936
+ s=Im_s.data()[offset*2+k];
937
+ d=Im_d.data()[offset*2+k];
938
+ //s=m_s;
939
+ //d=m_d;
940
+ energy+=__min((double)abs(pX[offset*2+k]-pWinSize[k][offset]+pOffset[k][offset]-pX[(offset+1)*2+k]+pWinSize[k][offset+1]-pOffset[k][offset+1])*s,d);
941
+ }
942
+ if(i<Height-1)
943
+ {
944
+ s=Im_s.data()[offset*2+k];
945
+ d=Im_d.data()[offset*2+k];
946
+ //s=m_s;
947
+ //d=m_d;
948
+ energy+=__min((double)abs(pX[offset*2+k]-pWinSize[k][offset]+pOffset[k][offset]-pX[(offset+Width)*2+k]+pWinSize[k][offset+Width]-pOffset[k][offset+Width])*s,d);
949
+ }
950
+ }
951
+ int vx=pX[offset*2];
952
+ int vy=pX[offset*2+1];
953
+ int nStates=pWinSize[0][offset]*2+1;
954
+ energy+=pDataTerm[offset].data()[vy*nStates+vx];
955
+ for(size_t k=0;k<2;k++)
956
+ energy+=pRangeTerm[k][offset].data()[pX[offset*2+k]];
957
+ }
958
+ return energy;
959
+ }
960
+
961
+ void BPFlow::ComputeVelocity()
962
+ {
963
+ mFlow.allocate(Width,Height,2);
964
+ for(int i=0;i<Area;i++)
965
+ {
966
+ mFlow.data()[i*2]=pX[i*2]+pOffset[0][i]-pWinSize[0][i];
967
+ mFlow.data()[i*2+1]=pX[i*2+1]+pOffset[1][i]-pWinSize[1][i];
968
+ }
969
+ }
970
+
971
+ //------------------------------------------------------------------------------------------------
972
+ // multi-grid belie propagation
973
+ //------------------------------------------------------------------------------------------------
974
+ void BPFlow::generateCoarserLevel(BPFlow &bp)
975
+ {
976
+ //------------------------------------------------------------------------------------------------
977
+ // set the dimensions and parameters
978
+ //------------------------------------------------------------------------------------------------
979
+ bp.Width=Width/2;
980
+ if(Width%2==1)
981
+ bp.Width++;
982
+
983
+ bp.Height=Height/2;
984
+ if(Height%2==1)
985
+ bp.Height++;
986
+
987
+ bp.Area=bp.Width*bp.Height;
988
+ bp.s=s;
989
+ bp.d=d;
990
+
991
+ DImage foo;
992
+ Im_s.smoothing(foo);
993
+ foo.imresize(bp.Im_s,bp.Width,bp.Height);
994
+ Im_d.smoothing(foo);
995
+ foo.imresize(bp.Im_d,bp.Width,bp.Height);
996
+
997
+ bp.IsDisplay=IsDisplay;
998
+ bp.nNeighbors=nNeighbors;
999
+
1000
+ //------------------------------------------------------------------------------------------------
1001
+ // allocate buffers
1002
+ //------------------------------------------------------------------------------------------------
1003
+ for(int i=0;i<2;i++)
1004
+ {
1005
+ bp.pOffset[i]=new int[bp.Area];
1006
+ bp.pWinSize[i]=new int[bp.Area];
1007
+ ReduceImage(bp.pOffset[i],Width,Height,pOffset[i]);
1008
+ ReduceImage(bp.pWinSize[i],Width,Height,pWinSize[i]);
1009
+ }
1010
+ //------------------------------------------------------------------------------------------------
1011
+ // generate data term
1012
+ //------------------------------------------------------------------------------------------------
1013
+ bp.nTotalMatches=bp.AllocateBuffer(bp.pDataTerm,bp.ptrDataTerm,bp.pWinSize[0],bp.pWinSize[1]);
1014
+ for(int i=0;i<bp.Height;i++)
1015
+ for(int j=0;j<bp.Width;j++)
1016
+ {
1017
+ int offset=i*bp.Width+j;
1018
+ for(int ii=0;ii<2;ii++)
1019
+ for(int jj=0;jj<2;jj++)
1020
+ {
1021
+ int y=i*2+ii;
1022
+ int x=j*2+jj;
1023
+ if(y<Height && x<Width)
1024
+ {
1025
+ int nStates=(bp.pWinSize[0][offset]*2+1)*(bp.pWinSize[1][offset]*2+1);
1026
+ for(int k=0;k<nStates;k++)
1027
+ bp.pDataTerm[offset].data()[k]+=pDataTerm[y*Width+x].data()[k];
1028
+ }
1029
+ }
1030
+ }
1031
+ //------------------------------------------------------------------------------------------------
1032
+ // generate range term
1033
+ //------------------------------------------------------------------------------------------------
1034
+ bp.ComputeRangeTerm(gamma/2);
1035
+ }
1036
+
1037
+ void BPFlow::propagateFinerLevel(BPFlow &bp)
1038
+ {
1039
+ for(int i=0;i<bp.Height;i++)
1040
+ for(int j=0;j<bp.Width;j++)
1041
+ {
1042
+ int y=i/2;
1043
+ int x=j/2;
1044
+ int nStates1=pWinSize[0][y*Width+x]*2+1;
1045
+ int nStates2=pWinSize[1][y*Width+x]*2+1;
1046
+ for(int k=0;k<2;k++)
1047
+ {
1048
+ memcpy(bp.pDualMessage[k][i*bp.Width+j].data(),pDualMessage[k][y*Width+x].data(),sizeof(T_message)*(pWinSize[k][y*Width+x]*2+1));
1049
+ for(int l=0;l<nNeighbors;l++)
1050
+ memcpy(bp.pSpatialMessage[k][(i*bp.Width+j)*nNeighbors+l].data(),pSpatialMessage[k][(y*Width+x)*nNeighbors+l].data(),sizeof(T_message)*(pWinSize[k][y*Width+x]*2+1));
1051
+ }
1052
+ }
1053
+ }
1054
+
1055
+ template<class T>
1056
+ void BPFlow::ReduceImage(T* pDstData,int width,int height,const T *pSrcData)
1057
+ {
1058
+ int DstWidth=width/2;
1059
+ if(width%2==1)
1060
+ DstWidth++;
1061
+ int DstHeight=height/2;
1062
+ if(height%2==1)
1063
+ DstHeight++;
1064
+ memset(pDstData,0,sizeof(T)*DstWidth*DstHeight);
1065
+ int sum=0;
1066
+ for(int i=0;i<DstHeight;i++)
1067
+ for(int j=0;j<DstWidth;j++)
1068
+ {
1069
+ int offset=i*DstWidth+j;
1070
+ sum=0;
1071
+ for(int ii=0;ii<2;ii++)
1072
+ for(int jj=0;jj<2;jj++)
1073
+ {
1074
+ int x=j*2+jj;
1075
+ int y=i*2+ii;
1076
+ if(y<height && x<width)
1077
+ {
1078
+ pDstData[offset]+=pSrcData[y*width+x];
1079
+ sum++;
1080
+ }
1081
+ }
1082
+ pDstData[offset]/=sum;
1083
+ }
1084
+ }
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/BPFlow.h ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include "memory.h"
4
+ #include "Image.h"
5
+
6
+ typedef int T_state; // T_state is the type for state
7
+ typedef unsigned char T_input; // T_input is the data type of the input image
8
+ // T_message is the data type of the messages and beliefs
9
+ //typedef double T_message;
10
+ #define INTMESSAGE
11
+ #ifdef INTMESSAGE
12
+ typedef int T_message;
13
+ #else
14
+ typedef double T_message;
15
+ #endif
16
+
17
+ //-----------------------------------------------------------------------------------
18
+ // class for 1D pixel buffer
19
+ //-----------------------------------------------------------------------------------
20
+ template <class T>
21
+ class PixelBuffer1D
22
+ {
23
+ private:
24
+ short int nDim;
25
+ T* pData;
26
+ public:
27
+ PixelBuffer1D(void)
28
+ {
29
+ nDim=0;
30
+ pData=NULL;
31
+ }
32
+ PixelBuffer1D(int ndims)
33
+ {
34
+ allocate(ndims);
35
+ }
36
+ void allocate(int ndims)
37
+ {
38
+ nDim=ndims;
39
+ }
40
+ ~PixelBuffer1D()
41
+ {
42
+ nDim=0;
43
+ pData=NULL;
44
+ }
45
+ inline const T operator [](int index) const
46
+ {
47
+ return pData[index];
48
+ }
49
+ inline T& operator [](int index)
50
+ {
51
+ return pData[index];
52
+ }
53
+ T*& data(){return pData;};
54
+ const T* data() const{return pData;};
55
+ int nElements() const{return nDim;};
56
+ };
57
+
58
+ //-----------------------------------------------------------------------------------
59
+ // class for 2D pixel buffer
60
+ //-----------------------------------------------------------------------------------
61
+ template <class T>
62
+ class PixelBuffer2D
63
+ {
64
+ private:
65
+ short int nDimX,nDimY;
66
+ T* pData;
67
+ public:
68
+ PixelBuffer2D(void)
69
+ {
70
+ nDimX=nDimY=0;
71
+ pData=NULL;
72
+ }
73
+ PixelBuffer2D(int ndimx,int ndimy)
74
+ {
75
+ allocate(ndimx,ndimy);
76
+ }
77
+ void allocate(int ndimx,int ndimy)
78
+ {
79
+ nDimX=ndimx;
80
+ nDimY=ndimy;
81
+ pData=NULL;
82
+ }
83
+ ~PixelBuffer2D()
84
+ {
85
+ nDimX=nDimY=0;
86
+ pData=NULL;
87
+ }
88
+ inline const T operator [](int index) const
89
+ {
90
+ return pData[index];
91
+ }
92
+ inline T& operator [](int index)
93
+ {
94
+ return pData[index];
95
+ }
96
+ T*& data(){return pData;};
97
+ const T* data() const{return pData;};
98
+ int nElements()const{return nDimX*nDimY;};
99
+ };
100
+
101
+ //-----------------------------------------------------------------------------------
102
+ // the class for BP flow
103
+ //-----------------------------------------------------------------------------------
104
+ class BPFlow
105
+ {
106
+ private:
107
+ bool IsDisplay;
108
+ bool IsDataTermTruncated;
109
+ bool IsTRW;
110
+ double CTRW;
111
+
112
+ size_t Height,Width,Area,nChannels;
113
+ size_t Height2,Width2;
114
+
115
+ T_input *pIm1,*pIm2; // the two images for matching
116
+
117
+ int *pOffset[2]; // the predicted flow
118
+ int *pWinSize[2];// the dimension of the matching size
119
+ size_t nTotalMatches;
120
+
121
+ // the buffers for belief propagation
122
+ PixelBuffer2D<T_message>* pDataTerm; // the data term
123
+ PixelBuffer1D<T_message>* pRangeTerm[2]; // the range term
124
+ PixelBuffer1D<T_message>* pSpatialMessage[2]; // the spatial message
125
+ PixelBuffer1D<T_message>* pDualMessage[2]; // the dual message between two layers
126
+ PixelBuffer1D<T_message>* pBelief[2]; // the belief
127
+
128
+ T_message *ptrDataTerm;
129
+ T_message *ptrRangeTerm[2];
130
+ T_message* ptrSpatialMessage[2];
131
+ T_message *ptrDualMessage[2];
132
+ T_message* ptrBelief[2];
133
+
134
+ size_t nTotalSpatialElements[2];
135
+ size_t nTotalDualElements[2];
136
+ size_t nTotalBelifElements[2];
137
+
138
+ int *pX; // the final states
139
+
140
+ DImage mFlow; // the flow field
141
+
142
+ int nNeighbors;
143
+ double s,d,gamma; // the parameters of regularization
144
+ //double m_s,m_d;
145
+ DImage Im_s,Im_d; // per pixel parameterization
146
+ public:
147
+ BPFlow(void);
148
+ ~BPFlow(void);
149
+ void ReleaseBuffer();
150
+ void setPara(double _s,double _d);
151
+ void setPara(const DImage& im_s,const DImage& im_d){Im_s=im_s;Im_d=im_d;};
152
+ void setDataTermTruncation(bool isTruncated){IsDataTermTruncated=isTruncated;};
153
+ void setDisplay(bool isDisplay){IsDisplay=isDisplay;};
154
+ void setTRW(bool isTRW){IsTRW=isTRW;};
155
+ void setCTRW(double cTRW){CTRW=cTRW;};
156
+ void LoadImages(int _width,int _height,int _nchannels,const T_input* pImage1,const T_input* pImage2);
157
+ void LoadImages(int _width,int _height,int _nchannels,const T_input* pImage1,
158
+ int _width2,int _height2,const T_input* pImage2);
159
+
160
+ void setHomogeneousMRF(int winSize);
161
+
162
+ template<class T>
163
+ void LoadOffset(T* pOffsetX,T* pOffsetY);
164
+ template <class T>
165
+ void LoadWinSize(T* pWinSizeX,T* pWinSizeY);
166
+
167
+ void ComputeDataTerm();
168
+ void ComputeRangeTerm(double _gamma);
169
+ void AllocateMessage();
170
+ double MessagePassing(int nIterations,int nHierarchy,double* pEnergyList=NULL);
171
+ void Bipartite(int count);
172
+ void BP_S(int count);
173
+ void TRW_S(int count);
174
+
175
+ template<class T>
176
+ bool InsideImage(T x,T y);
177
+
178
+ template<class T1,class T2>
179
+ size_t AllocateBuffer(T1*& pBuffer,size_t factor,T2*& ptrData,const int* pWinSize);
180
+
181
+ template<class T1,class T2>
182
+ size_t AllocateBuffer(T1*& pBuffer,T2*& ptrData,const int* pWinSize1,const int* pWinSize2);
183
+
184
+ // this is the core function for message updating
185
+ void UpdateSpatialMessage(int x,int y,int plane,int direction); //T_message* message);
186
+
187
+ void UpdateDualMessage(int x,int y,int plane);
188
+
189
+ template<class T>
190
+ void Add2Message(T* message,const T* other,int nstates);
191
+
192
+ template<class T>
193
+ void Add2Message(T* message,const T* other,int nstates,double Coeff);
194
+
195
+ void ComputeBelief();
196
+
197
+ void FindOptimalSolution();
198
+ void FindOptimalSolutionSequential();
199
+
200
+ double GetEnergy();
201
+
202
+ const int* x() const{return pX;};
203
+
204
+ void ComputeVelocity();
205
+
206
+ const DImage& flow() const{return mFlow;};
207
+ DImage& flow(){return mFlow;};
208
+
209
+ //------------------------------------------------------------------------
210
+ // multi-grid belief propagation
211
+ void generateCoarserLevel(BPFlow& bp);
212
+ void propagateFinerLevel(BPFlow& bp);
213
+
214
+ template<class T>
215
+ void ReduceImage(T* pOutputData,int width,int height,const T* pInputData);
216
+ };
217
+
218
+ template<class T>
219
+ void BPFlow::LoadOffset(T* pOffsetX,T* pOffsetY)
220
+ {
221
+ for(int i=0;i<2;i++)
222
+ {
223
+ _Release1DBuffer(pOffset[i]);
224
+ pOffset[i]=new T_state[Area];
225
+ }
226
+ for(size_t j=0;j<Area;j++)
227
+ {
228
+ pOffset[0][j]=pOffsetX[j];
229
+ pOffset[1][j]=pOffsetY[j];
230
+ }
231
+ }
232
+
233
+ template<class T>
234
+ void BPFlow::LoadWinSize(T* pWinSizeX,T* pWinSizeY)
235
+ {
236
+ for(int i=0;i<2;i++)
237
+ {
238
+ _Release1DBuffer(pWinSize[i]);
239
+ pWinSize[i]=new T_state[Area];
240
+ }
241
+ for(size_t j=0;j<Area;j++)
242
+ {
243
+ pWinSize[0][j]=pWinSizeX[j];
244
+ pWinSize[1][j]=pWinSizeY[j];
245
+ }
246
+ }
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/Image.h ADDED
@@ -0,0 +1,1574 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef _Image_h
2
+ #define _Image_h
3
+
4
+ #include "project.h"
5
+ #include "stdio.h"
6
+ #include "memory.h"
7
+ #include "ImageProcessing.h"
8
+ #include <iostream>
9
+
10
+ #ifndef _MATLAB
11
+ #include <QFile>
12
+ #include <QString>
13
+ #include "ImageIO.h"
14
+ #else
15
+ #include "mex.h"
16
+ #endif
17
+
18
+ using namespace std;
19
+
20
+ // template class for image
21
+ template <class T>
22
+ class Image
23
+ {
24
+ protected:
25
+ T* pData;
26
+ int imWidth,imHeight,nChannels;
27
+ int nPixels,nElements;
28
+ bool IsDerivativeImage;
29
+ public:
30
+ Image(void);
31
+ Image(int width,int height,int nchannels=1);
32
+ Image(const T& value,int _width,int _height,int _nchannels=1);
33
+ #ifndef _MATLAB
34
+ Image(const QImage& image);
35
+ #endif
36
+ Image(const Image<T>& other);
37
+ ~Image(void);
38
+ virtual Image<T>& operator=(const Image<T>& other);
39
+
40
+ virtual inline void computeDimension(){nPixels=imWidth*imHeight;nElements=nPixels*nChannels;};
41
+
42
+ virtual void allocate(int width,int height,int nchannels=1);
43
+
44
+ template <class T1>
45
+ void allocate(const Image<T1>& other);
46
+
47
+ virtual void clear();
48
+ virtual void reset();
49
+ virtual void copyData(const Image<T>& other);
50
+ void setValue(const T& value);
51
+ void setValue(const T& value,int _width,int _height,int _nchannels=1);
52
+ T max() const{
53
+ T Max=pData[0];
54
+ for(int i=1;i<nElements;i++)
55
+ Max=__max(Max,pData[i]);
56
+ return Max;
57
+ };
58
+ T min() const{
59
+ T Min=pData[0];
60
+ for(int i=1;i<nElements;i++)
61
+ Min=__min(Min,pData[i]);
62
+ return Min;
63
+ }
64
+ template <class T1>
65
+ void copy(const Image<T1>& other);
66
+
67
+ void im2double();
68
+
69
+ // function to access the member variables
70
+ inline T*& data(){return pData;};
71
+ inline const T*& data() const{return (const T*&)pData;};
72
+ inline int width() const {return imWidth;};
73
+ inline int height() const {return imHeight;};
74
+ inline int nchannels() const {return nChannels;};
75
+ inline int npixels() const {return nPixels;};
76
+ inline int nelements() const {return nElements;};
77
+ inline bool isDerivativeImage() const {return IsDerivativeImage;};
78
+ bool IsFloat () const;
79
+ bool IsEmpty() const {if(nElements==0) return true;else return false;};
80
+ bool IsInImage(int x,int y) const {if(x>=0 && x<imWidth && y>=0 && y<imHeight) return true; else return false;};
81
+
82
+ template <class T1>
83
+ bool matchDimension (const Image<T1>& image) const;
84
+
85
+ bool matchDimension (int width,int height,int nchannels) const;
86
+
87
+ inline void setDerivative(bool isDerivativeImage=true){IsDerivativeImage=isDerivativeImage;};
88
+
89
+ // function to move this image to another one
90
+ template <class T1>
91
+ void moveto(Image<T1>& image,int x,int y,int width=0,int height=0);
92
+
93
+ // function of basic image operations
94
+ virtual bool imresize(double ratio);
95
+ template <class T1>
96
+ void imresize(Image<T1>& result,double ratio) const;
97
+ void imresize(int dstWidth,int dstHeight);
98
+ template <class T1>
99
+ void imresize(Image<T1>& result,int dstWidth,int dstHeight) const;
100
+
101
+ #ifndef _MATLAB
102
+ virtual bool imread(const QString& filename);
103
+ virtual void imread(const QImage& image);
104
+
105
+ virtual bool imwrite(const QString& filename,int quality=100) const;
106
+ virtual bool imwrite(const QString& filename,ImageIO::ImageType imagetype,int quality=100) const;
107
+ virtual bool imwrite(const QString& fileanme,T min,T max,int quality=100) const;
108
+ #else
109
+ virtual bool imread(const char* filename) const {return true;};
110
+ virtual bool imwrite(const char* filename) const {return true;};
111
+ #endif
112
+
113
+ template <class T1>
114
+ Image<T1> dx(bool IsAdvancedFilter=false) const;
115
+
116
+ template <class T1>
117
+ void dx(Image<T1>& image,bool IsAdvancedFilter=false) const;
118
+
119
+ template<class T1>
120
+ Image<T1> dy(bool IsAdvancedFilter=false) const;
121
+
122
+ template <class T1>
123
+ void dy(Image<T1>& image,bool IsAdvancedFilter=false) const;
124
+
125
+ template <class T1>
126
+ void dxx(Image<T1>& image) const;
127
+
128
+ template <class T1>
129
+ void dyy(Image<T1>& image) const;
130
+
131
+ template <class T1>
132
+ void laplacian(Image<T1>& image) const;
133
+
134
+ template <class T1>
135
+ void gradientmag(Image<T1>& image) const;
136
+
137
+ template <class T1>
138
+ void GaussianSmoothing(Image<T1>& image,double sigma,int fsize) const;
139
+
140
+ template <class T1>
141
+ void smoothing(Image<T1>& image,double factor=4);
142
+
143
+ template <class T1>
144
+ Image<T1> smoothing(double factor=4);
145
+
146
+ void smoothing(double factor=4);
147
+
148
+ // funciton for filtering
149
+ template <class T1>
150
+ void imfilter(Image<T1>& image,double* filter,int fsize) const;
151
+
152
+ template <class T1>
153
+ Image<T1> imfilter(double* filter,int fsize);
154
+
155
+ template <class T1>
156
+ void imfilter_h(Image<T1>& image,double* filter,int fsize) const;
157
+
158
+ template <class T1>
159
+ void imfilter_v(Image<T1>& image,double* filter,int fsize) const;
160
+
161
+ template <class T1>
162
+ void imfilter_hv(Image<T1>& image,double* hfilter,int hfsize,double* vfilter,int vfsize) const;
163
+
164
+ // function to desaturating
165
+ template <class T1>
166
+ void desaturate(Image<T1>& image) const;
167
+
168
+ void desaturate();
169
+
170
+ template <class T1>
171
+ void collapse(Image<T1>& image) const;
172
+
173
+ // function to concatenate images
174
+ template <class T1,class T2>
175
+ void concatenate(Image<T1>& destImage,const Image<T2>& addImage) const;
176
+
177
+ template <class T1,class T2>
178
+ void concatenate(Image<T1>& destImage,const Image<T2>& addImage,double ratio) const;
179
+
180
+ template <class T1>
181
+ Image<T> concatenate(const Image<T1>& addImage) const;
182
+
183
+ // function to separate the channels of the image
184
+ template <class T1,class T2>
185
+ void separate(unsigned firstNChannels,Image<T1>& image1,Image<T2>& image2) const;
186
+
187
+ // function to sample patch
188
+ template <class T1>
189
+ void getPatch(Image<T1>& patch,double x,double y,int fsize) const;
190
+
191
+ // function to crop the image
192
+ template <class T1>
193
+ void crop(Image<T1>& patch,int Left,int Top,int Width,int Height) const;
194
+
195
+ // basic numerics of images
196
+ template <class T1,class T2>
197
+ void Multiply(const Image<T1>& image1,const Image<T2>& image2);
198
+
199
+ template <class T1,class T2,class T3>
200
+ void Multiply(const Image<T1>& image1,const Image<T2>& image2,const Image<T3>& image3);
201
+
202
+ template <class T1>
203
+ void Multiplywith(const Image<T1>& image1);
204
+
205
+ void Multiplywith(double value);
206
+
207
+ template <class T1,class T2>
208
+ void Add(const Image<T1>& image1,const Image<T2>& image2);
209
+
210
+ template <class T1,class T2>
211
+ void Add(const Image<T1>& image1,const Image<T2>& image2,double ratio);
212
+
213
+ void Add(const T value);
214
+
215
+ template <class T1>
216
+ void Add(const Image<T1>& image1,const double value);
217
+
218
+ template <class T1>
219
+ void Add(const Image<T1>& image1);
220
+
221
+ template <class T1,class T2>
222
+ void Subtract(const Image<T1>& image1,const Image<T2>& image2);
223
+
224
+ // function to normalize an image
225
+ void normalize(Image<T>& image);
226
+
227
+ // function to compute the statistics of the image
228
+ double norm2() const;
229
+
230
+ template <class T1>
231
+ double innerproduct(Image<T1>& image) const;
232
+
233
+ // function to bilateral smooth flow field
234
+ template <class T1>
235
+ void BilateralFiltering(Image<T1>& other,int fsize,double filter_signa,double range_sigma);
236
+
237
+ // file IO
238
+ #ifndef _MATLAB
239
+ bool writeImage(QFile& file) const;
240
+ bool readImage(QFile& file);
241
+ bool writeImage(const QString& filename) const;
242
+ bool readImage(const QString& filename);
243
+ #endif
244
+
245
+ #ifdef _MATLAB
246
+ bool LoadMatlabImage(const mxArray* image,bool IsImageScaleCovnersion=true);
247
+ template <class T1>
248
+ void LoadMatlabImageCore(const mxArray* image,bool IsImageScaleCovnersion=true);
249
+
250
+ template <class T1>
251
+ void ConvertFromMatlab(const T1* pMatlabPlane,int _width,int _height,int _nchannels);
252
+
253
+ void OutputToMatlab(mxArray*& matrix);
254
+
255
+ template <class T1>
256
+ void ConvertToMatlab(T1* pMatlabPlane);
257
+ #endif
258
+ };
259
+
260
+
261
+ typedef Image<unsigned char> BiImage;
262
+ typedef Image<short int> IntImage;
263
+ typedef Image<float> FImage;
264
+ typedef Image<double> DImage;
265
+
266
+ //------------------------------------------------------------------------------------------
267
+ // constructor
268
+ //------------------------------------------------------------------------------------------
269
+ template <class T>
270
+ Image<T>::Image()
271
+ {
272
+ pData=NULL;
273
+ imWidth=imHeight=nChannels=nPixels=nElements=0;
274
+ IsDerivativeImage=false;
275
+ }
276
+
277
+ //------------------------------------------------------------------------------------------
278
+ // constructor with specified dimensions
279
+ //------------------------------------------------------------------------------------------
280
+ template <class T>
281
+ Image<T>::Image(int width,int height,int nchannels)
282
+ {
283
+ imWidth=width;
284
+ imHeight=height;
285
+ nChannels=nchannels;
286
+ computeDimension();
287
+ pData=NULL;
288
+ pData=new T[nElements];
289
+ if(nElements>0)
290
+ memset(pData,0,sizeof(T)*nElements);
291
+ IsDerivativeImage=false;
292
+ }
293
+
294
+ template <class T>
295
+ Image<T>::Image(const T& value,int _width,int _height,int _nchannels)
296
+ {
297
+ pData=NULL;
298
+ allocate(_width,_height,_nchannels);
299
+ setValue(value);
300
+ }
301
+
302
+ #ifndef _MATLAB
303
+ template <class T>
304
+ Image<T>::Image(const QImage& image)
305
+ {
306
+ pData=NULL;
307
+ imread(image);
308
+ }
309
+ #endif
310
+
311
+ template <class T>
312
+ void Image<T>::allocate(int width,int height,int nchannels)
313
+ {
314
+ clear();
315
+ imWidth=width;
316
+ imHeight=height;
317
+ nChannels=nchannels;
318
+ computeDimension();
319
+ pData=NULL;
320
+
321
+ if(nElements>0)
322
+ {
323
+ pData=new T[nElements];
324
+ memset(pData,0,sizeof(T)*nElements);
325
+ }
326
+ }
327
+
328
+ template <class T>
329
+ template <class T1>
330
+ void Image<T>::allocate(const Image<T1> &other)
331
+ {
332
+ allocate(other.width(),other.height(),other.nchannels());
333
+ }
334
+
335
+ //------------------------------------------------------------------------------------------
336
+ // copy constructor
337
+ //------------------------------------------------------------------------------------------
338
+ template <class T>
339
+ Image<T>::Image(const Image<T>& other)
340
+ {
341
+ imWidth=imHeight=nChannels=nElements=0;
342
+ pData=NULL;
343
+ copyData(other);
344
+ }
345
+
346
+ //------------------------------------------------------------------------------------------
347
+ // destructor
348
+ //------------------------------------------------------------------------------------------
349
+ template <class T>
350
+ Image<T>::~Image()
351
+ {
352
+ if(pData!=NULL)
353
+ delete []pData;
354
+ }
355
+
356
+ //------------------------------------------------------------------------------------------
357
+ // clear the image
358
+ //------------------------------------------------------------------------------------------
359
+ template <class T>
360
+ void Image<T>::clear()
361
+ {
362
+ if(pData!=NULL)
363
+ delete []pData;
364
+ pData=NULL;
365
+ imWidth=imHeight=nChannels=nPixels=nElements=0;
366
+ }
367
+
368
+ //------------------------------------------------------------------------------------------
369
+ // reset the image (reset the buffer to zero)
370
+ //------------------------------------------------------------------------------------------
371
+ template <class T>
372
+ void Image<T>::reset()
373
+ {
374
+ if(pData!=NULL)
375
+ memset(pData,0,sizeof(T)*nElements);
376
+ }
377
+
378
+ template <class T>
379
+ void Image<T>::setValue(const T &value)
380
+ {
381
+ for(int i=0;i<nElements;i++)
382
+ pData[i]=value;
383
+ }
384
+
385
+ template <class T>
386
+ void Image<T>::setValue(const T& value,int _width,int _height,int _nchannels)
387
+ {
388
+ if(imWidth!=_width || imHeight!=_height || nChannels!=_nchannels)
389
+ allocate(_width,_height,_nchannels);
390
+ setValue(value);
391
+ }
392
+
393
+ //------------------------------------------------------------------------------------------
394
+ // copy from other image
395
+ //------------------------------------------------------------------------------------------
396
+ template <class T>
397
+ void Image<T>::copyData(const Image<T>& other)
398
+ {
399
+ imWidth=other.imWidth;
400
+ imHeight=other.imHeight;
401
+ nChannels=other.nChannels;
402
+ nPixels=other.nPixels;
403
+ IsDerivativeImage=other.IsDerivativeImage;
404
+
405
+ if(nElements!=other.nElements)
406
+ {
407
+ nElements=other.nElements;
408
+ if(pData!=NULL)
409
+ delete []pData;
410
+ pData=NULL;
411
+ pData=new T[nElements];
412
+ }
413
+ if(nElements>0)
414
+ memcpy(pData,other.pData,sizeof(T)*nElements);
415
+ }
416
+
417
+ template <class T>
418
+ template <class T1>
419
+ void Image<T>::copy(const Image<T1>& other)
420
+ {
421
+ clear();
422
+
423
+ imWidth=other.width();
424
+ imHeight=other.height();
425
+ nChannels=other.nchannels();
426
+ computeDimension();
427
+
428
+ IsDerivativeImage=other.isDerivativeImage();
429
+
430
+ pData=NULL;
431
+ pData=new T[nElements];
432
+ const T1*& srcData=other.data();
433
+ for(int i=0;i<nElements;i++)
434
+ pData[i]=srcData[i];
435
+ }
436
+
437
+ template <class T>
438
+ void Image<T>::im2double()
439
+ {
440
+ if(IsFloat())
441
+ for(int i=0;i<nElements;i++)
442
+ pData[i]/=255;
443
+ }
444
+
445
+ //------------------------------------------------------------------------------------------
446
+ // override equal operator
447
+ //------------------------------------------------------------------------------------------
448
+ template <class T>
449
+ Image<T>& Image<T>::operator=(const Image<T>& other)
450
+ {
451
+ copyData(other);
452
+ return *this;
453
+ }
454
+
455
+ template <class T>
456
+ bool Image<T>::IsFloat() const
457
+ {
458
+ if(typeid(T)==typeid(float) || typeid(T)==typeid(double) || typeid(T)==typeid(long double))
459
+ return true;
460
+ else
461
+ return false;
462
+ }
463
+
464
+ template <class T>
465
+ template <class T1>
466
+ bool Image<T>::matchDimension(const Image<T1>& image) const
467
+ {
468
+ if(imWidth==image.width() && imHeight==image.height() && nChannels==image.nchannels())
469
+ return true;
470
+ else
471
+ return false;
472
+ }
473
+
474
+ template <class T>
475
+ bool Image<T>::matchDimension(int width, int height, int nchannels) const
476
+ {
477
+ if(imWidth==width && imHeight==height && nChannels==nchannels)
478
+ return true;
479
+ else
480
+ return false;
481
+ }
482
+
483
+ //------------------------------------------------------------------------------------------
484
+ // function to move this image to a dest image at (x,y) with specified width and height
485
+ //------------------------------------------------------------------------------------------
486
+ template <class T>
487
+ template <class T1>
488
+ void Image<T>::moveto(Image<T1>& image,int x0,int y0,int width,int height)
489
+ {
490
+ if(width==0)
491
+ width=imWidth;
492
+ if(height==0)
493
+ height=imHeight;
494
+ int NChannels=__min(nChannels,image.nchannels());
495
+
496
+ int x,y;
497
+ for(int i=0;i<height;i++)
498
+ {
499
+ y=y0+i;
500
+ if(y>=image.height())
501
+ break;
502
+ for(int j=0;j<width;j++)
503
+ {
504
+ x=x0+j;
505
+ if(x>=image.width())
506
+ break;
507
+ for(int k=0;k<NChannels;k++)
508
+ image.data()[(y*image.width()+x)*image.nchannels()+k]=pData[(i*imWidth+j)*nChannels+k];
509
+ }
510
+ }
511
+ }
512
+
513
+
514
+ //------------------------------------------------------------------------------------------
515
+ // resize the image
516
+ //------------------------------------------------------------------------------------------
517
+ template <class T>
518
+ bool Image<T>::imresize(double ratio)
519
+ {
520
+ if(pData==NULL)
521
+ return false;
522
+
523
+ T* pDstData;
524
+ int DstWidth,DstHeight;
525
+ DstWidth=(double)imWidth*ratio;
526
+ DstHeight=(double)imHeight*ratio;
527
+ pDstData=new T[DstWidth*DstHeight*nChannels];
528
+
529
+ ImageProcessing::ResizeImage(pData,pDstData,imWidth,imHeight,nChannels,ratio);
530
+
531
+ delete []pData;
532
+ pData=pDstData;
533
+ imWidth=DstWidth;
534
+ imHeight=DstHeight;
535
+ computeDimension();
536
+ return true;
537
+ }
538
+
539
+ template <class T>
540
+ template <class T1>
541
+ void Image<T>::imresize(Image<T1>& result,double ratio) const
542
+ {
543
+ int DstWidth,DstHeight;
544
+ DstWidth=(double)imWidth*ratio;
545
+ DstHeight=(double)imHeight*ratio;
546
+ if(result.width()!=DstWidth || result.height()!=DstHeight || result.nchannels()!=nChannels)
547
+ result.allocate(DstWidth,DstHeight,nChannels);
548
+ ImageProcessing::ResizeImage(pData,result.data(),imWidth,imHeight,nChannels,ratio);
549
+ }
550
+
551
+ template <class T>
552
+ template <class T1>
553
+ void Image<T>::imresize(Image<T1>& result,int DstWidth,int DstHeight) const
554
+ {
555
+ if(result.width()!=DstWidth || result.height()!=DstHeight || result.nchannels()!=nChannels)
556
+ result.allocate(DstWidth,DstHeight,nChannels);
557
+ ImageProcessing::ResizeImage(pData,result.data(),imWidth,imHeight,nChannels,DstWidth,DstHeight);
558
+ }
559
+
560
+
561
+ template <class T>
562
+ void Image<T>::imresize(int dstWidth,int dstHeight)
563
+ {
564
+ DImage foo(dstWidth,dstHeight,nChannels);
565
+ ImageProcessing::ResizeImage(pData,foo.data(),imWidth,imHeight,nChannels,dstWidth,dstHeight);
566
+ copyData(foo);
567
+ }
568
+
569
+ //------------------------------------------------------------------------------------------
570
+ // function to load the image
571
+ //------------------------------------------------------------------------------------------
572
+ #ifndef _MATLAB
573
+ template <class T>
574
+ bool Image<T>::imread(const QString &filename)
575
+ {
576
+ clear();
577
+ if(ImageIO::loadImage(filename,pData,imWidth,imHeight,nChannels))
578
+ {
579
+ computeDimension();
580
+ return true;
581
+ }
582
+ return false;
583
+ }
584
+
585
+ template <class T>
586
+ void Image<T>::imread(const QImage& image)
587
+ {
588
+ clear();
589
+ ImageIO::loadImage(image,pData,imWidth,imHeight,nChannels);
590
+ computeDimension();
591
+ }
592
+
593
+ //------------------------------------------------------------------------------------------
594
+ // function to write the image
595
+ //------------------------------------------------------------------------------------------
596
+ template <class T>
597
+ bool Image<T>::imwrite(const QString& filename,int quality) const
598
+ {
599
+ ImageIO::ImageType type;
600
+ if(IsDerivativeImage)
601
+ type=ImageIO::derivative;
602
+ else
603
+ type=ImageIO::standard;
604
+
605
+ return ImageIO::writeImage(filename,(const T*&)pData,imWidth,imHeight,nChannels,type,quality);
606
+ }
607
+
608
+ template <class T>
609
+ bool Image<T>::imwrite(const QString &filename, ImageIO::ImageType imagetype, int quality) const
610
+ {
611
+ return ImageIO::writeImage(filename,(const T*&)pData,imWidth,imHeight,nChannels,imagetype,quality);
612
+ }
613
+
614
+ template <class T>
615
+ bool Image<T>::imwrite(const QString &filename, T min, T max, int quality) const
616
+ {
617
+ return ImageIO::writeImage(filename,(const T*&)pData,imWidth,imHeight,nChannels,min,max,quality);
618
+ }
619
+
620
+ #endif
621
+
622
+ //------------------------------------------------------------------------------------------
623
+ // function to get x-derivative of the image
624
+ //------------------------------------------------------------------------------------------
625
+ template <class T>
626
+ template <class T1>
627
+ void Image<T>::dx(Image<T1>& result,bool IsAdvancedFilter) const
628
+ {
629
+ if(matchDimension(result)==false)
630
+ result.allocate(imWidth,imHeight,nChannels);
631
+ result.reset();
632
+ result.setDerivative();
633
+ T1*& data=result.data();
634
+ int i,j,k,offset;
635
+ if(IsAdvancedFilter==false)
636
+ for(i=0;i<imHeight;i++)
637
+ for(j=0;j<imWidth-1;j++)
638
+ {
639
+ offset=i*imWidth+j;
640
+ for(k=0;k<nChannels;k++)
641
+ data[offset*nChannels+k]=(T1)pData[(offset+1)*nChannels+k]-pData[offset*nChannels+k];
642
+ }
643
+ else
644
+ {
645
+ double xFilter[5]={1,-8,0,8,-1};
646
+ for(i=0;i<5;i++)
647
+ xFilter[i]/=12;
648
+ ImageProcessing::hfiltering(pData,data,imWidth,imHeight,nChannels,xFilter,2);
649
+ }
650
+ }
651
+
652
+ template <class T>
653
+ template <class T1>
654
+ Image<T1> Image<T>::dx(bool IsAdvancedFilter) const
655
+ {
656
+ Image<T1> result;
657
+ dx<T1>(result,IsAdvancedFilter);
658
+ return result;
659
+ }
660
+
661
+ //------------------------------------------------------------------------------------------
662
+ // function to get y-derivative of the image
663
+ //------------------------------------------------------------------------------------------
664
+ template <class T>
665
+ template <class T1>
666
+ void Image<T>::dy(Image<T1>& result,bool IsAdvancedFilter) const
667
+ {
668
+ if(matchDimension(result)==false)
669
+ result.allocate(imWidth,imHeight,nChannels);
670
+ result.setDerivative();
671
+ T1*& data=result.data();
672
+ int i,j,k,offset;
673
+ if(IsAdvancedFilter==false)
674
+ for(i=0;i<imHeight-1;i++)
675
+ for(j=0;j<imWidth;j++)
676
+ {
677
+ offset=i*imWidth+j;
678
+ for(k=0;k<nChannels;k++)
679
+ data[offset*nChannels+k]=(T1)pData[(offset+imWidth)*nChannels+k]-pData[offset*nChannels+k];
680
+ }
681
+ else
682
+ {
683
+ double yFilter[5]={1,-8,0,8,-1};
684
+ for(i=0;i<5;i++)
685
+ yFilter[i]/=12;
686
+ ImageProcessing::vfiltering(pData,data,imWidth,imHeight,nChannels,yFilter,2);
687
+ }
688
+ }
689
+
690
+ template <class T>
691
+ template <class T1>
692
+ Image<T1> Image<T>::dy(bool IsAdvancedFilter) const
693
+ {
694
+ Image<T1> result;
695
+ dy<T1>(result,IsAdvancedFilter);
696
+ return result;
697
+ }
698
+
699
+ //------------------------------------------------------------------------------------------
700
+ // function to compute the second order derivative
701
+ //------------------------------------------------------------------------------------------
702
+ template <class T>
703
+ template <class T1>
704
+ void Image<T>::dxx(Image<T1> &image) const
705
+ {
706
+ if(!matchDimension(image))
707
+ image.allocate(imWidth,imHeight,nChannels);
708
+ T1* pDstData=image.data();
709
+ if(nChannels==1) // if there is only one image channel
710
+ for(int i=0;i<imHeight;i++)
711
+ for(int j=0;j<imWidth;j++)
712
+ {
713
+ int offset=i*imWidth+j;
714
+ if(j==0)
715
+ {
716
+ pDstData[offset]=pData[offset]-pData[offset+1];
717
+ continue;
718
+ }
719
+ if(j==imWidth-1)
720
+ {
721
+ pDstData[offset]=pData[offset]-pData[offset-1];
722
+ continue;
723
+ }
724
+ pDstData[offset]=pData[offset]*2-pData[offset-1]-pData[offset+1];
725
+ }
726
+ else
727
+ for(int i=0;i<imHeight;i++)
728
+ for(int j=0;j<imWidth;j++)
729
+ {
730
+ int offset=(i*imWidth+j)*nChannels;
731
+ if(j==0)
732
+ {
733
+ for(int k=0;k<nChannels;k++)
734
+ pDstData[offset+k]=pData[offset+k]-pData[offset+nChannels+k];
735
+ continue;
736
+ }
737
+ if(j==imWidth-1)
738
+ {
739
+ for(int k=0;k<nChannels;k++)
740
+ pDstData[offset+k]=pData[offset+k]-pData[offset-nChannels+k];
741
+ continue;
742
+ }
743
+ for(int k=0;k<nChannels;k++)
744
+ pDstData[offset+k]=pData[offset+k]*2-pData[offset+nChannels+k]-pData[offset-nChannels+k];
745
+ }
746
+ }
747
+
748
+ template <class T>
749
+ template <class T1>
750
+ void Image<T>::dyy(Image<T1>& image) const
751
+ {
752
+ if(!matchDimension(image))
753
+ image.allocate(imWidth,imHeight,nChannels);
754
+ T1* pDstData=image.data();
755
+ if(nChannels==1)
756
+ for(int i=0;i<imHeight;i++)
757
+ for(int j=0;j<imWidth;j++)
758
+ {
759
+ int offset=i*imWidth+j;
760
+ if(i==0)
761
+ {
762
+ pDstData[offset]=pData[offset]-pData[offset+imWidth];
763
+ continue;
764
+ }
765
+ if(i==imHeight-1)
766
+ {
767
+ pDstData[offset]=pData[offset]-pData[offset-imWidth];
768
+ continue;
769
+ }
770
+ pDstData[offset]=pData[offset]*2-pData[offset+imWidth]-pData[offset-imWidth];
771
+ }
772
+ else
773
+ for(int i=0;i<imHeight;i++)
774
+ for(int j=0;j<imWidth;j++)
775
+ {
776
+ int offset=(i*imWidth+j)*nChannels;
777
+ if(i==0)
778
+ {
779
+ for(int k=0;k<nChannels;k++)
780
+ pDstData[offset+k]=pData[offset+k]-pData[offset+imWidth*nChannels+k];
781
+ continue;
782
+ }
783
+ if(i==imHeight-1)
784
+ {
785
+ for(int k=0;k<nChannels;k++)
786
+ pDstData[offset+k]=pData[offset+k]-pData[offset-imWidth*nChannels+k];
787
+ continue;
788
+ }
789
+ for(int k=0;k<nChannels;k++)
790
+ pDstData[offset+k]=pData[offset+k]*2-pData[offset+imWidth*nChannels+k]-pData[offset-imWidth*nChannels+k];
791
+ }
792
+ }
793
+
794
+ //------------------------------------------------------------------------------------------
795
+ // function for fast laplacian computation
796
+ //------------------------------------------------------------------------------------------
797
+ template <class T>
798
+ template <class T1>
799
+ void Image<T>::laplacian(Image<T1> &image) const
800
+ {
801
+ if(!matchDimension(image))
802
+ image.allocate(*this);
803
+ image.setDerivative(true);
804
+ ImageProcessing::Laplacian(pData,image.data(),imWidth,imHeight,nChannels);
805
+ }
806
+
807
+
808
+ //------------------------------------------------------------------------------------------
809
+ // function to compute the gradient magnitude of the image
810
+ //------------------------------------------------------------------------------------------
811
+ template <class T>
812
+ template <class T1>
813
+ void Image<T>::gradientmag(Image<T1> &image) const
814
+ {
815
+ if(image.width()!=imWidth || image.height()!=imHeight)
816
+ image.allocate(imWidth,imHeight);
817
+ DImage Ix,Iy;
818
+ dx(Ix,true);
819
+ dy(Iy,true);
820
+ double temp;
821
+ double* imagedata=image.data();
822
+ const double *Ixdata=Ix.data(),*Iydata=Iy.data();
823
+ for(int i=0;i<nPixels;i++)
824
+ {
825
+ temp=0;
826
+ int offset=i*nChannels;
827
+ for(int k=0;k<nChannels;k++)
828
+ {
829
+ temp+=Ixdata[offset+k]*Ixdata[offset+k];
830
+ temp+=Iydata[offset+k]*Iydata[offset+k];
831
+ }
832
+ imagedata[i]=sqrt(temp);
833
+ }
834
+ }
835
+
836
+ //------------------------------------------------------------------------------------------
837
+ // function to do Gaussian smoothing
838
+ //------------------------------------------------------------------------------------------
839
+ template <class T>
840
+ template <class T1>
841
+ void Image<T>::GaussianSmoothing(Image<T1>& image,double sigma,int fsize) const
842
+ {
843
+ Image<T1> foo;
844
+ // constructing the 1D gaussian filter
845
+ double* gFilter;
846
+ gFilter=new double[fsize*2+1];
847
+ double sum=0;
848
+ sigma=sigma*sigma*2;
849
+ for(int i=-fsize;i<=fsize;i++)
850
+ {
851
+ gFilter[i+fsize]=exp(-(double)(i*i)/sigma);
852
+ sum+=gFilter[i+fsize];
853
+ }
854
+ for(int i=0;i<2*fsize+1;i++)
855
+ gFilter[i]/=sum;
856
+
857
+ // apply filtering
858
+ imfilter_hv(image,gFilter,fsize,gFilter,fsize);
859
+
860
+ delete gFilter;
861
+ }
862
+
863
+ //------------------------------------------------------------------------------------------
864
+ // function to smooth the image using a simple 3x3 filter
865
+ // the filter is [1 factor 1]/(factor+2), applied horizontally and vertically
866
+ //------------------------------------------------------------------------------------------
867
+ template <class T>
868
+ template <class T1>
869
+ void Image<T>::smoothing(Image<T1>& image,double factor)
870
+ {
871
+ // build
872
+ double filter2D[9]={1,0,1,0, 0, 0,1, 0,1};
873
+ filter2D[1]=filter2D[3]=filter2D[5]=filter2D[7]=factor;
874
+ filter2D[4]=factor*factor;
875
+ for(int i=0;i<9;i++)
876
+ filter2D[i]/=(factor+2)*(factor+2);
877
+
878
+ if(matchDimension(image)==false)
879
+ image.allocate(imWidth,imHeight,nChannels);
880
+ imfilter<T1>(image,filter2D,1);
881
+ }
882
+
883
+ template <class T>
884
+ template <class T1>
885
+ Image<T1> Image<T>::smoothing(double factor)
886
+ {
887
+ Image<T1> result;
888
+ smoothing(result,factor);
889
+ return result;
890
+ }
891
+
892
+ template <class T>
893
+ void Image<T>::smoothing(double factor)
894
+ {
895
+ Image<T> result(imWidth,imHeight,nChannels);
896
+ smoothing(result,factor);
897
+ copyData(result);
898
+ }
899
+
900
+ //------------------------------------------------------------------------------------------
901
+ // function of image filtering
902
+ //------------------------------------------------------------------------------------------
903
+ template <class T>
904
+ template <class T1>
905
+ void Image<T>::imfilter(Image<T1>& image,double* filter,int fsize) const
906
+ {
907
+ if(matchDimension(image)==false)
908
+ image.allocate(imWidth,imHeight,nChannels);
909
+ ImageProcessing::filtering(pData,image.data(),imWidth,imHeight,nChannels,filter,fsize);
910
+ }
911
+
912
+ template <class T>
913
+ template <class T1>
914
+ Image<T1> Image<T>::imfilter(double *filter, int fsize)
915
+ {
916
+ Image<T1> result;
917
+ imfilter(result,filter,fsize);
918
+ return result;
919
+ }
920
+
921
+ template <class T>
922
+ template <class T1>
923
+ void Image<T>::imfilter_h(Image<T1>& image,double* filter,int fsize) const
924
+ {
925
+ if(matchDimension(image)==false)
926
+ image.allocate(imWidth,imHeight,nChannels);
927
+ ImageProcessing::hfiltering(pData,image.data(),imWidth,imHeight,nChannels,filter,fsize);
928
+ }
929
+
930
+ template <class T>
931
+ template <class T1>
932
+ void Image<T>::imfilter_v(Image<T1>& image,double* filter,int fsize) const
933
+ {
934
+ if(matchDimension(image)==false)
935
+ image.allocate(imWidth,imHeight,nChannels);
936
+ ImageProcessing::vfiltering(pData,image.data(),imWidth,imHeight,nChannels,filter,fsize);
937
+ }
938
+
939
+
940
+ template <class T>
941
+ template <class T1>
942
+ void Image<T>::imfilter_hv(Image<T1> &image, double *hfilter, int hfsize, double *vfilter, int vfsize) const
943
+ {
944
+ if(matchDimension(image)==false)
945
+ image.allocate(imWidth,imHeight,nChannels);
946
+ T1* pTempBuffer;
947
+ pTempBuffer=new T1[nElements];
948
+ ImageProcessing::hfiltering(pData,pTempBuffer,imWidth,imHeight,nChannels,hfilter,hfsize);
949
+ ImageProcessing::vfiltering(pTempBuffer,image.data(),imWidth,imHeight,nChannels,vfilter,vfsize);
950
+ delete pTempBuffer;
951
+ }
952
+
953
+ //------------------------------------------------------------------------------------------
954
+ // function for desaturation
955
+ //------------------------------------------------------------------------------------------
956
+ template <class T>
957
+ template <class T1>
958
+ void Image<T>::desaturate(Image<T1> &image) const
959
+ {
960
+ if(nChannels!=3)
961
+ {
962
+ collapse(image);
963
+ return;
964
+ }
965
+ if(!(image.width()==imWidth && image.height()==imHeight && image.nChannels==1))
966
+ image.allocate(imWidth,imHeight,1);
967
+ T1* data=image.data();
968
+ int offset;
969
+ for(int i=0;i<nPixels;i++)
970
+ {
971
+ offset=i*3;
972
+ data[i]=(double)pData[offset]*.299+pData[offset+1]*.587+pData[offset+2]*.114;
973
+ }
974
+ }
975
+
976
+ template <class T>
977
+ void Image<T>::desaturate()
978
+ {
979
+ Image<T> temp;
980
+ desaturate(temp);
981
+ copyData(temp);
982
+ }
983
+
984
+ template <class T>
985
+ template <class T1>
986
+ void Image<T>::collapse(Image<T1> &image) const
987
+ {
988
+ if(!(image.width()==imWidth && image.height()==imHeight && image.nChannels==1))
989
+ image.allocate(imWidth,imHeight,1);
990
+ T1* data=image.data();
991
+ int offset;
992
+ double temp;
993
+ for(int i=0;i<nPixels;i++)
994
+ {
995
+ offset=i*nChannels;
996
+ temp=0;
997
+ for(int j=0;j<nChannels;j++)
998
+ temp+=pData[offset+j];
999
+ data[i]=temp/nChannels;
1000
+ }
1001
+ }
1002
+
1003
+ //------------------------------------------------------------------------------------------
1004
+ // function to concatenate two images
1005
+ //------------------------------------------------------------------------------------------
1006
+ template <class T>
1007
+ template <class T1,class T2>
1008
+ void Image<T>::concatenate(Image<T1> &destImage, const Image<T2> &addImage) const
1009
+ {
1010
+ if(addImage.width()!=imWidth || addImage.height()!=imHeight)
1011
+ {
1012
+ destImage.copy(*this);
1013
+ return;
1014
+ }
1015
+ int extNChannels=nChannels+addImage.nchannels();
1016
+ if(destImage.width()!=imWidth || destImage.height()!=imHeight || destImage.nchannels()!=extNChannels)
1017
+ destImage.allocate(imWidth,imHeight,extNChannels);
1018
+ int offset;
1019
+ T1*& pDestData=destImage.data();
1020
+ const T2*& pAddData=addImage.data();
1021
+ for(int i=0;i<imHeight;i++)
1022
+ for(int j=0;j<imWidth;j++)
1023
+ {
1024
+ offset=i*imWidth+j;
1025
+ for(int k=0;k<nChannels;k++)
1026
+ pDestData[offset*extNChannels+k]=pData[offset*nChannels+k];
1027
+ for(int k=nChannels;k<extNChannels;k++)
1028
+ pDestData[offset*extNChannels+k]=pAddData[offset*addImage.nchannels()+k-nChannels];
1029
+ }
1030
+ }
1031
+
1032
+ template <class T>
1033
+ template <class T1,class T2>
1034
+ void Image<T>::concatenate(Image<T1> &destImage, const Image<T2> &addImage,double ratio) const
1035
+ {
1036
+ if(addImage.width()!=imWidth || addImage.height()!=imHeight)
1037
+ {
1038
+ destImage.copy(*this);
1039
+ return;
1040
+ }
1041
+ int extNChannels=nChannels+addImage.nchannels();
1042
+ if(destImage.width()!=imWidth || destImage.height()!=imHeight || destImage.nchannels()!=extNChannels)
1043
+ destImage.allocate(imWidth,imHeight,extNChannels);
1044
+ int offset;
1045
+ T1*& pDestData=destImage.data();
1046
+ const T2*& pAddData=addImage.data();
1047
+ for(int i=0;i<imHeight;i++)
1048
+ for(int j=0;j<imWidth;j++)
1049
+ {
1050
+ offset=i*imWidth+j;
1051
+ for(int k=0;k<nChannels;k++)
1052
+ pDestData[offset*extNChannels+k]=pData[offset*nChannels+k];
1053
+ for(int k=nChannels;k<extNChannels;k++)
1054
+ pDestData[offset*extNChannels+k]=pAddData[offset*addImage.nchannels()+k-nChannels]*ratio;
1055
+ }
1056
+ }
1057
+
1058
+
1059
+ template <class T>
1060
+ template <class T1>
1061
+ Image<T> Image<T>::concatenate(const Image<T1> &addImage) const
1062
+ {
1063
+ Image<T> destImage;
1064
+ concatenate(destImage,addImage);
1065
+ return destImage;
1066
+ }
1067
+
1068
+ //------------------------------------------------------------------------------------------
1069
+ // function to separate the image into two
1070
+ //------------------------------------------------------------------------------------------
1071
+ template <class T>
1072
+ template <class T1,class T2>
1073
+ void Image<T>::separate(unsigned int firstNChannels, Image<T1> &image1, Image<T2> &image2) const
1074
+ {
1075
+ image1.IsDerivativeImage=IsDerivativeImage;
1076
+ image2.IsDerivativeImage=IsDerivativeImage;
1077
+
1078
+ if(firstNChannels>=nChannels)
1079
+ {
1080
+ image1=*this;
1081
+ image2.allocate(imWidth,imHeight,0);
1082
+ return;
1083
+ }
1084
+ if(firstNChannels==0)
1085
+ {
1086
+ image1.allocate(imWidth,imHeight,0);
1087
+ image2=*this;
1088
+ return;
1089
+ }
1090
+ int secondNChannels=nChannels-firstNChannels;
1091
+ if(image1.width()!=imWidth || image1.height()!=imHeight || image1.nchannels()!=firstNChannels)
1092
+ image1.allocate(imWidth,imHeight,firstNChannels);
1093
+ if(image2.width()!=imWidth || image2.height()!=imHeight || image2.nchannels()!=secondNChannels)
1094
+ image2.allocate(imWidth,imHeight,secondNChannels);
1095
+
1096
+ for(int i=0;i<imHeight;i++)
1097
+ for(int j=0;j<imWidth;j++)
1098
+ {
1099
+ int offset=i*imWidth+j;
1100
+ for(int k=0;k<firstNChannels;k++)
1101
+ image1.pData[offset*firstNChannels+k]=pData[offset*nChannels+k];
1102
+ for(int k=firstNChannels;k<nChannels;k++)
1103
+ image2.pData[offset*secondNChannels+k-firstNChannels]=pData[offset*nChannels+k];
1104
+ }
1105
+ }
1106
+
1107
+ //------------------------------------------------------------------------------------------
1108
+ // function to separate the image into two
1109
+ //------------------------------------------------------------------------------------------
1110
+ template <class T>
1111
+ template <class T1>
1112
+ void Image<T>::getPatch(Image<T1>& patch,double x,double y,int wsize) const
1113
+ {
1114
+ int wlength=wsize*2+1;
1115
+ if(patch.width()!=wlength || patch.height()!=wlength || patch.nchannels()!=nChannels)
1116
+ patch.allocate(wlength,wlength,nChannels);
1117
+ else
1118
+ patch.reset();
1119
+ ImageProcessing::getPatch(pData,patch.data(),imWidth,imHeight,nChannels,x,y,wsize);
1120
+ }
1121
+
1122
+ //------------------------------------------------------------------------------------------
1123
+ // function to crop an image
1124
+ //------------------------------------------------------------------------------------------
1125
+ template <class T>
1126
+ template <class T1>
1127
+ void Image<T>::crop(Image<T1>& patch,int Left,int Top,int Width,int Height) const
1128
+ {
1129
+ if(patch.width()!=Width || patch.height()!=Height || patch.nchannels()!=nChannels)
1130
+ patch.allocate(Width,Height,nChannels);
1131
+ // make sure that the cropping is valid
1132
+ if(Left<0 || Top<0 || Left>=imWidth || Top>=imHeight)
1133
+ {
1134
+ cout<<"The cropping coordinate is outside the image boundary!"<<endl;
1135
+ return;
1136
+ }
1137
+ if(Width<0 || Height<0 || Width+Left>imWidth || Height+Top>imHeight)
1138
+ {
1139
+ cout<<"The patch to crop is invalid!"<<endl;
1140
+ return;
1141
+ }
1142
+ ImageProcessing::cropImage(pData,imWidth,imHeight,nChannels,patch.data(),Left,Top,Width,Height);
1143
+ }
1144
+
1145
+ //------------------------------------------------------------------------------------------
1146
+ // function to multiply image1, image2 and image3 to the current image
1147
+ //------------------------------------------------------------------------------------------
1148
+ template <class T>
1149
+ template <class T1,class T2,class T3>
1150
+ void Image<T>::Multiply(const Image<T1>& image1,const Image<T2>& image2,const Image<T3>& image3)
1151
+ {
1152
+ if(image1.matchDimension(image2)==false || image2.matchDimension(image3)==false)
1153
+ {
1154
+ cout<<"Error in image dimensions--function Image<T>::Multiply()!"<<endl;
1155
+ return;
1156
+ }
1157
+ if(matchDimension(image1)==false)
1158
+ allocate(image1);
1159
+
1160
+ const T1*& pData1=image1.data();
1161
+ const T2*& pData2=image2.data();
1162
+ const T3*& pData3=image3.data();
1163
+
1164
+ for(int i=0;i<nElements;i++)
1165
+ pData[i]=pData1[i]*pData2[i]*pData3[i];
1166
+ }
1167
+
1168
+ template <class T>
1169
+ template <class T1,class T2>
1170
+ void Image<T>::Multiply(const Image<T1>& image1,const Image<T2>& image2)
1171
+ {
1172
+ if(image1.matchDimension(image2)==false)
1173
+ {
1174
+ cout<<"Error in image dimensions--function Image<T>::Multiply()!"<<endl;
1175
+ return;
1176
+ }
1177
+ if(matchDimension(image1)==false)
1178
+ allocate(image1);
1179
+
1180
+ const T1*& pData1=image1.data();
1181
+ const T2*& pData2=image2.data();
1182
+
1183
+ for(int i=0;i<nElements;i++)
1184
+ pData[i]=pData1[i]*pData2[i];
1185
+ }
1186
+
1187
+ template <class T>
1188
+ template <class T1>
1189
+ void Image<T>::Multiplywith(const Image<T1> &image1)
1190
+ {
1191
+ if(matchDimension(image1)==false)
1192
+ {
1193
+ cout<<"Error in image dimensions--function Image<T>::Multiplywith()!"<<endl;
1194
+ return;
1195
+ }
1196
+ const T1*& pData1=image1.data();
1197
+ for(int i=0;i<nElements;i++)
1198
+ pData[i]*=pData1[i];
1199
+ }
1200
+
1201
+ template <class T>
1202
+ void Image<T>::Multiplywith(double value)
1203
+ {
1204
+ for(int i=0;i<nElements;i++)
1205
+ pData[i]*=value;
1206
+ }
1207
+
1208
+ //------------------------------------------------------------------------------------------
1209
+ // function to add image2 to image1 to the current image
1210
+ //------------------------------------------------------------------------------------------
1211
+ template <class T>
1212
+ template <class T1,class T2>
1213
+ void Image<T>::Add(const Image<T1>& image1,const Image<T2>& image2)
1214
+ {
1215
+ if(image1.matchDimension(image2)==false)
1216
+ {
1217
+ cout<<"Error in image dimensions--function Image<T>::Add()!"<<endl;
1218
+ return;
1219
+ }
1220
+ if(matchDimension(image1)==false)
1221
+ allocate(image1);
1222
+
1223
+ const T1*& pData1=image1.data();
1224
+ const T2*& pData2=image2.data();
1225
+ for(int i=0;i<nElements;i++)
1226
+ pData[i]=pData1[i]+pData2[i];
1227
+ }
1228
+
1229
+ template <class T>
1230
+ template <class T1,class T2>
1231
+ void Image<T>::Add(const Image<T1>& image1,const Image<T2>& image2,double ratio)
1232
+ {
1233
+ if(image1.matchDimension(image2)==false)
1234
+ {
1235
+ cout<<"Error in image dimensions--function Image<T>::Add()!"<<endl;
1236
+ return;
1237
+ }
1238
+ if(matchDimension(image1)==false)
1239
+ allocate(image1);
1240
+
1241
+ const T1*& pData1=image1.data();
1242
+ const T2*& pData2=image2.data();
1243
+ for(int i=0;i<nElements;i++)
1244
+ pData[i]=pData1[i]+pData2[i]*ratio;
1245
+ }
1246
+
1247
+ template <class T>
1248
+ template <class T1>
1249
+ void Image<T>::Add(const Image<T1>& image1,const double ratio)
1250
+ {
1251
+ if(matchDimension(image1)==false)
1252
+ {
1253
+ cout<<"Error in image dimensions--function Image<T>::Add()!"<<endl;
1254
+ return;
1255
+ }
1256
+ const T1*& pData1=image1.data();
1257
+ for(int i=0;i<nElements;i++)
1258
+ pData[i]+=pData1[i]*ratio;
1259
+ }
1260
+
1261
+ template <class T>
1262
+ template <class T1>
1263
+ void Image<T>::Add(const Image<T1>& image1)
1264
+ {
1265
+ if(matchDimension(image1)==false)
1266
+ {
1267
+ cout<<"Error in image dimensions--function Image<T>::Add()!"<<endl;
1268
+ return;
1269
+ }
1270
+ const T1*& pData1=image1.data();
1271
+ for(int i=0;i<nElements;i++)
1272
+ pData[i]+=pData1[i];
1273
+ }
1274
+
1275
+
1276
+ template <class T>
1277
+ void Image<T>::Add(const T value)
1278
+ {
1279
+ for(int i=0;i<nElements;i++)
1280
+ pData[i]+=value;
1281
+ }
1282
+
1283
+ //------------------------------------------------------------------------------------------
1284
+ // function to subtract image2 from image1
1285
+ //------------------------------------------------------------------------------------------
1286
+ template <class T>
1287
+ template <class T1,class T2>
1288
+ void Image<T>::Subtract(const Image<T1> &image1, const Image<T2> &image2)
1289
+ {
1290
+ if(image1.matchDimension(image2)==false)
1291
+ {
1292
+ cout<<"Error in image dimensions--function Image<T>::Add()!"<<endl;
1293
+ return;
1294
+ }
1295
+ if(matchDimension(image1)==false)
1296
+ allocate(image1);
1297
+
1298
+ const T1*& pData1=image1.data();
1299
+ const T2*& pData2=image2.data();
1300
+ for(int i=0;i<nElements;i++)
1301
+ pData[i]=pData1[i]-pData2[i];
1302
+ }
1303
+
1304
+ //------------------------------------------------------------------------------------------
1305
+ // normalize an image
1306
+ //------------------------------------------------------------------------------------------
1307
+ template <class T>
1308
+ void Image<T>::normalize(Image<T>& image)
1309
+ {
1310
+ if(image.width()!=imWidth || image.height()!=imHeight || image.nchannels()!=nChannels)
1311
+ image.allocate(imWidth,imHeight,nChannels);
1312
+ T Max,Min;
1313
+ Max=Min=pData[0];
1314
+ for(int i=0;i<nElements;i++)
1315
+ {
1316
+ Max=qMax(Max,pData[i]);
1317
+ Min=qMin(Min,pData[i]);
1318
+ }
1319
+ if(Max==Min)
1320
+ return;
1321
+ double ratio=1/(Max-Min);
1322
+ if(IsFloat()==false)
1323
+ ratio*=255;
1324
+ T* data=image.data();
1325
+ for(int i=0;i<nElements;i++)
1326
+ data[i]=(double)(pData[i]-Min)*ratio;
1327
+ }
1328
+
1329
+ template <class T>
1330
+ double Image<T>::norm2() const
1331
+ {
1332
+ double result=0;
1333
+ for(int i=0;i<nElements;i++)
1334
+ result+=pData[i]*pData[i];
1335
+ return result;
1336
+ }
1337
+
1338
+ template <class T>
1339
+ template <class T1>
1340
+ double Image<T>::innerproduct(Image<T1> &image) const
1341
+ {
1342
+ double result=0;
1343
+ const T1* pData1=image.data();
1344
+ for(int i=0;i<nElements;i++)
1345
+ result+=pData[i]*pData1[i];
1346
+ return result;
1347
+ }
1348
+
1349
+ #ifndef _MATLAB
1350
+ template <class T>
1351
+ bool Image<T>::writeImage(QFile &file) const
1352
+ {
1353
+ file.write((char *)&imWidth,sizeof(int));
1354
+ file.write((char *)&imHeight,sizeof(int));
1355
+ file.write((char *)&nChannels,sizeof(int));
1356
+ file.write((char *)&IsDerivativeImage,sizeof(bool));
1357
+ if(file.write((char *)pData,sizeof(T)*nElements)!=sizeof(T)*nElements)
1358
+ return false;
1359
+ return true;
1360
+ }
1361
+
1362
+ template <class T>
1363
+ bool Image<T>::readImage(QFile& file)
1364
+ {
1365
+ clear();
1366
+ file.read((char *)&imWidth,sizeof(int));
1367
+ file.read((char *)&imHeight,sizeof(int));
1368
+ file.read((char *)&nChannels,sizeof(int));
1369
+ file.read((char *)&IsDerivativeImage,sizeof(bool));
1370
+ if(imWidth<0 ||imWidth>100000 || imHeight<0 || imHeight>100000 || nChannels<0 || nChannels>10000)
1371
+ return false;
1372
+ allocate(imWidth,imHeight,nChannels);
1373
+ if(file.read((char *)pData,sizeof(T)*nElements)!=sizeof(T)*nElements)
1374
+ return false;
1375
+ return true;
1376
+ }
1377
+
1378
+ template <class T>
1379
+ bool Image<T>::writeImage(const QString &filename) const
1380
+ {
1381
+ QFile file(filename);
1382
+ if(file.open(QIODevice::WriteOnly)==false)
1383
+ return false;
1384
+ if(!writeImage(file))
1385
+ return false;
1386
+ return true;
1387
+ }
1388
+
1389
+ template <class T>
1390
+ bool Image<T>::readImage(const QString &filename)
1391
+ {
1392
+ QFile file(filename);
1393
+ if(file.open(QIODevice::ReadOnly)==false)
1394
+ return false;
1395
+ if(!readImage(file))
1396
+ return false;
1397
+ return true;
1398
+ }
1399
+ #endif
1400
+
1401
+
1402
+ template <class T>
1403
+ template <class T1>
1404
+ void Image<T>::BilateralFiltering(Image<T1>& other,int fsize,double filter_sigma,double range_sigma)
1405
+ {
1406
+ double *pBuffer;
1407
+ Image<T1> result(other);
1408
+ pBuffer=new double[other.nchannels()];
1409
+ for(int i=0;i<imHeight;i++)
1410
+ for(int j=0;j<imWidth;j++)
1411
+ {
1412
+ double totalWeight=0;
1413
+ for(int k=0;k<other.nchannels();k++)
1414
+ pBuffer[k]=0;
1415
+ for(int ii=-fsize;ii<=fsize;ii++)
1416
+ for(int jj=-fsize;jj<=fsize;jj++)
1417
+ {
1418
+ int x=j+jj;
1419
+ int y=i+ii;
1420
+ if(x<0 || x>=imWidth || y<0 || y>=imHeight)
1421
+ continue;
1422
+
1423
+ // compute weight
1424
+ int offset=(y*imWidth+x)*nChannels;
1425
+ double temp=0;
1426
+ for(int k=0;k<nChannels;k++)
1427
+ {
1428
+ double diff=pData[offset+k]-pData[(i*imWidth+j)*nChannels+k];
1429
+ temp+=diff*diff;
1430
+ }
1431
+ double weight=exp(-temp/(2*range_sigma*range_sigma));
1432
+ weight*=exp(-(double)(ii*ii+jj*jj)/(2*filter_sigma*filter_sigma));
1433
+ totalWeight+=weight;
1434
+ for(int k=0;k<other.nchannels();k++)
1435
+ pBuffer[k]+=other.data()[(y*imWidth+x)*other.nchannels()+k]*weight;
1436
+ }
1437
+ for(int k=0;k<other.nchannels();k++)
1438
+ result.data()[(i*imWidth+j)*other.nchannels()]=pBuffer[k]/totalWeight;
1439
+ }
1440
+ other.copyData(result);
1441
+ delete pBuffer;
1442
+ }
1443
+
1444
+
1445
+ #ifdef _MATLAB
1446
+
1447
+ template <class T>
1448
+ template <class T1>
1449
+ void Image<T>::LoadMatlabImageCore(const mxArray *image,bool IsImageScaleCovnersion)
1450
+ {
1451
+ int nDim = mxGetNumberOfDimensions(image);
1452
+ const mwSize* imDim = mxGetDimensions(image);
1453
+ if(nDim==2)
1454
+ allocate(imDim[1],imDim[0]);
1455
+ else if(nDim==3)
1456
+ allocate(imDim[1],imDim[0],imDim[2]);
1457
+ else
1458
+ mexErrMsgTxt("The image doesn't have the appropriate dimension!");
1459
+ T1* pMatlabPlane=(T1*)mxGetData(image);
1460
+ bool IsMatlabFloat;
1461
+ if(typeid(T1)==typeid(float) || typeid(T1)==typeid(double) || typeid(T1)==typeid(long double))
1462
+ IsMatlabFloat=true;
1463
+ else
1464
+ IsMatlabFloat=false;
1465
+ bool isfloat=IsFloat();
1466
+ if(isfloat==IsMatlabFloat || IsImageScaleCovnersion==false)
1467
+ {
1468
+ ConvertFromMatlab<T1>(pMatlabPlane,imWidth,imHeight,nChannels);
1469
+ return;
1470
+ }
1471
+ int offset=0;
1472
+ if(isfloat==true)
1473
+ for(int i=0;i<imHeight;i++)
1474
+ for(int j=0;j<imWidth;j++)
1475
+ for(int k=0;k<nChannels;k++)
1476
+ pData[offset++]=(double)pMatlabPlane[k*nPixels+j*imHeight+i]/255;
1477
+ else
1478
+ for(int i=0;i<imHeight;i++)
1479
+ for(int j=0;j<imWidth;j++)
1480
+ for(int k=0;k<nChannels;k++)
1481
+ pData[offset++]=(double)pMatlabPlane[k*nPixels+j*imHeight+i]*255;
1482
+ }
1483
+
1484
+ template <class T>
1485
+ bool Image<T>::LoadMatlabImage(const mxArray* matrix,bool IsImageScaleCovnersion)
1486
+ {
1487
+ if(mxIsClass(matrix,"uint8"))
1488
+ {
1489
+ LoadMatlabImageCore<unsigned char>(matrix,IsImageScaleCovnersion);
1490
+ return true;
1491
+ }
1492
+ if(mxIsClass(matrix,"int8"))
1493
+ {
1494
+ LoadMatlabImageCore<char>(matrix,IsImageScaleCovnersion);
1495
+ return true;
1496
+ }
1497
+ if(mxIsClass(matrix,"int32"))
1498
+ {
1499
+ LoadMatlabImageCore<int>(matrix,IsImageScaleCovnersion);
1500
+ return true;
1501
+ }
1502
+ if(mxIsClass(matrix,"uint32"))
1503
+ {
1504
+ LoadMatlabImageCore<unsigned int>(matrix,IsImageScaleCovnersion);
1505
+ return true;
1506
+ }
1507
+ if(mxIsClass(matrix,"int16"))
1508
+ {
1509
+ LoadMatlabImageCore<short int>(matrix,IsImageScaleCovnersion);
1510
+ return true;
1511
+ }
1512
+ if(mxIsClass(matrix,"uint16"))
1513
+ {
1514
+ LoadMatlabImageCore<unsigned short int>(matrix,IsImageScaleCovnersion);
1515
+ return true;
1516
+ }
1517
+ if(mxIsClass(matrix,"single"))
1518
+ {
1519
+ LoadMatlabImageCore<float>(matrix,IsImageScaleCovnersion);
1520
+ return true;
1521
+ }
1522
+ if(mxIsClass(matrix,"double"))
1523
+ {
1524
+ LoadMatlabImageCore<double>(matrix,IsImageScaleCovnersion);
1525
+ return true;
1526
+ }
1527
+ mexErrMsgTxt("Unknown type of the image!");
1528
+ return false;
1529
+ }
1530
+
1531
+
1532
+ template <class T>
1533
+ template <class T1>
1534
+ void Image<T>::ConvertFromMatlab(const T1 *pMatlabPlane, int _width, int _height, int _nchannels)
1535
+ {
1536
+ if(imWidth!=_width || imHeight!=_height || nChannels!=_nchannels)
1537
+ allocate(_width,_height,_nchannels);
1538
+ int offset=0;
1539
+ for(int i=0;i<imHeight;i++)
1540
+ for(int j=0;j<imWidth;j++)
1541
+ for(int k=0;k<nChannels;k++)
1542
+ pData[offset++]=pMatlabPlane[k*nPixels+j*imHeight+i];
1543
+ }
1544
+
1545
+ // convert image data to matlab matrix
1546
+ template <class T>
1547
+ template <class T1>
1548
+ void Image<T>::ConvertToMatlab(T1 *pMatlabPlane)
1549
+ {
1550
+ int offset=0;
1551
+ for(int i=0;i<imHeight;i++)
1552
+ for(int j=0;j<imWidth;j++)
1553
+ for(int k=0;k<nChannels;k++)
1554
+ pMatlabPlane[k*nPixels+j*imHeight+i]=pData[offset++];
1555
+ }
1556
+
1557
+ template <class T>
1558
+ void Image<T>::OutputToMatlab(mxArray *&matrix)
1559
+ {
1560
+ mwSize dims[3];
1561
+ dims[0]=imHeight;
1562
+ dims[1]=imWidth;
1563
+ dims[2]=nChannels;
1564
+ if(nChannels==1)
1565
+ matrix=mxCreateNumericArray(2, dims,mxDOUBLE_CLASS, mxREAL);
1566
+ else
1567
+ matrix=mxCreateNumericArray(3, dims,mxDOUBLE_CLASS, mxREAL);
1568
+ ConvertToMatlab<double>((double*)mxGetData(matrix));
1569
+ }
1570
+
1571
+ #endif
1572
+
1573
+
1574
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/ImageIO.h ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef _ImageIO_h
2
+ #define _ImageIO_h
3
+
4
+ #include <QVector>
5
+ #include <QImage>
6
+ #include <QString>
7
+ #include "math.h"
8
+ //-----------------------------------------------------------------------------------------
9
+ // this class is a wrapper to use QImage to load image into image planes
10
+ //-----------------------------------------------------------------------------------------
11
+
12
+ class ImageIO
13
+ {
14
+ public:
15
+ enum ImageType{standard, derivative, normalized};
16
+ ImageIO(void);
17
+ ~ImageIO(void);
18
+ public:
19
+ template <class T>
20
+ static void loadImage(const QImage& image,T*& pImagePlane,int& width,int& height,int& nchannels);
21
+ template <class T>
22
+ static bool loadImage(const QString& filename,T*& pImagePlane,int& width,int& height,int& nchannels);
23
+
24
+ template <class T>
25
+ static unsigned char convertPixel(const T& value,bool IsFloat,ImageType type,T& _Max,T& _Min);
26
+
27
+ template <class T>
28
+ static bool writeImage(const QString& filename, const T*& pImagePlane,int width,int height,int nchannels,ImageType type=standard,int quality=-1);
29
+
30
+ template <class T>
31
+ static bool writeImage(const QString& filename,const T* pImagePlane,int width,int height,int nchannels,T min, T max,int quality=-1);
32
+
33
+ };
34
+
35
+ template <class T>
36
+ void ImageIO::loadImage(const QImage& image, T*& pImagePlane,int& width,int& height,int& nchannels)
37
+ {
38
+ // get the image information
39
+ width=image.width();
40
+ height=image.height();
41
+ nchannels=3;
42
+ pImagePlane=new T[width*height*nchannels];
43
+
44
+ // check whether the type is float point
45
+ bool IsFloat=false;
46
+ if(typeid(T)==typeid(double) || typeid(T)==typeid(float) || typeid(T)==typeid(long double))
47
+ IsFloat=true;
48
+
49
+ const unsigned char* plinebuffer;
50
+ for(int i=0;i<height;i++)
51
+ {
52
+ plinebuffer=image.scanLine(i);
53
+ for(int j=0;j<width;j++)
54
+ {
55
+ if(IsFloat)
56
+ {
57
+ pImagePlane[(i*width+j)*3]=(T)plinebuffer[j*4]/255;
58
+ pImagePlane[(i*width+j)*3+1]=(T)plinebuffer[j*4+1]/255;
59
+ pImagePlane[(i*width+j)*3+2]=(T)plinebuffer[j*4+2]/255;
60
+ }
61
+ else
62
+ {
63
+ pImagePlane[(i*width+j)*3]=plinebuffer[j*4];
64
+ pImagePlane[(i*width+j)*3+1]=plinebuffer[j*4+1];
65
+ pImagePlane[(i*width+j)*3+2]=plinebuffer[j*4+2];
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ template <class T>
72
+ bool ImageIO::loadImage(const QString&filename, T*& pImagePlane,int& width,int& height,int& nchannels)
73
+ {
74
+ QImage image;
75
+ if(image.load(filename)==false)
76
+ return false;
77
+ if(image.format()!=QImage::Format_RGB32)
78
+ {
79
+ QImage temp=image.convertToFormat(QImage::Format_RGB32);
80
+ image=temp;
81
+ }
82
+ loadImage(image,pImagePlane,width,height,nchannels);
83
+ return true;
84
+ }
85
+
86
+ template <class T>
87
+ bool ImageIO::writeImage(const QString& filename, const T*& pImagePlane,int width,int height,int nchannels,ImageType type,int quality)
88
+ {
89
+ int nPixels=width*height,nElements;
90
+ nElements=nPixels*nchannels;
91
+ unsigned char* pTempBuffer;
92
+ pTempBuffer=new unsigned char[nPixels*4];
93
+ memset(pTempBuffer,0,nPixels*4);
94
+
95
+ // check whether the type is float point
96
+ bool IsFloat=false;
97
+ if(typeid(T)==typeid(double) || typeid(T)==typeid(float) || typeid(T)==typeid(long double))
98
+ IsFloat=true;
99
+
100
+ T _Max=0,_Min=0;
101
+ switch(type){
102
+ case standard:
103
+ break;
104
+ case derivative:
105
+ _Max=0;
106
+ for(int i=0;i<nPixels;i++)
107
+ {
108
+ if(IsFloat)
109
+ _Max=__max(_Max,fabs((double)pImagePlane[i]));
110
+ else
111
+ _Max=__max(_Max,abs(pImagePlane[i]));
112
+ }
113
+ break;
114
+ case normalized:
115
+ _Min=_Max=pImagePlane[0];
116
+ for(int i=1;i<nElements;i++)
117
+ {
118
+ _Min=__min(_Min,pImagePlane[i]);
119
+ _Max=__max(_Max,pImagePlane[i]);
120
+ }
121
+ break;
122
+ }
123
+
124
+ for(int i=0;i<nPixels;i++)
125
+ {
126
+ if(nchannels>=3)
127
+ {
128
+ pTempBuffer[i*4]=convertPixel(pImagePlane[i*nchannels],IsFloat,type,_Max,_Min);
129
+ pTempBuffer[i*4+1]=convertPixel(pImagePlane[i*nchannels+1],IsFloat,type,_Max,_Min);
130
+ pTempBuffer[i*4+2]=convertPixel(pImagePlane[i*nchannels+2],IsFloat,type,_Max,_Min);
131
+ }
132
+ else
133
+ for (int j=0;j<3;j++)
134
+ pTempBuffer[i*4+j]=convertPixel(pImagePlane[i*nchannels],IsFloat,type,_Max,_Min);
135
+ pTempBuffer[i*4+3]=255;
136
+ }
137
+ QImage *pQImage=new QImage(pTempBuffer,width,height,QImage::Format_RGB32);
138
+ bool result= pQImage->save(filename,0,quality);
139
+ delete pQImage;
140
+ delete pTempBuffer;
141
+ return result;
142
+ }
143
+
144
+ template <class T>
145
+ bool ImageIO::writeImage(const QString& filename, const T* pImagePlane,int width,int height,int nchannels,T min,T max,int quality)
146
+ {
147
+ int nPixels=width*height,nElements;
148
+ nElements=nPixels*nchannels;
149
+ unsigned char* pTempBuffer;
150
+ pTempBuffer=new unsigned char[nPixels*4];
151
+ memset(pTempBuffer,0,nPixels*4);
152
+
153
+ // check whether the type is float point
154
+ bool IsFloat=false;
155
+ if(typeid(T)==typeid(double) || typeid(T)==typeid(float) || typeid(T)==typeid(long double))
156
+ IsFloat=true;
157
+
158
+ T _Max=max,_Min=min;
159
+
160
+ for(int i=0;i<nPixels;i++)
161
+ {
162
+ if(nchannels>=3)
163
+ {
164
+ pTempBuffer[i*4]=convertPixel(pImagePlane[i*nchannels],IsFloat,normalized,_Max,_Min);
165
+ pTempBuffer[i*4+1]=convertPixel(pImagePlane[i*nchannels+1],IsFloat,normalized,_Max,_Min);
166
+ pTempBuffer[i*4+2]=convertPixel(pImagePlane[i*nchannels+2],IsFloat,normalized,_Max,_Min);
167
+ }
168
+ else
169
+ for (int j=0;j<3;j++)
170
+ pTempBuffer[i*4+j]=convertPixel(pImagePlane[i*nchannels],IsFloat,normalized,_Max,_Min);
171
+ pTempBuffer[i*4+3]=255;
172
+ }
173
+ QImage *pQImage=new QImage(pTempBuffer,width,height,QImage::Format_RGB32);
174
+ bool result= pQImage->save(filename,0,quality);
175
+ delete pQImage;
176
+ delete pTempBuffer;
177
+ return result;
178
+ }
179
+
180
+ template <class T>
181
+ unsigned char ImageIO::convertPixel(const T& value,bool IsFloat,ImageType type,T& _Max,T& _Min)
182
+ {
183
+ switch(type){
184
+ case standard:
185
+ if(IsFloat)
186
+ return __max(__min(value*255,255),0);
187
+ else
188
+ return __max(__min(value,255),0);
189
+ break;
190
+ case derivative:
191
+ return (double)((double)value/_Max+1)/2*255;
192
+ break;
193
+ case normalized:
194
+ return (double)(value-_Min)/(_Max-_Min)*255;
195
+ break;
196
+ }
197
+ return 0;
198
+ }
199
+
200
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/ImageProcessing.h ADDED
@@ -0,0 +1,387 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef _ImageProcessing_h
2
+ #define _ImageProcessing_h
3
+
4
+ #include "math.h"
5
+ #include "stdio.h"
6
+ #include "stdlib.h"
7
+ #include <typeinfo>
8
+
9
+ //----------------------------------------------------------------------------------
10
+ // class to handle basic image processing functions
11
+ // this is a collection of template functions. These template functions are
12
+ // used in other image classes such as BiImage, IntImage and FImage
13
+ //----------------------------------------------------------------------------------
14
+
15
+ class ImageProcessing
16
+ {
17
+ public:
18
+ ImageProcessing(void);
19
+ ~ImageProcessing(void);
20
+ public:
21
+ // basic functions
22
+ template <class T>
23
+ static inline T EnforceRange(const T& x,const int& MaxValue) {return __min(__max(x,0),MaxValue-1);};
24
+
25
+ //---------------------------------------------------------------------------------
26
+ // function to interpolate the image plane
27
+ //---------------------------------------------------------------------------------
28
+ template <class T1,class T2>
29
+ static inline void BilinearInterpolate(const T1* pImage,int width,int height,int nChannels,double x,double y,T2* result);
30
+
31
+ template <class T1>
32
+ static inline T1 BilinearInterpolate(const T1* pImage,int width,int height,double x,double y);
33
+
34
+ template <class T1,class T2>
35
+ static void ResizeImage(const T1* pSrcImage,T2* pDstImage,int SrcWidth,int SrcHeight,int nChannels,double Ratio);
36
+
37
+ template <class T1,class T2>
38
+ static void ResizeImage(const T1* pSrcImage,T2* pDstImage,int SrcWidth,int SrcHeight,int nChannels,int DstWidth,int DstHeight);
39
+
40
+ //---------------------------------------------------------------------------------
41
+ // functions for 1D filtering
42
+ //---------------------------------------------------------------------------------
43
+ template <class T1,class T2>
44
+ static void hfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter1D,int fsize);
45
+
46
+ template <class T1,class T2>
47
+ static void vfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter1D,int fsize);
48
+
49
+ //---------------------------------------------------------------------------------
50
+ // functions for 2D filtering
51
+ //---------------------------------------------------------------------------------
52
+ template <class T1,class T2>
53
+ static void filtering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter2D,int fsize);
54
+
55
+ template <class T1,class T2>
56
+ static void Laplacian(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels);
57
+
58
+ //---------------------------------------------------------------------------------
59
+ // functions for sample a patch from the image
60
+ //---------------------------------------------------------------------------------
61
+ template <class T1,class T2>
62
+ static void getPatch(const T1* pSrcImgae,T2* pPatch,int width,int height,int nChannels,double x,double y,int wsize);
63
+
64
+ //---------------------------------------------------------------------------------
65
+ // function to warp image
66
+ //---------------------------------------------------------------------------------
67
+ template <class T1,class T2>
68
+ static void warpImage(T1* pWarpIm2,const T1* pIm1,const T1* pIm2,const T2* pVx,const T2* pVy,int width,int height,int nChannels);
69
+
70
+ //---------------------------------------------------------------------------------
71
+ // function to crop an image
72
+ //---------------------------------------------------------------------------------
73
+ template <class T1,class T2>
74
+ static void cropImage(const T1* pSrcImage,int SrcWidth,int SrcHeight,int nChannels,T2* pDstImage,int Left,int Top,int DstWidth,int DstHeight);
75
+ //---------------------------------------------------------------------------------
76
+
77
+ //---------------------------------------------------------------------------------
78
+ // function to generate a 2D Gaussian
79
+ //---------------------------------------------------------------------------------
80
+ template <class T>
81
+ static void generate2DGaussian(T*& pImage,int wsize,double sigma=-1);
82
+ };
83
+
84
+ //--------------------------------------------------------------------------------------------------
85
+ // function to interplate multi-channel image plane for (x,y)
86
+ // --------------------------------------------------------------------------------------------------
87
+ template <class T1,class T2>
88
+ inline void ImageProcessing::BilinearInterpolate(const T1* pImage,int width,int height,int nChannels,double x,double y,T2* result)
89
+ {
90
+ int xx,yy,m,n,u,v,l,offset;
91
+ xx=x;
92
+ yy=y;
93
+ double dx,dy,s;
94
+ dx=__max(__min(x-xx,1),0);
95
+ dy=__max(__min(y-yy,1),0);
96
+
97
+ memset(result,0,sizeof(T2)*nChannels);
98
+
99
+ for(m=0;m<=1;m++)
100
+ for(n=0;n<=1;n++)
101
+ {
102
+ u=EnforceRange(xx+m,width);
103
+ v=EnforceRange(yy+n,height);
104
+ offset=(v*width+u)*nChannels;
105
+ s=fabs(1-m-dx)*fabs(1-n-dy);
106
+ for(l=0;l<nChannels;l++)
107
+ result[l]+=pImage[offset+l]*s;
108
+ }
109
+ }
110
+
111
+ template <class T1>
112
+ inline T1 ImageProcessing::BilinearInterpolate(const T1* pImage,int width,int height,double x,double y)
113
+ {
114
+ int xx,yy,m,n,u,v,l,offset;
115
+ xx=x;
116
+ yy=y;
117
+ double dx,dy,s;
118
+ dx=__max(__min(x-xx,1),0);
119
+ dy=__max(__min(y-yy,1),0);
120
+
121
+ T1 result=0;
122
+ for(m=0;m<=1;m++)
123
+ for(n=0;n<=1;n++)
124
+ {
125
+ u=EnforceRange(xx+m,width);
126
+ v=EnforceRange(yy+n,height);
127
+ offset=v*width+u;
128
+ s=fabs(1-m-dx)*fabs(1-n-dy);
129
+ result+=pImage[offset]*s;
130
+ }
131
+ return result;
132
+ }
133
+ //------------------------------------------------------------------------------------------------------------
134
+ // this is the most general function for reszing an image with a varying nChannels
135
+ // bilinear interpolation is used for now. It might be replaced by other (bicubic) interpolation methods
136
+ //------------------------------------------------------------------------------------------------------------
137
+ template <class T1,class T2>
138
+ void ImageProcessing::ResizeImage(const T1* pSrcImage,T2* pDstImage,int SrcWidth,int SrcHeight,int nChannels,double Ratio)
139
+ {
140
+ int DstWidth,DstHeight;
141
+ DstWidth=(double)SrcWidth*Ratio;
142
+ DstHeight=(double)SrcHeight*Ratio;
143
+ memset(pDstImage,sizeof(T2)*DstWidth*DstHeight*nChannels,0);
144
+
145
+ double x,y;
146
+
147
+ for(int i=0;i<DstHeight;i++)
148
+ for(int j=0;j<DstWidth;j++)
149
+ {
150
+ x=(double)(j+1)/Ratio-1;
151
+ y=(double)(i+1)/Ratio-1;
152
+
153
+ // bilinear interpolation
154
+ BilinearInterpolate(pSrcImage,SrcWidth,SrcHeight,nChannels,x,y,pDstImage+(i*DstWidth+j)*nChannels);
155
+ }
156
+ }
157
+
158
+ template <class T1,class T2>
159
+ void ImageProcessing::ResizeImage(const T1 *pSrcImage, T2 *pDstImage, int SrcWidth, int SrcHeight, int nChannels, int DstWidth, int DstHeight)
160
+ {
161
+ double xRatio=(double)DstWidth/SrcWidth;
162
+ double yRatio=(double)DstHeight/SrcHeight;
163
+ memset(pDstImage,sizeof(T2)*DstWidth*DstHeight*nChannels,0);
164
+
165
+ double x,y;
166
+
167
+ for(int i=0;i<DstHeight;i++)
168
+ for(int j=0;j<DstWidth;j++)
169
+ {
170
+ x=(double)(j+1)/xRatio-1;
171
+ y=(double)(i+1)/yRatio-1;
172
+
173
+ // bilinear interpolation
174
+ BilinearInterpolate(pSrcImage,SrcWidth,SrcHeight,nChannels,x,y,pDstImage+(i*DstWidth+j)*nChannels);
175
+ }
176
+ }
177
+
178
+ //------------------------------------------------------------------------------------------------------------
179
+ // horizontal direction filtering
180
+ //------------------------------------------------------------------------------------------------------------
181
+ template <class T1,class T2>
182
+ void ImageProcessing::hfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter1D,int fsize)
183
+ {
184
+ memset(pDstImage,0,sizeof(T2)*width*height*nChannels);
185
+ T2* pBuffer;
186
+ double w;
187
+ int i,j,l,k,offset,jj;
188
+ for(i=0;i<height;i++)
189
+ for(j=0;j<width;j++)
190
+ {
191
+ offset=i*width*nChannels;
192
+ pBuffer=pDstImage+offset+j*nChannels;
193
+ for(l=-fsize;l<=fsize;l++)
194
+ {
195
+ w=pfilter1D[l+fsize];
196
+ jj=EnforceRange(j+l,width);
197
+ for(k=0;k<nChannels;k++)
198
+ pBuffer[k]+=pSrcImage[offset+jj*nChannels+k]*w;
199
+ }
200
+ }
201
+ }
202
+
203
+ //------------------------------------------------------------------------------------------------------------
204
+ // fast filtering algorithm for laplacian
205
+ //------------------------------------------------------------------------------------------------------------
206
+ template <class T1,class T2>
207
+ void ImageProcessing::Laplacian(const T1 *pSrcImage, T2 *pDstImage, int width, int height, int nChannels)
208
+ {
209
+ int LineWidth=width*nChannels;
210
+ int nElements=width*height*nChannels;
211
+ // first treat the corners
212
+ for(int k=0;k<nChannels;k++)
213
+ {
214
+ pDstImage[k]=pSrcImage[k]*2-pSrcImage[nChannels+k]-pSrcImage[LineWidth+k];
215
+ pDstImage[LineWidth-nChannels+k]=pSrcImage[LineWidth-nChannels+k]*2-pSrcImage[LineWidth-2*nChannels+k]-pSrcImage[2*LineWidth-nChannels+k];
216
+ pDstImage[nElements-LineWidth+k]=pSrcImage[nElements-LineWidth+k]*2-pSrcImage[nElements-LineWidth+nChannels+k]-pSrcImage[nElements-2*LineWidth+k];
217
+ pDstImage[nElements-nChannels+k]=pSrcImage[nElements-nChannels+k]*2-pSrcImage[nElements-2*nChannels+k]-pSrcImage[nElements-LineWidth-nChannels+k];
218
+ }
219
+ // then treat the borders
220
+ for(int i=1;i<width-1;i++)
221
+ for(int k=0;k<nChannels;k++)
222
+ {
223
+ pDstImage[i*nChannels+k]=pSrcImage[i*nChannels+k]*3-pSrcImage[(i-1)*nChannels+k]-pSrcImage[(i+1)*nChannels+k]-pSrcImage[i*nChannels+LineWidth+k];
224
+ pDstImage[nElements-LineWidth+i*nChannels+k]=pSrcImage[nElements-LineWidth+i*nChannels+k]*3-pSrcImage[nElements-LineWidth+(i-1)*nChannels+k]-pSrcImage[nElements-LineWidth+(i+1)*nChannels+k]-pSrcImage[nElements-2*LineWidth+i*nChannels+k];
225
+ }
226
+ for(int i=1;i<height-1;i++)
227
+ for(int k=0;k<nChannels;k++)
228
+ {
229
+ pDstImage[i*LineWidth+k]=pSrcImage[i*LineWidth+k]*3-pSrcImage[i*LineWidth+nChannels+k]-pSrcImage[(i-1)*LineWidth+k]-pSrcImage[(i+1)*LineWidth+k];
230
+ pDstImage[(i+1)*LineWidth-nChannels+k]=pSrcImage[(i+1)*LineWidth-nChannels+k]*3-pSrcImage[(i+1)*LineWidth-2*nChannels+k]-pSrcImage[i*LineWidth-nChannels+k]-pSrcImage[(i+2)*LineWidth-nChannels+k];
231
+ }
232
+ // now the interior
233
+ for(int i=1;i<height-1;i++)
234
+ for(int j=1;j<width-1;j++)
235
+ {
236
+ int offset=(i*width+j)*nChannels;
237
+ for(int k=0;k<nChannels;k++)
238
+ pDstImage[offset+k]=pSrcImage[offset+k]*4-pSrcImage[offset+nChannels+k]-pSrcImage[offset-nChannels+k]-pSrcImage[offset-LineWidth+k]-pSrcImage[offset+LineWidth+k];
239
+ }
240
+ }
241
+
242
+
243
+ //------------------------------------------------------------------------------------------------------------
244
+ // vertical direction filtering
245
+ //------------------------------------------------------------------------------------------------------------
246
+ template <class T1,class T2>
247
+ void ImageProcessing::vfiltering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter1D,int fsize)
248
+ {
249
+ memset(pDstImage,0,sizeof(T2)*width*height*nChannels);
250
+ T2* pBuffer;
251
+ double w;
252
+ int i,j,l,k,offset,ii;
253
+ for(i=0;i<height;i++)
254
+ for(j=0;j<width;j++)
255
+ {
256
+ pBuffer=pDstImage+(i*width+j)*nChannels;
257
+ for(l=-fsize;l<=fsize;l++)
258
+ {
259
+ w=pfilter1D[l+fsize];
260
+ ii=EnforceRange(i+l,height);
261
+ for(k=0;k<nChannels;k++)
262
+ pBuffer[k]+=pSrcImage[(ii*width+j)*nChannels+k]*w;
263
+ }
264
+ }
265
+ }
266
+
267
+ //------------------------------------------------------------------------------------------------------------
268
+ // 2d filtering
269
+ //------------------------------------------------------------------------------------------------------------
270
+ template <class T1,class T2>
271
+ void ImageProcessing::filtering(const T1* pSrcImage,T2* pDstImage,int width,int height,int nChannels,double* pfilter2D,int fsize)
272
+ {
273
+ double w;
274
+ int i,j,u,v,k,ii,jj,wsize,offset;
275
+ wsize=fsize*2+1;
276
+ double* pBuffer=new double[nChannels];
277
+ for(i=0;i<height;i++)
278
+ for(j=0;j<width;j++)
279
+ {
280
+ for(k=0;k<nChannels;k++)
281
+ pBuffer[k]=0;
282
+ for(u=-fsize;u<=fsize;u++)
283
+ for(v=-fsize;v<=fsize;v++)
284
+ {
285
+ w=pfilter2D[(u+fsize)*wsize+v+fsize];
286
+ ii=EnforceRange(i+u,height);
287
+ jj=EnforceRange(j+v,width);
288
+ offset=(ii*width+jj)*nChannels;
289
+ for(k=0;k<nChannels;k++)
290
+ pBuffer[k]+=pSrcImage[offset+k]*w;
291
+ }
292
+ offset=(i*width+j)*nChannels;
293
+ for(k=0;k<nChannels;k++)
294
+ pDstImage[offset+k]=pBuffer[k];
295
+ }
296
+ delete pBuffer;
297
+ }
298
+
299
+ //------------------------------------------------------------------------------------------------------------
300
+ // function to sample a patch from the source image
301
+ //------------------------------------------------------------------------------------------------------------
302
+ template <class T1,class T2>
303
+ void ImageProcessing::getPatch(const T1* pSrcImage,T2* pPatch,int width,int height,int nChannels,double x0,double y0,int wsize)
304
+ {
305
+ // suppose pPatch has been allocated and cleared before calling the function
306
+ int wlength=wsize*2+1;
307
+ double x,y;
308
+ for(int i=-wsize;i<=wsize;i++)
309
+ for(int j=-wsize;j<=wsize;j++)
310
+ {
311
+ y=y0+i;
312
+ x=x0+j;
313
+ if(x<0 || x>width-1 || y<0 || y>height-1)
314
+ continue;
315
+ BilinearInterpolate(pSrcImage,width,height,nChannels,x,y,pPatch+((i+wsize)*wlength+j+wsize)*nChannels);
316
+ }
317
+ }
318
+
319
+ //------------------------------------------------------------------------------------------------------------
320
+ // function to warp an image with respect to flow field
321
+ // pWarpIm2 has to be allocated before hands
322
+ //------------------------------------------------------------------------------------------------------------
323
+ template <class T1,class T2>
324
+ void ImageProcessing::warpImage(T1 *pWarpIm2, const T1 *pIm1, const T1 *pIm2, const T2 *pVx, const T2 *pVy, int width, int height, int nChannels)
325
+ {
326
+ for(int i=0;i<height;i++)
327
+ for(int j=0;j<width;j++)
328
+ {
329
+ int offset=i*width+j;
330
+ double x,y;
331
+ y=i+pVy[offset];
332
+ x=j+pVx[offset];
333
+ offset*=nChannels;
334
+ if(x<0 || x>width-1 || y<0 || y>height-1)
335
+ {
336
+ for(int k=0;k<nChannels;k++)
337
+ pWarpIm2[offset+k]=pIm1[offset+k];
338
+ continue;
339
+ }
340
+ BilinearInterpolate(pIm2,width,height,nChannels,x,y,pWarpIm2+offset);
341
+ }
342
+ }
343
+
344
+ //------------------------------------------------------------------------------------------------------------
345
+ // function to crop an image from the source
346
+ // assume that pDstImage has been allocated
347
+ // also Left and Top must be valid, DstWidth and DstHeight should ensure that the image lies
348
+ // inside the image boundary
349
+ //------------------------------------------------------------------------------------------------------------
350
+ template <class T1,class T2>
351
+ void ImageProcessing::cropImage(const T1 *pSrcImage, int SrcWidth, int SrcHeight, int nChannels, T2 *pDstImage, int Left, int Top, int DstWidth, int DstHeight)
352
+ {
353
+ if(typeid(T1)==typeid(T2))
354
+ {
355
+ for(int i=0;i<DstHeight;i++)
356
+ memcpy(pDstImage+i*DstWidth*nChannels,pSrcImage+((i+Top)*SrcWidth+Left)*nChannels,sizeof(T1)*DstWidth*nChannels);
357
+ return;
358
+ }
359
+ int offsetSrc,offsetDst;
360
+ for(int i=0;i<DstHeight;i++)
361
+ for(int j=0;j<DstWidth;j++)
362
+ {
363
+ offsetSrc=((i+Top)*SrcWidth+Left+j)*nChannels;
364
+ offsetDst=(i*DstWidth+j)*nChannels;
365
+ for(int k=0;k<nChannels;k++)
366
+ pDstImage[offsetDst+k]=pSrcImage[offsetSrc+k];
367
+ }
368
+ }
369
+
370
+ //------------------------------------------------------------------------------------------------------------
371
+ // function to generate a 2D Gaussian image
372
+ // pImage must be allocated before calling the function
373
+ //------------------------------------------------------------------------------------------------------------
374
+ template <class T>
375
+ void ImageProcessing::generate2DGaussian(T*& pImage, int wsize, double sigma)
376
+ {
377
+ if(sigma==-1)
378
+ sigma=wsize;
379
+ double alpha=1/(2*sigma*sigma);
380
+ int winlength=wsize*2+1;
381
+ if(pImage==NULL)
382
+ pImage=new T[winlength*winlength];
383
+ for(int i=-wsize;i<=wsize;i++)
384
+ for(int j=-wsize;j<=wsize;j++)
385
+ pImage[(i+wsize)*winlength+j+wsize]=exp(-(double)(i*i+j*j)*alpha);
386
+ }
387
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/Stochastic.cpp ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "Stochastic.h"
2
+ #include "time.h"
3
+ #include "stdlib.h"
4
+ #include "stdio.h"
5
+
6
+ CStochastic::CStochastic(void)
7
+ {
8
+ }
9
+
10
+ CStochastic::~CStochastic(void)
11
+ {
12
+ }
13
+
14
+ void CStochastic::ConvertInt2String(int x,char* string,int BitNumber)
15
+ {
16
+ int i,Base=1;
17
+ for(i=1;i<BitNumber;i++)
18
+ Base*=10;
19
+ for(i=0;i<BitNumber;i++)
20
+ {
21
+ string[i]=x/Base+'0';
22
+ x%=Base;
23
+ Base/=10;
24
+ }
25
+ string[i]='\0';
26
+ }
27
+
28
+ double CStochastic::UniformSampling()
29
+ {
30
+ return (double)rand()/(RAND_MAX+1);
31
+ }
32
+
33
+ int CStochastic::UniformSampling(int R)
34
+ {
35
+ int Index=(double)UniformSampling()*R;
36
+ if(Index>R-1)
37
+ Index=R-1;
38
+ return Index;
39
+ }
40
+
41
+ double CStochastic::GaussianSampling()
42
+ {
43
+ int i;
44
+ double result=0;
45
+ for (i=0;i<12;i++)
46
+ result+=UniformSampling();
47
+ result-=6;
48
+ return result;
49
+ }
50
+
51
+
52
+ double CStochastic::GetMean(double* signal,int length)
53
+ {
54
+ double mean=0;
55
+ int i;
56
+ for(i=0;i<length;i++)
57
+ mean+=signal[i];
58
+ mean/=length;
59
+ return mean;
60
+ }
61
+
62
+ int CStochastic::Sampling(double* Density,int NumSamples)
63
+ {
64
+ double RandNumber=UniformSampling();
65
+ int i;
66
+ double sum=0;
67
+ for(i=0;i<NumSamples;i++)
68
+ {
69
+ sum+=Density[i];
70
+ if(sum>=RandNumber)
71
+ return i;
72
+ }
73
+ return NumSamples-1;
74
+ }
75
+
76
+ void CStochastic::Generate1DGaussian(double* pGaussian,int size,double sigma)
77
+ {
78
+ int i;
79
+ if(sigma==0)
80
+ sigma=size/2;
81
+ for(i=-size;i<=size;i++)
82
+ pGaussian[i+size]=exp(-(double)i*i/(2*sigma));
83
+ }
84
+
85
+ void CStochastic::Generate2DGaussian(double* pGaussian,int WinSize,double sigma)
86
+ {
87
+ int i,j,WinLength=WinSize*2+1;
88
+ double Sigma;
89
+ if(sigma==0)
90
+ Sigma=WinSize;
91
+ else
92
+ Sigma=sigma;
93
+ Sigma*=Sigma;
94
+ for (i=-WinSize;i<=WinSize;i++)
95
+ for(j=-WinSize;j<=WinSize;j++)
96
+ pGaussian[(i+WinSize)*WinLength+j+WinSize]=exp(-(double)(i*i+j*j)/(2*Sigma));
97
+ Normalize(WinLength*WinLength,pGaussian);
98
+ }
99
+
100
+ double CStochastic::entropy(double* pDensity,int n)
101
+ {
102
+ double result=0;
103
+ int i;
104
+ for(i=0;i<n;i++)
105
+ result-=log(__max(pDensity[i],1E-6))*pDensity[i];
106
+ return result;
107
+ }
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/Stochastic.h ADDED
@@ -0,0 +1,410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef STOCHASTIC_H
2
+ #define STOCHASTIC_H
3
+
4
+ #include "math.h"
5
+ #include "stdlib.h"
6
+ #include "project.h"
7
+ #include "memory.h"
8
+
9
+ #define _Release_2DArray(X,i,length) for(i=0;i<length;i++) if(X[i]!=NULL) delete X[i]; delete []X
10
+
11
+ #ifndef _abs(x)
12
+ #define _abs(x) (x>=0)?x:-x
13
+ #endif
14
+
15
+ #ifndef PI
16
+ #define PI 3.1415927
17
+ #endif
18
+
19
+ enum SortType{SortAscending,SortDescending};
20
+
21
+ class CStochastic
22
+ {
23
+ public:
24
+ CStochastic(void);
25
+ ~CStochastic(void);
26
+ static void ConvertInt2String(int x,char* string,int BitNumber=3);
27
+ static double UniformSampling();
28
+ static int UniformSampling(int R);
29
+ static double GaussianSampling();
30
+ template <class T> static void GetMeanVar(T* signal,int length,double* mean,double* var);
31
+ static int Sampling(double* Density,int NumSamples);
32
+ static double GetMean(double *signal,int length);
33
+ static void Generate1DGaussian(double* pGaussian,int size,double sigma=0);
34
+ static void Generate2DGaussian(double* pGaussian,int size,double sigma=0);
35
+ static double entropy(double* pDensity,int n);
36
+
37
+ template <class T> static T sum(int NumData,T* pData);
38
+ template <class T> static void Normalize(int NumData,T* pData);
39
+ template <class T> static T mean(int NumData, T* pData);
40
+ template <class T> static void sort(int number, T* pData,int *pIndex,SortType m_SortType=SortDescending);
41
+ template <class T> static T Min(int NumData, T* pData);
42
+ template <class T> static T Min(int NumData, T* pData1,T* pData2);
43
+ template <class T> static T Max(int NumData ,T* pData);
44
+ template <class T> static int FindMax(int NumData,T* pData);
45
+ template <class T1,class T2> static void ComputeVectorMean(int Dim,int NumData,T1* pData,T2* pMean,double* pWeight=NULL);
46
+ template <class T1,class T2> static void ComputeMeanCovariance(int Dim,int NumData,T1* pData,T2* pMean,T2* pCovarance,double* pWeight=NULL);
47
+ template <class T1,class T2> static double VectorSquareDistance(int Dim,T1* pVector1,T2* pVector2);
48
+ template <class T1> static void KMeanClustering(int Dim,int NumData,int NumClusters,T1* pData,int *pPartition,double** pClusterMean=NULL,int MaxIterationNum=10,int MinClusterSampleNumber=2);
49
+ template <class T> static double norm(T* X,int Dim);
50
+ template <class T1,class T2> static int FindClosestPoint(T1* pPointSet,int NumPoints,int nDim,T2* QueryPoint);
51
+ template <class T1,class T2> static void GaussianFiltering(T1* pSrcArray,T2* pDstArray,int NumPoints,int nChannels,int size,double sigma);
52
+ };
53
+
54
+ template <class T>
55
+ void CStochastic::GetMeanVar(T* signal,int length,double* mean,double* var)
56
+ {
57
+ double m_mean=0,m_var=0;
58
+
59
+ int i;
60
+ for (i=0;i<length;i++)
61
+ m_mean+=signal[i];
62
+ m_mean/=length;
63
+ for (i=0;i<length;i++)
64
+ m_var+=(signal[i]-m_mean)*(signal[i]-m_mean);
65
+ m_var/=length-1;
66
+ *mean=m_mean;
67
+ *var=m_var;
68
+ }
69
+
70
+ template <class T>
71
+ T CStochastic::sum(int NumData, T* pData)
72
+ {
73
+ T sum=0;
74
+ int i;
75
+ for(i=0;i<NumData;i++)
76
+ sum+=pData[i];
77
+ return sum;
78
+ }
79
+
80
+ template <class T>
81
+ void CStochastic::Normalize(int NumData,T* pData)
82
+ {
83
+ int i;
84
+ T Sum;
85
+ Sum=sum(NumData,pData);
86
+ for(i=0;i<NumData;i++)
87
+ pData[i]/=Sum;
88
+ }
89
+
90
+ template <class T>
91
+ T CStochastic::mean(int NumData,T* pData)
92
+ {
93
+ return sum(NumData,pData)/NumData;
94
+ }
95
+
96
+ ////////////////////////////////////////////////////////////
97
+ // sort data in descending order
98
+ template <class T>
99
+ void CStochastic::sort(int Number,T* pData,int *pIndex,SortType m_SortType)
100
+ {
101
+ int i,j,offset_extreme,*flag;
102
+ double extreme;
103
+ flag=new int[Number];
104
+ memset(flag,0,sizeof(int)*Number);
105
+ for(i=0;i<Number;i++)
106
+ {
107
+ if(m_SortType==SortDescending)
108
+ extreme=-1E100;
109
+ else
110
+ extreme=1E100;
111
+ offset_extreme=0;
112
+ for(j=0;j<Number;j++)
113
+ {
114
+ if(flag[j]==1)
115
+ continue;
116
+ if( (m_SortType==SortDescending && extreme<pData[j]) || (m_SortType==SortAscending && extreme>pData[j]))
117
+ {
118
+ extreme=pData[j];
119
+ offset_extreme=j;
120
+ }
121
+ }
122
+ pIndex[i]=offset_extreme;
123
+ flag[offset_extreme]=1;
124
+ }
125
+ delete flag;
126
+ }
127
+
128
+ template <class T>
129
+ T CStochastic::Min(int NumData,T* pData)
130
+ {
131
+ int i;
132
+ T result=pData[0];
133
+ for(i=1;i<NumData;i++)
134
+ result=__min(result,pData[i]);
135
+ return result;
136
+ }
137
+
138
+ template <class T>
139
+ T CStochastic::Min(int NumData,T* pData1,T* pData2)
140
+ {
141
+ int i;
142
+ T result=pData1[0]+pData2[0];
143
+ for(i=1;i<NumData;i++)
144
+ result=__min(result,pData1[i]+pData2[i]);
145
+ return result;
146
+ }
147
+
148
+ template <class T>
149
+ T CStochastic::Max(int NumData,T* pData)
150
+ {
151
+ int i;
152
+ T result=pData[0];
153
+ for(i=1;i<NumData;i++)
154
+ result=__max(result,pData[i]);
155
+ return result;
156
+ }
157
+
158
+ template <class T>
159
+ int CStochastic::FindMax(int NumData,T* pData)
160
+ {
161
+ int i,index;
162
+ T result=pData[0];
163
+ index=0;
164
+ for(i=1;i<NumData;i++)
165
+ if(pData[i]>result)
166
+ {
167
+ index=i;
168
+ result=pData[i];
169
+ }
170
+ return index;
171
+ }
172
+
173
+
174
+ template <class T1,class T2>
175
+ void CStochastic::ComputeMeanCovariance(int Dim,int NumData,T1* pData,T2* pMean,T2* pCovariance,double* pWeight)
176
+ {
177
+ int i,j,k;
178
+ memset(pMean,0,sizeof(T2)*Dim);
179
+ memset(pCovariance,0,sizeof(T2)*Dim*Dim);
180
+
181
+ bool IsWeightLoaded=false;
182
+ double Sum;
183
+ if(pWeight!=NULL)
184
+ IsWeightLoaded=true;
185
+
186
+ // compute mean first
187
+ Sum=0;
188
+ if(IsWeightLoaded)
189
+ for(i=0;i<NumData;i++)
190
+ {
191
+ if(pWeight[i]==0)
192
+ continue;
193
+ for(j=0;j<Dim;j++)
194
+ pMean[j]+=pData[i*Dim+j]*pWeight[i];
195
+ Sum+=pWeight[i];
196
+ }
197
+ else
198
+ {
199
+ for(i=0;i<NumData;i++)
200
+ for(j=0;j<Dim;j++)
201
+ pMean[j]+=pData[i*Dim+j];
202
+ Sum=NumData;
203
+ }
204
+ for(j=0;j<Dim;j++)
205
+ pMean[j]/=Sum;
206
+
207
+ //compute covariance;
208
+ T2* pTempVector;
209
+ pTempVector=new T2[Dim];
210
+
211
+ for(i=0;i<NumData;i++)
212
+ {
213
+ for(j=0;j<Dim;j++)
214
+ pTempVector[j]=pData[i*Dim+j]-pMean[j];
215
+ if(IsWeightLoaded)
216
+ {
217
+ if(pWeight[i]==0)
218
+ continue;
219
+ for(j=0;j<Dim;j++)
220
+ for(k=0;k<=j;k++)
221
+ pCovariance[j*Dim+k]+=pTempVector[j]*pTempVector[k]*pWeight[i];
222
+ }
223
+ else
224
+ for(j=0;j<Dim;j++)
225
+ for(k=0;k<=j;k++)
226
+ pCovariance[j*Dim+k]+=pTempVector[j]*pTempVector[k];
227
+ }
228
+ for(j=0;j<Dim;j++)
229
+ for(k=j+1;k<Dim;k++)
230
+ pCovariance[j*Dim+k]=pCovariance[k*Dim+j];
231
+
232
+ for(j=0;j<Dim*Dim;j++)
233
+ pCovariance[j]/=Sum;
234
+
235
+ delete []pTempVector;
236
+ }
237
+
238
+ template <class T1,class T2>
239
+ void CStochastic::ComputeVectorMean(int Dim,int NumData,T1* pData,T2* pMean,double* pWeight)
240
+ {
241
+ int i,j;
242
+ memset(pMean,0,sizeof(T2)*Dim);
243
+ bool IsWeightLoaded;
244
+ double Sum;
245
+ if(pWeight=NULL)
246
+ IsWeightLoaded=false;
247
+ else
248
+ IsWeightLoaded=true;
249
+
250
+ Sum=0;
251
+ if(IsWeightLoaded)
252
+ for(i=0;i<NumData;i++)
253
+ {
254
+ if(pWeight[i]==0)
255
+ continue;
256
+ for(j=0;j<Dim;j++)
257
+ pMean[j]+=pData[i*Dim+j]*pWeight[i];
258
+ Sum+=pWeight[i];
259
+ }
260
+ else
261
+ {
262
+ for(i=0;i<NumData;i++)
263
+ for(j=0;j<Dim;j++)
264
+ pMean[j]+=pData[i*Dim+j];
265
+ Sum=NumData;
266
+ }
267
+ for(j=0;j<Dim;j++)
268
+ pMean[j]/=Sum;
269
+ }
270
+
271
+ template <class T1,class T2>
272
+ double CStochastic::VectorSquareDistance(int Dim,T1* pVector1,T2* pVector2)
273
+ {
274
+ double result=0,temp;
275
+ int i;
276
+ for(i=0;i<Dim;i++)
277
+ {
278
+ temp=pVector1[i]-pVector2[i];
279
+ result+=temp*temp;
280
+ }
281
+ return result;
282
+ }
283
+
284
+ template <class T1>
285
+ void CStochastic::KMeanClustering(int Dim,int NumData,int NumClusters,T1* pData,int *pPartition,double** pClusterMean,int MaxIterationNum, int MinClusterSampleNumber)
286
+ {
287
+ int i,j,k,l,Index,ClusterSampleNumber;
288
+ double MinDistance,Distance;
289
+ double** pCenters;
290
+ pCenters=new double*[NumClusters];
291
+ for(i=0;i<NumClusters;i++)
292
+ pCenters[i]=new double[Dim];
293
+
294
+ // generate randome guess of the partition
295
+ _CStochastic_KMeanClustering_InitializePartition:
296
+ for(i=0;i<NumClusters;i++)
297
+ {
298
+ Index=UniformSampling(NumData);
299
+ for(j=0;j<Dim;j++)
300
+ pCenters[i][j]=pData[Index*Dim+j];
301
+ }
302
+
303
+ for(k=0;k<MaxIterationNum;k++)
304
+ {
305
+ // step 1. do partition
306
+ for(i=0;i<NumData;i++)
307
+ {
308
+ MinDistance=1E100;
309
+ for(j=0;j<NumClusters;j++)
310
+ {
311
+ Distance=VectorSquareDistance(Dim,pData+i*Dim,pCenters[j]);
312
+ if(Distance<MinDistance)
313
+ {
314
+ MinDistance=Distance;
315
+ Index=j;
316
+ }
317
+ }
318
+ pPartition[i]=Index;
319
+ }
320
+ // step 2. compute mean
321
+ for(i=0;i<NumClusters;i++)
322
+ {
323
+ memset(pCenters[i],0,sizeof(double)*Dim);
324
+ ClusterSampleNumber=0;
325
+ for(j=0;j<NumData;j++)
326
+ if(pPartition[j]==i)
327
+ {
328
+ for(l=0;l<Dim;l++)
329
+ pCenters[i][l]+=pData[j*Dim+l];
330
+ ClusterSampleNumber++;
331
+ }
332
+ // maybe the initial partition is bad
333
+ // if so just do initial partition again
334
+ if(ClusterSampleNumber<MinClusterSampleNumber)
335
+ goto _CStochastic_KMeanClustering_InitializePartition;
336
+ for(l=0;l<Dim;l++)
337
+ pCenters[i][l]/=ClusterSampleNumber;
338
+ }
339
+ }
340
+ // output the final partition if necessary
341
+ if(pClusterMean!=NULL)
342
+ for(i=0;i<NumClusters;i++)
343
+ for(l=0;l<Dim;l++)
344
+ pClusterMean[i][l]=pCenters[i][l];
345
+ // free buffer
346
+ for(i=0;i<NumClusters;i++)
347
+ delete pCenters[i];
348
+ delete []pCenters;
349
+ }
350
+
351
+ template <class T>
352
+ double CStochastic::norm(T* X,int Dim)
353
+ {
354
+ double result=0;
355
+ int i;
356
+ for(i=0;i<Dim;i++)
357
+ result+=X[i]*X[i];
358
+ result=sqrt(result);
359
+ return result;
360
+ }
361
+
362
+ template <class T1,class T2>
363
+ int CStochastic::FindClosestPoint(T1* pPointSet,int NumPoints,int nDim,T2* QueryPoint)
364
+ {
365
+ int i,j,Index=0,offset;
366
+ T1 MinDistance,Distance,x;
367
+ MinDistance=0;
368
+ for(j=0;j<nDim;j++)
369
+ MinDistance+=_abs(pPointSet[j]-QueryPoint[j]);
370
+ for(i=1;i<NumPoints;i++)
371
+ {
372
+ Distance=0;
373
+ offset=i*nDim;
374
+ for(j=0;j<nDim;j++)
375
+ {
376
+ x=pPointSet[offset+j]-QueryPoint[j];
377
+ Distance+=_abs(x);
378
+ }
379
+ if(Distance<MinDistance)
380
+ {
381
+ MinDistance=Distance;
382
+ Index=i;
383
+ }
384
+ }
385
+ return Index;
386
+ }
387
+
388
+ template <class T1,class T2>
389
+ void CStochastic::GaussianFiltering(T1* pSrcArray,T2* pDstArray,int NumPoints,int nChannels,int size,double sigma)
390
+ {
391
+ int i,j,u,l;
392
+ double *pGaussian,temp;
393
+ pGaussian=new double[2*size+1];
394
+ Generate1DGaussian(pGaussian,size,sigma);
395
+ for(i=0;i<NumPoints;i++)
396
+ for(l=0;l<nChannels;l++)
397
+ {
398
+ temp=0;
399
+ for(j=-size;j<=size;j++)
400
+ {
401
+ u=i+j;
402
+ u=__max(__min(u,NumPoints-1),0);
403
+ temp+=pSrcArray[u*nChannels+l]*pGaussian[j+size];
404
+ }
405
+ pDstArray[i*nChannels+l]=temp;
406
+ }
407
+ delete pGaussian;
408
+ }
409
+
410
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/main.cpp ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <QtGui/QApplication>
2
+ #include <QtCore/QCoreApplication>
3
+ #include "Image.h"
4
+ #include "BPFlow.h"
5
+ #include "stdio.h"
6
+ #include "time.h"
7
+
8
+ int main(int argc, char *argv[])
9
+ {
10
+ time_t start,end;
11
+ double dif;
12
+
13
+ QCoreApplication a(argc, argv);
14
+
15
+ time (&start);
16
+
17
+ BiImage im1,im2,Im1,Im2;
18
+ if(!im1.imread("sflowg.00.jpg"))
19
+ {
20
+ printf("Error in loading frame 1!");
21
+ return -1;
22
+ }
23
+ if(!im2.imread("sflowg.01.jpg"))
24
+ {
25
+ printf("Error in loading frame 2!");
26
+ return -1;
27
+ }
28
+ //if(!im1.imread("scene1.row2.jpg"))
29
+ //{
30
+ // printf("Error in loading frame 1!");
31
+ // return -1;
32
+ //}
33
+ //if(!im2.imread("scene1.row3.jpg"))
34
+ //{
35
+ // printf("Error in loading frame 2!");
36
+ // return -1;
37
+ //}
38
+
39
+ im1.GaussianSmoothing(Im1,.8,5);
40
+ im2.GaussianSmoothing(Im2,.8,5);
41
+ Im1.imresize(0.5);
42
+ Im2.imresize(0.5);
43
+ //Im1=im1;
44
+ //Im2=im2;
45
+
46
+ double alpha=0.03*255;
47
+ double gamma=0.002*255;
48
+ BPFlow bpflow;
49
+ int wsize=7;
50
+
51
+ bpflow.setDataTermTruncation(true);
52
+ //bpflow.setTRW(true);
53
+ //bpflow.setDisplay(false);
54
+ bpflow.LoadImages(Im1.width(),Im1.height(),Im1.nchannels(),Im1.data(),Im2.data());
55
+ bpflow.setPara(alpha*2,alpha*20);
56
+ bpflow.setHomogeneousMRF(wsize);
57
+ bpflow.ComputeDataTerm();
58
+ bpflow.ComputeRangeTerm(gamma);
59
+ bpflow.MessagePassing(100,3);
60
+
61
+ //for(int i=0;i<55;i++)
62
+ //{
63
+ // double CTRW=(i+1)*0.02;
64
+ // bpflow.setCTRW(CTRW);
65
+ // printf("No.%d CTRW=%f energy=%f\n",i+1,CTRW,bpflow.MessagePassing(300,1));
66
+ //}
67
+
68
+ //bpflow.MessagePassing(60);
69
+ bpflow.ComputeVelocity();
70
+
71
+ DImage vx(Im1.width(),Im1.height()),vy(Im1.width(),Im1.height());
72
+ for(int i=0;i<Im1.npixels();i++)
73
+ {
74
+ vx.data()[i]=bpflow.flow().data()[i*2];
75
+ vy.data()[i]=bpflow.flow().data()[i*2+1];
76
+ }
77
+ vx.imwrite("vx_discrete.jpg",ImageIO::normalized);
78
+ vy.imwrite("vy_discrete.jpg",ImageIO::normalized);
79
+
80
+ time (&end);
81
+ dif = difftime (end,start);
82
+ printf ("It took you %.2lf seconds to run SIFT flow.\n", dif );
83
+
84
+ //return a.exec();
85
+ return 1;
86
+ }
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/mexDiscreteFlow.cpp ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "mex.h"
2
+ #include "project.h"
3
+ #include "Image.h"
4
+ #include "BPFlow.h"
5
+
6
+ double* outputMatrix2(mxArray*& plhs,int n1,int n2)
7
+ {
8
+ mwSize dims[2];
9
+ dims[0]=n1;
10
+ dims[1]=n2;
11
+ plhs=mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL);
12
+ return (double *)mxGetData(plhs);
13
+ }
14
+
15
+ double* outputMatrix3(mxArray*& plhs,int n1,int n2,int n3)
16
+ {
17
+ mwSize dims[3];
18
+ dims[0]=n1;
19
+ dims[1]=n2;
20
+ dims[2]=n3;
21
+ plhs=mxCreateNumericArray(3,dims,mxDOUBLE_CLASS,mxREAL);
22
+ return (double *)mxGetData(plhs);
23
+ }
24
+
25
+ double* outputMatrix4(mxArray*& plhs,int n1,int n2,int n3,int n4)
26
+ {
27
+ mwSize dims[4];
28
+ dims[0]=n1;
29
+ dims[1]=n2;
30
+ dims[2]=n3;
31
+ dims[3]=n4;
32
+ plhs=mxCreateNumericArray(4,dims,mxDOUBLE_CLASS,mxREAL);
33
+ return (double *)mxGetData(plhs);
34
+ }
35
+
36
+
37
+ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
38
+ {
39
+ BiImage Im1,Im2;
40
+ Im1.LoadMatlabImage(prhs[0]);
41
+ Im2.LoadMatlabImage(prhs[1]);
42
+
43
+
44
+ // define parameters
45
+ double alpha=0.01;
46
+ double d=1;
47
+ double gamma=0.001;
48
+ int nIterations=40;
49
+ int nHierarchy=2;
50
+ int wsize=5;
51
+
52
+ // load the parameters for matching
53
+ if(nrhs>=3)
54
+ {
55
+ int nDims=mxGetNumberOfDimensions(prhs[2]);
56
+ if(nDims>2)
57
+ mexErrMsgTxt("The third parameter must be a vector!");
58
+ const mwSize* dims=mxGetDimensions(prhs[2]);
59
+ if(dims[0]!=1 && dims[1]!=1)
60
+ mexErrMsgTxt("The third parameter must be a vector!");
61
+ int nPara=dims[0]+dims[1]-1;
62
+ double* para=(double *)mxGetData(prhs[2]);
63
+
64
+ if(nPara>=1)
65
+ alpha=para[0];
66
+ if(nPara>=2)
67
+ d=para[1];
68
+ if(nPara>=3)
69
+ gamma=para[2];
70
+ if(nPara>=4)
71
+ nIterations=para[3];
72
+ if(nPara>=5)
73
+ nHierarchy=para[4];
74
+ if(nPara>=6)
75
+ wsize=para[5];
76
+ }
77
+ //printf("Alpha: %f d: %f gamma: %f nIterations: %d nHierarchy: %d wsize: %d\n",alpha,d,gamma,nIterations,nHierarchy,wsize);
78
+ // load offset information
79
+ IntImage OffsetX,OffsetY;
80
+
81
+ if(nrhs>=5)
82
+ {
83
+ OffsetX.LoadMatlabImage(prhs[3],false); // there is no force of conversion
84
+ OffsetY.LoadMatlabImage(prhs[4],false);
85
+ }
86
+
87
+ IntImage WinSizeX,WinSizeY;
88
+ if(nrhs>=7)
89
+ {
90
+ WinSizeX.LoadMatlabImage(prhs[5],false); // there is no force of conversion
91
+ WinSizeY.LoadMatlabImage(prhs[6],false);
92
+ }
93
+
94
+ DImage Im_s,Im_d;
95
+ if(nrhs==9)
96
+ {
97
+ Im_s.LoadMatlabImage(prhs[7],false); // no force of converstion
98
+ Im_d.LoadMatlabImage(prhs[8],false);
99
+ }
100
+ // output parameters
101
+ double* pEnergyList=NULL;
102
+ if(nlhs>1)
103
+ pEnergyList=outputMatrix2(plhs[1],1,nIterations);
104
+
105
+ // the main function goes here
106
+ BPFlow bpflow;
107
+ bpflow.LoadImages(Im1.width(),Im1.height(),Im1.nchannels(),Im1.data(),Im2.width(),Im2.height(),Im2.data());
108
+
109
+ if(nrhs>7)
110
+ bpflow.setPara(Im_s,Im_d);
111
+ else
112
+ bpflow.setPara(alpha,d);
113
+
114
+ bpflow.setHomogeneousMRF(wsize); // first assume homogeneous setup
115
+
116
+ if(nrhs>=4)
117
+ bpflow.LoadOffset(OffsetX.data(),OffsetY.data());
118
+
119
+ if(nrhs>=6)
120
+ bpflow.LoadWinSize(WinSizeX.data(),WinSizeY.data());
121
+
122
+ bpflow.ComputeDataTerm();
123
+ bpflow.ComputeRangeTerm(gamma);
124
+
125
+ bpflow.MessagePassing(nIterations,nHierarchy,pEnergyList);
126
+ bpflow.ComputeVelocity();
127
+
128
+ bpflow.flow().OutputToMatlab(plhs[0]);
129
+
130
+ }
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/mexDiscreteFlow.m ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ % mex function to perform SIFT flow matching
2
+ %
3
+ % Usage:
4
+ %
5
+ % [flow,energylist] = mexDiscreteFlow(im1,im2,para);
6
+ % [flow,energylist] = mexDiscreteFlow(im1,im2,para,offsetX,offsetY,winSizeX,winSizeY);
7
+ %
8
+ % ** Input arguments **
9
+ %
10
+ % Arguments "im1" and "im2" are SIFT images. SIFT flow is estimated from im1 to im2. Normally
11
+ % MATLAB function dense_sift is used to generate a dense SIFT image from a RGB image. The
12
+ % argument "para" is the a vector specifying the parameters of matching. Let
13
+ %
14
+ % para = [alpha,d,gamma,nIterations,nHierarchy,wsize];
15
+ %
16
+ % where each element is defined as (the number in the parenthesis is the defaut value)
17
+ %
18
+ % alpha: (0.01) the weight of the truncated L1-norm regularization on the flow
19
+ % d: (1) the threshold of the truncation
20
+ % gamma: (0.001) the weight of the magnitude of the flow
21
+ % nIterations: (40) the number of iterations
22
+ % nHierarchy: (2) the number of hierarchies in the efficient BP implementation
23
+ % wsize: (5) the half size of the search window
24
+ %
25
+ % Notice that the two images are NOT required to have the same dimension. But certainly you
26
+ % wouldn't expect to get anything meaningful if their dimensions are too different.
27
+ %
28
+ % Arguments "offsetX" and "offsetY" should have the same dimension (height and width) as im1.
29
+ % These two parameters are introduced to handle coarse-to-fine SIFT flow matching. We can
30
+ % specify the center of the matching window by defining offsetX and offsetY. When these two
31
+ % arguments are not specified, they are treated as 0.
32
+ %
33
+ % Arugments "winSizeX" and "winSizeY" should have also the same dimeiosn as im1. These two
34
+ % parameters are introduced to overwrite "wsize" in "para", to specify pixel-wise window size.
35
+ %
36
+ % ** Output arguments **
37
+ %
38
+ % The first argument "flow" is a [h x w x 2] matrix where flow(:,:,1) is the horizontal component
39
+ % and flow(:,:,2) is the vertical component. The height and weight of flow is the same as im1.
40
+ %
41
+ % The second argument "energylist" records the energy obtained by the BP algorithm at each
42
+ % iteration.
43
+ %
44
+ % Ce Liu
45
+ % CSAIL, MIT
46
+ % Jan, 2009
47
+ % All rights reserved
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/mexDiscreteFlow.mexa64 ADDED
Binary file (74.5 kB). View file
 
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/mexDiscreteFlow.mexmaci64 ADDED
Binary file (77.5 kB). View file
 
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/mexDiscreteFlow.mexw64 ADDED
Binary file (61.4 kB). View file
 
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/project.h ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include "stdio.h"
3
+
4
+ // if the files are compiled in linux or mac os then uncomment the following line, otherwise comment it if you compile using visual studio in windows
5
+ #define _LINUX_MAC
6
+
7
+ template <class T>
8
+ void _Release1DBuffer(T* pBuffer)
9
+ {
10
+ if(pBuffer!=NULL)
11
+ delete []pBuffer;
12
+ pBuffer=NULL;
13
+ }
14
+
15
+ template <class T>
16
+ void _Rlease2DBuffer(T** pBuffer,size_t nElements)
17
+ {
18
+ for(size_t i=0;i<nElements;i++)
19
+ delete [](pBuffer[i]);
20
+ delete []pBuffer;
21
+ pBuffer=NULL;
22
+ }
23
+
24
+
25
+ #define _MATLAB
26
+
27
+ #ifdef _MATLAB
28
+ #include "mex.h"
29
+ #endif
30
+
31
+
32
+ #ifdef _LINUX_MAC
33
+
34
+ template <class T1,class T2>
35
+ T1 __min(T1 a, T2 b)
36
+ {
37
+ return (a>b)?b:a;
38
+ }
39
+
40
+ template <class T1,class T2>
41
+ T1 __max(T1 a, T2 b)
42
+ {
43
+ return (a<b)?b:a;
44
+ }
45
+
46
+ #endif
UVDoc_official/eval/eval_code/SIFTflow/mexDiscreteFlow/readme.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The *.cpp and *.h files in this folder are used to mex a matlab dll file for SIFT flow matching. Use the following command to compile in Matlab (tested on version 7.6 or later)
2
+
3
+ mex mexDiscreteFlow.cpp BPFlow.cpp Stochastic.cpp
4
+
5
+ It has been tested in Windows 7 x64, Linux x64 and Mac OS 10.6. Precompiled versions of Windows 7 x64 and Mac OS 10.6 are included in the folder.
6
+
7
+
8
+ ------------------------- Important -------------------------
9
+
10
+ You must change one line in order to compile correctly. On line 5 of project.h, you should comment this line if you are compiling using visual studio in windows, or uncomment if you are in linux or mac os.
11
+
12
+ -------------------------------------------------------------
UVDoc_official/eval/eval_code/SIFTflow/readme.txt ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ This is the software package of our TPAMI paper:
2
+
3
+ C. Liu, J. Yuen and A. Torralba. SIFT Flow: Dense Correspondence across Scenes and its Applications. IEEE Transactions on Pattern Analysis and Machine Intelligence (TPAMI), 2010.
4
+
5
+ Please cite our paper if you use our code for your research. Also, please notice that there is slight change in the package compared to the ECCV version. Obtaining dense SIFT features has been mexed.
6
+
7
+
8
+ Please run demo.h first. If error appears, please go to "mexDenseSIFT" and "mexDiscreteFlow" subfolders and follow the instructions in readme.txt (yes, there is readme.txt in each folder) to compile the cpp files.
9
+
10
+ ------------------------- Important -------------------------
11
+
12
+ You must change one line in order to compile correctly. On line 5 of project.h, you should comment this line if you are compiling using visual studio in windows, or uncomment if you are in linux or mac os.
13
+
14
+ -------------------------------------------------------------
15
+
16
+ Run demo.m in MATLAB and you will see how SIFT flow works.
17
+
18
+ Enjoy!
19
+
20
+
21
+ Ce Liu
22
+
23
+ Microsoft Research New England
24
+ Sep 2010
UVDoc_official/eval/eval_code/SIFTflow/warpFL.m ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ % warp i2 according to flow field in vx vy
2
+ function [warpI2,I]=warp(i2,vx,vy)
3
+ [M,N]=size(i2);
4
+ [x,y]=meshgrid(1:N,1:M);
5
+ warpI2=interp2(x,y,i2,x+vx,y+vy,'bicubic');
6
+ I=find(isnan(warpI2));
7
+ warpI2(I)=zeros(size(I));