-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathNLMIntegralSelfCode.m
More file actions
312 lines (274 loc) · 9.78 KB
/
NLMIntegralSelfCode.m
File metadata and controls
312 lines (274 loc) · 9.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
%Efficient template matching code
%Load up a 3by3 test image
testImg = imread("images/test.jpeg");
test2Img = imread("images/alleyReference.png");
test3Img = imread("images/test2.jpeg");
testImgBW = rgb2gray(testImg);
test2ImgBW = rgb2gray(test2Img);
test3ImgBW = rgb2gray(test3Img);
%filtering parameters
%patch size, search window, sigma, decayH
pSize = 3;
swSize = pSize * 3;
sigma = 5;
decayH = 0.5;
%The samplingImg is the image we pick values from, the resultImg is the
%denoised image.
samplingImg = test2ImgBW;
resultImg = samplingImg;
%Loop through all the pixels and find the intensities and replace the ones
%in the result image
[imgM, imgN] = size(samplingImg);
% offsets = disFinder(swSize, pSize, 9, 9, samplingImg);
% ssdList = getSSD(offsets, pSize, 9, 9, samplingImg);
for row = 1 : imgM
for col = 1 : imgN
%intImg = integralImageCalc(samplingImg);
%first we need to check if the patch will exceed the boundaries of
%the image
isOut = isOutBound(imgN, imgM, pSize, col, row);
if isOut == 0
offsets = disFinder(swSize, pSize, col, row, samplingImg);
ssdList = getSSD(offsets, pSize, col, row, samplingImg);
pI = calcIntensity(col, row, offsets, ssdList, samplingImg, sigma, decayH);
resultImg(row, col) = pI;
end
end
end
figure;
subplot(2,1,1);
imshow(uint8(samplingImg));
subplot(2,1,2);
imshow(uint8(resultImg));
%the following function finds the list of displacements for a given point
%and search window
function displacements = disFinder(swSize, pSize, ptX, ptY, img)
%calculate the correct search window by truncating the pixels that are
%out of bound from the original image
swOffset = int16(swSize - 1) / 2;
%compute the limits of the search window
swMinX = ptX - swOffset;
swMinY = ptY - swOffset;
swMaxX = ptX + swOffset;
swMaxY = ptY + swOffset;
%get the limits of the image
[m, n] = size(img);
%resize the limits of the search window
if swMinX < 1
swMinX = 1;
end
if swMinY < 1
swMinY = 1;
end
if swMaxX > n
swMaxX = n;
end
if swMaxY > m
swMaxY = m;
end
%with the search window limits corrected, we can identify all the
%patches to compare
%we also initalize the displacement array to store all the
%displacements
disArray = zeros(2, swMaxX * swMaxY);
%loop through all the possible pixels in the corect search window
%we will ignore the pixels that create patches that exceed outside the
%boundaries of the search window
%set up a displacement array counter
dCounter = 1;
for row = swMinY : swMaxY
for col = swMinX : swMaxX
%Check if the patch goes out of bounds of the search window
isOut = isOutBound(swMaxX, swMaxY, pSize, col, row);
if isOut == 0 %if the patch does not exceed the boundaries of the search window
%we will add its offset into our displacement array
disArray(1, dCounter) = col - ptX; %the offset x amount
disArray(2, dCounter) = row - ptY; %the offset y amount
%increment the dCounter
dCounter = dCounter + 1;
end
%if the patch is out of bounds, we do nothing and just loop to
%the next set of coordinates
end
end
%get rid of the exta zero elements
disArray = disArray(:, 1 : dCounter -1);
%output the array containing all the offsets we need to compute for the
%ssd
displacements = disArray;
end
%The following function takes all the offsets for the single point and
%computes the array of ssd for each patch
function ssdArray = getSSD(offsetArray, pSize, ptX, ptY, img)
%initlize the ssd array to contain all the ssd's
[oRow, oCol] = size(offsetArray);
ssdA = zeros(1, oCol);
%loop through all the offsets and calucalate the SSD
for ssdC = 1 : oCol
%get the offset values
offsetX = offsetArray(1, ssdC);
offsetY = offsetArray(2, ssdC);
%Find the distance ^ 2 image map
diffImage = calcDifferenceImage(offsetX, offsetY, img);
%Next using the difference Image, calculate the integral image
intImage = integralImageCalc(diffImage);
%After obtaining the integral image we can find the ssd for the
%exact patch we have
pOffset = (pSize - 1) / 2;
pMinX = ptX - pOffset;
pMaxX = ptX + pOffset;
pMinY = ptY - pOffset;
pMaxY = ptY + pOffset;
%correct the limits to the integral image constraints
[intM, intN] = size(intImage);
if pMinX > intN
pMinX = intN;
end
if pMinY > intM
pMinY = intM;
end
if pMaxX > intN
pMaxX = intN;
end
if pMaxY > intM
pMaxY = intM;
end
%using the formula we will obtain the sum of this patch
l1 = intImage(pMinY, pMinX);
l2 = intImage(pMinY, pMaxX);
l3 = intImage(pMaxY, pMaxX);
l4 = intImage(pMaxY, pMinX);
sumOfPatch = l3 - l2 - l4 + l1;
%insert the sum into the array
ssdA(1, ssdC) = sumOfPatch;
end
%output the ssd of the patches
ssdArray = ssdA;
end
%The following function caluclates the difference image of an image and its offset
function dImg = calcDifferenceImage(offsetX, offsetY, img)
%get the size of the image
[mImg, nImg] = size(img);
%first we need to identity how the Images will be tructated
dMinX = 1;
dMinY = 1;
dMaxX = nImg;
dMaxY = mImg;
ogMinX = 1;
ogMinY = 1;
ogMaxX = nImg;
ogMaxY = mImg;
%please note, what ever we do to the displaced image, to apply the
%opposite operator to the original image
if offsetX > 0 %if the x offset is positive
%we will shrink x from the top left
dMinX = 1 + offsetX;
%since x offset is positive, the shift for og image will be
%negative
ogMaxX = ogMaxX - offsetX;
else
%if the x offset is negative, we shrink from the bottom right
dMaxX = dMaxX + offsetX;
%since x offset is negative, the shift for og image will be
%positive
ogMinX = 1 - offsetX;
end
if offsetY > 0 %if the y offset is positive
%we will shrink y from the top left
dMinY = 1 + offsetY;
ogMaxY = ogMaxY - offsetY;
else
%if the y offset is negative, we will shrink from the bottom right
dMaxY = dMaxY + offsetY;
ogMinY = 1 - offsetY;
end
%now we construct the two images, dImg and ogImage
dImage = double(img(dMinY : dMaxY, dMinX : dMaxX));
ogImage = double(img(ogMinY : ogMaxY, ogMinX : ogMaxX));
%the two images should now have the same dimensions for us to caluclate
%the difference
%It is in this moment we also normalise the values
diffImage = ((ogImage - dImage) .^ 2) / 255;
%now we return the image
dImg = diffImage;
end
%the following function calculates the intensity of the pixel we are
%modifying
function pixIntensity = calcIntensity(ptX, ptY, offsetArray, ssdArray, img, sigma, decayH)
%First we must calc the weights array from the ssd, sigma and decay H
[rowC, colC] = size(ssdArray);
wArray = zeros(1, colC);
%for every ssd we get add a new weight to the weight array
for wC = 1 : colC
weight = calcWeight(ssdArray(1, wC), sigma, decayH);
wArray(1, wC) = weight;
end
%Given the weight array we now loop through all the weights and
%multiply it with the pixel
%Then accumulate the values in accumulator
accumulator = 0;
for wC = 1 : colC
%first we need to discover the pixel intensity
pixelX = ptX + offsetArray(1, wC);
pixelY = ptY + offsetArray(2, wC);
pixel = img(pixelY, pixelX);
pIntensity = pixel * wArray(1, wC);
accumulator = uint16(accumulator) + uint16(pIntensity);
end
pixIntensity = uint8(accumulator / colC);
end
function value = calcWeight(ssd, sigma, decayH)
%normalised sigma
sigma = sigma / 255;
temp1 = max(ssd - (2 * sigma), 0);
temp2 = temp1 / decayH;
temp3 = -temp2;
value = exp(temp3);
end
function out = isOutBound(limitX, limitY, windowSize, ptX, ptY)
offset = (windowSize - 1) / 2;
minX = ptX - offset;
minY = ptY - offset;
maxX = ptX + offset;
maxY = ptY + offset;
if minX < 1 || minY < 1
out = 1;
elseif maxX > limitX || maxY > limitY
out = 1;
else
out = 0;
end
end
%Integral Image calculator
function image = integralImageCalc(img)
%create the integral image values holder
[m,n] = size(img);
integralImg = zeros(m+1,n+1);
horizontalImg = zeros(m+1, n+1);
%caluclate the horizontal integral image
for row = 1 : m+1
for col = 1: n+1
if col == 1 || row == 1
horizontalImg(row, col) = 0;
else
horizontalImg(row, col) = horizontalImg(row, col - 1) + img(row-1, col-1);
end
end
end
%the sum of the value is the sum of the value above + the rest
%on its row
for row = 1 : m +1
for col = 1 : n +1
%if it is the first element, let the first element by itself
if row == 1 || col == 1
integralImg(row, col) = 0;
else
%computing the integral value
integralImg(row, col) = integralImg(row - 1, col) + horizontalImg(row, col);
end
end
end
%remove the edge zeros
integralImg = integralImg(2:m+1, 2:n+1);
image = integralImg;
end