1

I'm using matplotlib to do it but for some reason, my code creates an unexpected image.

import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import imread,imsave


# original image
image1=imread('img.jpg')
plt.imshow(image1)
plt.show()

# empesize the blue in that image
plt.imshow(image1*[0.95,0.95,1])
plt.show()

result:

The top image is the original one and the second (which is shown) is the unexpected result.

enter image description here

It seems that no matter what values I enter to the vector, I get the same strange result. Why?

Stav Alfi
  • 13,139
  • 23
  • 99
  • 171
  • Maybe it's because of data type. Try to force uint8 with `np.array(image1*[0.95,0.95,1]).astype(np.uint8)`. – kostek Jul 17 '18 at 20:56
  • First of all, It's working so thanks. I don't understand why. I thought `uint8` is helping when I sum over `255` but I don't sum anything. Am I? – Stav Alfi Jul 17 '18 at 21:01

1 Answers1

2

This question is closely related to Getting black plots with plt.imshow after multiplying image array by a scalar.

You may compare image1.dtype, which is uint8, to (image1*[0.95,0.95,1]).dtype, which is float.

Matplotlib imshow can plot integer values, in which case they need to be in the range [0, 255] or float values, in which case they need to be in the range [0.0, 1.0]. So while plotting the original image of integer values works fine, the multiplied image, which will consist of float values up to 255., exceeds the allowed range of [0.0, 1.0] by 25500%. Hence it is mostly white (because pixel values are cropped to 1.0).

The solution is either to cast the values back to uint after multiplication,

image2 = (image1*[0.95,0.95,1]).astype(np.uint8)

or to divide by 255.,

image2 = (image1*[0.95,0.95,1])/255.

You could also use plt.Normalize like

image2 = plt.Normalize(0,255)(image1*[0.95,0.95,1])
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • Thank you. Could you also tell me what will be the difference if I used `np.dot` instead of `*`? – Stav Alfi Jul 17 '18 at 21:25
  • np.dot is a completely different operation. It would mix the rgb channels. What would be the purpose of that? – ImportanceOfBeingErnest Jul 17 '18 at 21:30
  • After reading this answer: https://stackoverflow.com/a/12201744/806963 to grayscale an image, he used the vector `[0.3,0.6,0.1]` and `np.dot` it with the image. I understand the implementation differences between `*` and `np.dot` but still don't understand, for example, what will be the impact on the actual image if I would use `np.dot`. – Stav Alfi Jul 17 '18 at 21:43
  • Those are just two very different things. The multiplication with a vector will leave each channel intact, they will just be weighted differently. In contrast the dot product will mix the rgb channels and the output will be a single grey scale channel. So `*` means RGB -> RGB, while `dot` means RGB -> Grey. – ImportanceOfBeingErnest Jul 17 '18 at 21:49
  • Why `dot`, in general, result in a grey image? – Stav Alfi Jul 17 '18 at 21:53
  • ...due to the definition of a dot product in mathematics. vector * vector = vector; but rowvector dot columnvector = scalar. – ImportanceOfBeingErnest Jul 17 '18 at 21:57