I've started studying image processing some weeks ago, and I've started reading about image interpolation techniques, and testing them in Python with the help of cv2 library. I have a b&w image, and I have to resize it by a factor of 4 using bilinear interpolation and by simply zooming out. The problem is that I can't figure out why with zooming out the image seems to be better compared to bilinear algorithm. Maybe i'm missing something, but shouldn't be the result of bilinear interpolation better than zooming out?
Here is the code of zoom out algorithm (simply doing an average of the pixels):
A1 = cv2.imread('img.pgm', cv2.IMREAD_GRAYSCALE)
cv2_imshow(A1)
#Get height and width of source image
M1 = A1.shape[0]
N1 = A1.shape[1]
# Set height and width of target image
z = 4 # zoom out factor
M2 = round(M1/z)
N2 = round(N1/z)
A2 = np.zeros((M2,N2))
#Zoom out
for i in range(0, M2):
for j in range(0, N2):
for k in range (0, z):
for l in range(0, z):
A2[i,j] = A2[i,j] A1[z*i k, z*j l]
A2 = A2 / pow(z,2)
cv2_imshow(A2)
Here is the code of bilinear interpolation:
A = cv2.imread('img.pgm', cv2.IMREAD_GRAYSCALE)
cv2_imshow(A)
# Get height and width of source image
M1 = A1.shape[0]
N1 = A1.shape[1]
# Setting height and width of target image
c = 0.25 # Scaling of factor 4 (1/4)
M2 = round(c * M1)
N2 = round(c * N1)
A2 = np.zeros((M2,N2))
# Bilinear interpolation
for i in range(0,M2):
for j in range(0,N2):
x = (i 0.5) * M1/M2 # x = (i 0.5) / c
y = (j 0.5) * N1/N2 # y = (j 0.5) / c
k = round(x) - 1
l = round(y) - 1
k = min( max( k, 0 ), M1-2 )
l = min( max( l, 0 ), N1-2 )
u = x - k - 0.5
v = y - l - 0.5
A2[i,j] = round( (1-v) * ( (1-u)*A1[k,l] u*A1[k 1,l] ) v * ( (1-u)*A1[k,l 1] u*A1[k 1,l 1] ) )
cv2_imshow(A2)
CodePudding user response:
You are facing a phenomenon known as aliasing, which occurs when you sample the image too sparsely, so that the high frequencies are not faithfully preserved. (This is a little technical, see https://en.wikipedia.org/wiki/Nyquist_frequency)
The cure is to erase or lessen these high frequencies using a lowpass filter, such as averaging. In other terms, you blur the image to remove the fine features, that would be poorly sampled.
CodePudding user response:
"Zooming out" is orthogonal to the means of interpolation. Those things aren't comparable. Your choice of words confuses the issue.
Your two pieces of code only differ in that the first one sums up the entire source area that would contribute to a destination pixel (equivalent to INTER_AREA
in OpenCV), while the second code merely does a point sample for the source location (equivalent to INTER_LINEAR
in OpenCV).
Signal processing theory dictates that one has to apply a low-pass filter before decimating, or else incur aliasing artefacts.
INTER_AREA
's summing of source pixels constitutes a low-pass filter.