0
$\begingroup$

In a book, I saw the following code to load images from a directory:

1.image = cv2.imread(imagePath)
2.image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
3.image = cv2.resize(image, (28,28))            
4.image = img_to_array(image)
5.data.append(image)

cv2.imread()

It converts image to a numpys array in BGR format

img_to_array()

It converts PIL instance to numpy array, but in this case image will stay in BGR format as the image is loaded by cv2.

What is the use of img_to_array() (from keras.preprocessing.image module) after cv2.imread(), as it is already in numpy array.

Also:

To double check, I displayed images before and after applying img_to_array() using cv2.imshow().

BEFORE applying img_to_array()

enter image description here

AFTER applying img_to_array()###

enter image description here

Also Also:

But, if I try to save the images using cv2.imwrite into a file, they both are saved as normal (ie. like the first image). Why is this happening?

$\endgroup$
1
$\begingroup$

This is because of the data type you provide to the imshow() function.

Check the documentation:

The function may scale the image, depending on its depth: If the image is 8-bit unsigned, it is displayed as is. If the image is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. That is, the value range [0,255*256] is mapped to [0,255]. If the image is 32-bit or 64-bit floating-point, the pixel values are multiplied by 255. That is, the value range [0,1] is mapped to [0,255].

So when you use cv2.imread() it reads data uint8, that is 8-bit unsigned format thus imshow() displays the original data.

But when you use img_to_array() it converts data to the float. Thus imshow() multiplies it with 256. It expects the float values in normalized form, that is all the pixels are divided by 256. That is the reason for such a display.

This is how cv2.imread() data looks like... enter image description here

and its data type... enter image description here

This is how img_to_array() data looks like... enter image description here

and its data type... enter image description here

If you divide your image by 1.0 to convert it to the float...

import cv2
# from keras.preprocessing.image import img_to_array
image = cv2.imread("car.jpg")
image = image/1.0
cv2.imshow("Divided by 1.0", image)
cv2.waitKey(0)

...this is what you will get:

enter image description here

Same as img_to_array.

But it you divide image with 256.0 as follows:

import cv2
# from keras.preprocessing.image import img_to_array
image = cv2.imread("car.jpg")
image = image/256.0
cv2.imshow("Divided by 256.0", image)
cv2.waitKey(0)

You get the original image since imshow() multiplies the float with 256.

enter image description here

So what you need is to divide your img_to_array() output by 256 or convert it to the uint8.

$\endgroup$
2
  • $\begingroup$ Thanks @Shahriyar, So, img_to_array() is needed to make the array compatible with Keras or I can skip it ? $\endgroup$
    – Shiv
    Nov 19 '20 at 6:53
  • $\begingroup$ Depends on how you use that, mostly yes if the next question you use requires that format as an input. Not otherwise. Try to recheck your outputs after each step. $\endgroup$ Nov 19 '20 at 8:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.