Reputation: 1
I got some weird effect when using np.resize. The picture should be a cat but after a small resize the picture is completely different. What is happening? Does this happen to tf.resize too? cat pic: https://www.pexels.com/photo/white-and-grey-kitten-on-brown-and-black-leopard-print-textile-45201/
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
# Read Images of shape 220,230
img = mpimg.imread('cat.jpeg')
img_re = np.resize(img,(224,224,3))
# Output Images
plt.imshow(img_re)
Upvotes: 0
Views: 391
Reputation: 13336
numpy resize just resize the arrays. Numpy doesn't care about images or any other interpretation we might have of the array meaning.
Consider this example:
import numpy as np
A=np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
#A=
#array([[ 1, 2, 3],
# [ 4, 5, 6],
# [ 7, 8, 9],
# [10, 11, 12]])
np.resize(A, (2,6))
#Output
#array([[ 1, 2, 3, 4, 5, 6],
# [ 7, 8, 9, 10, 11, 12]])
All it does, is rearranging the bunch of 12 values in A. In A, they are interpreted as 4 lines of 3 values. Resized array use the same values, but interpreted as 2 lines of 6 values
if you use np.resize with a new size that leads to have less value than in the original, then, they are truncated
np.resize(A, (3,3))
#array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
If the new size means more data, then they are repeated
np.resize(A, (3,5))
#array([[ 1, 2, 3, 4, 5],
# [ 6, 7, 8, 9, 10],
# [11, 12, 1, 2, 3]])
So, in your case, it is truncated. You had 220×230×3 numbers in your original array, you only have 224×224×3 in the resized ones. But more importantly, they are rearranged. The first line contains the 220 pixels from the first original line, then the 4 first pixels of the second. Then the new second line contains the 216 remaining pixels of the orignal second line, and then 8 pixels of the original 3rd. And so on.
Yet another example maybe using a pattern line/column for values in the original image
im=np.array([[11,12,13],[21,22,23],[31,32,33]])
#Array whose value follows a 2D logic. Think of it as an image.
#array([[11, 12, 13],
# [21, 22, 23],
# [31, 32, 33]])
np.resize(im, (2,4))
#array([[11, 12, 13, 21],
# [22, 23, 31, 32]])
Not only value 33 was truncated from the result. But more importantly we lost the coherence of YX values.
Now, solution: well you need an image specific function to resize the image the way you want, not just some data management functions.
In pure numpy, you could
newImage=np.zeros((224,224,3))
newImage[:224,:220,:]=img[:224,:220,:]
(It drops the 6 last lines of img, and complete the 4 last columns with 0 — assuming that you meant 230 lines of 220 pixels for the original image. Not always clear when one drops the 3, whether shape are meant to be WxH image size, of (H, W, 3) numpy array shape. But you get the idea anyway).
Or, more realisticly, you use an image processing library to resize the image
import cv2
img_re = cv2.resize(img, (224,224))
(Note that here (224,224) are (W,H) dimensions, note (H,W) as in numpy shapes. Not that it matters when W=H, sure)
cv2
is probably overkill here. But it as the advantage to manipulate only ndarray, as you do.
A less overkill solution would be to use PIL
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import PIL
# Read Images of shape 220,230
img = PIL.Image.open('a1.jpg')
img_re = img.resize((224,224))
# Output Images
plt.imshow(img_re)
The difference is that here, img and img_re are no longer ndarray. Put if you need those arrays, you can easily
imgArr=np.array(img)
img_reArr=np.array(img_re)
Upvotes: 2