I am working through the textbook, "Understanding Deep Learning" (specifically page 173) and have been able to solve the problem for calculating the bilinear upsampling of a given image to create a double size image. This is a tutorial program, not intended to use libraries to do the actual bilinear step. We should do it "by hand".
I have a correct solution but it involves an ugly second loop to calculate the interpolation for the bottom right cell. The top left, top right, bottom left are all calculated cleanly in my first loop. But I could not do the same approach for the bottom right cell due to needing to look at the adjacent uncalculated values.
Is there a better approach?
Here is my code:
def bilinear(x_in):
x_out = np.zeros(( x_in.shape[0]*2, x_in.shape[1]*2 ))
x_in_pad = np.zeros((x_in.shape[0]+1, x_in.shape[1]+1))
x_in_pad[0:x_in.shape[0],0:x_in.shape[1]] = x_in
height, width = x_in.shape
height_out = height * 2
width_out = width * 2
for y in range(0, height_out, 2):
for x in range(0, width_out, 2):
y_start = y // 2
x_start = x // 2
anchor_value = x_in_pad[y_start, x_start]
right_value = x_in_pad[y_start, x_start + 1]
down_value = x_in_pad[y_start + 1, x_start]
x_out[y, x] = anchor_value
x_out[y, x + 1] = np.ceil((anchor_value + right_value)/2)
x_out[y + 1, x] = np.ceil((anchor_value + down_value)/2)
for y in range(0, height_out, 2):
for x in range(0, width_out, 2):
right_side = 0
if x + 2 == width_out:
right_side = 0
else:
right_side = x_out[y + 1, x + 2]
x_out[y + 1, x + 1] = np.ceil((x_out[y + 1, x] + right_side)/2)
return x_out
with test data:
print("Original:")
print(orig_2_2)
print("Bilinear:")
print(bilinear(orig_2_2))
yielding
Original:
[[2 4]
[4 8]]
Bilinear:
[[2. 3. 4. 2.]
[3. 5. 6. 3.]
[4. 6. 8. 4.]
[2. 3. 4. 2.]]