I use imshow function with interpolation='nearest' on a grayscale image and get a nice color picture as a result, looks like it does some sort of color segmentation for me, what exactly is going on there?
I would also like to get something like this for image processing, is there some function on numpy arrays like interpolate('nearest') out there?
EDIT: Please correct me if I'm wrong, it looks like it does simple pixel clustering (clusters are colors of the corresponding colormap) and the word 'nearest' says that it takes the nearest colormap color (probably in the RGB space) to decide to which cluster the pixel belongs.
interpolation='nearest' simply displays an image without trying to interpolate between pixels if the display resolution is not the same as the image resolution (which is most often the case). It will result an image in which pixels are displayed as a square of multiple pixels.
There is no relation between interpolation='nearest' and the grayscale image being displayed in color. By default imshow uses the jet colormap to display an image. If you want it to be displayed in greyscale, call the gray() method to select the gray colormap.
Related
Regarding the following cv2.inRange(...) invocation:
mask = cv2.inRange(quantized_img, color, color)
Must the 'quantized_img' and 'color' arguments be strictly in HSV or it's OK to have RGB image and RGB 'color'? It seems that RGB works for me, but all examples I could find are HSV-based. So I'm concerned about the correct usage.
Thanks!
In general, use whatever color space you like. RGB/BGR is fine, HSV is fine, something completely made up (with cv.transform) is fine too.
inRange spans a "cube".
Think about it. Imagine a 3D plot with R,G,B axes, or with H,S,V axes. In RGB space, the faces of the cube are aligned with those RGB axes. in HSV space the faces of the cube are aligned with those axes instead.
Now, a cube spanned in RGB space, when transformed into HSV space, is not aligned with the axes in HSV space. In fact it's not even a cube anymore, but likely some kind of torus or section of a cone or something. Same goes the other way around.
If the area of values you're interested in, in whatever space you choose, is flat or even stick-shaped (instead of a mostly spherical cloud), the cube you have to span might align very badly with the area of values you are interested in, and would have to include a lot of values you aren't interested in.
So you move into another color space where your values of interest are somewhat better aligned with the axes in that space. Then the cube spanned by inRange fits your purpose better.
Imagine a "stick" in RGB space going from the black corner to the white corner. It represents "colors" with no saturation to them (because colors are in the other six corners of the cube). Try spanning a cube over that area. Doesn't fit well.
In HSV space however, it's trivial. Usually it's visualized as a cylinder/inverted cone though... span a thin cylinder in the center: any Hue (angle), any Value (height), with very low Saturation (close to the center axis). If you took HSV as a cube, you'd span a thin wall instead. And it all would fit very well.
The explanation given by #Christoph Rackwitz is completely correct. I'll just like to add a few tips observed by me.
HSV and Lab color spaces are the best ones for color segmentation.
Keep BGR color space as probably the last option.
Do not just blindly start finding the range in HSV or Lab color segmentation for your color. Look for other methods too.
Other methods include:
Visualize each color channel of HSV and Lab separately as a grayscale image. You might see some pattern there only.
One thing that helped in my case was I did Otsu's thresholding on "Hue" and "Saturation" channels of my image and then performed a bitwise OR operation on their output. The final image had everything I need without any errors. Do a hit-and-try on your input images to observe such patterns. This helps a lot.
I am wanting to create a function that would determine how colorblind-friendly an image is (on a scale from 0-1). I have several color-related functions that are capable of performing the following tasks:
Take an image (as a PIL image, filename, or RGB array) and transform it into an image representative of what a colorblind person would see (for the different types of colorblindness)
Take an image and determine the rgb colors associated with each pixel of the image (transform into numpy array of rgb colors)
Determine the color palette associated with an image
Find the similarity between two rgb arrays (using CIELAB- see colormath package)
My first instinct was to transform the image and colorblind version of the image into RGB arrays and then use the CIELAB function to determine the similarity between the two images. However, that doesn't really solve the problem since it wouldn't be able to pick out things like readability (e.g. if the text and background color end up being very similar after adjusting for colorblindness).
Any ideas for how to determine how colorblind-friendly an image is?
Good day,
I have an image which I generate through a deep learning process. The image is RGB, and the values of the image range from -0.28 to 1.25. Typically I would rescale the image so that the values are floating point between 0 and 1, or integers between 0 and 255. However I have found that in my current experiment doing this has made my images much darker. The image type is np.array (float64).
If I plot the image using matplotlib.pyplot then the values of the original image get clipped, but the image is not darkened.
The problem with this is that I am unable to save this version of the image. plt.imsave('image.png', art) gives an error.
When I scale the image I get the below output which is dark. This image can be saved using plt.imsave().
Here is my scaling function:
def scale(img):
return((img - img.min())/(img.max() - img.min()) * 255)
My questions:
1) Why I am I not able to save my image in the first (bright) image? If scaling is the problem, then:
2) Why does scaling make the image dark.
Help is much appreciated.
1) Why am I not able to save my image in the first (bright) image?
It's hard to answer this without seeing the specific error you're getting, but my guess is it might have to do with the range of values in your image. Maybe negative values are an issue, or the fact that you have both negative floats and floats larger than 1.
If I create some fake RGB image data in the range [-0.28, 1.25] and try to save it with plt.imsave(), I get the following error:
ValueError: Floating point image RGB values must be in the 0..1 range.
2) Why does scaling make the image dark?
Scaling your image's pixel values will likely change the appearance.
Imagine you had a light image, such that the values in the image ranged from [200, 255]. When you scale the values, you spread the values from [0, 255] and now you have pixels that were previously bright (around 200) being mapped to black (0). If you have a generally bright image, it will seem darker after scaling. This seems to be the case for you.
As a side note: I would suggest using Pillow or OpenCV rather than Matplotlib if you're doing lots of image-related work :)
EDIT
As #alkasm pointed out in a comment, when you use plt.imshow() to display the image, the values are clipped. This means that the first image will have all negative values mapped to 0, and all values greater than 1 mapped to 1. The first image is clipped and saturated to make it appear that there are more dark and bright pixels than there should be.
So it's not that the second image is darker, it's that the first image isn't displayed properly.
Is there a way to change the colormap of an RGB image in matplotlib from hsv to say twilight?
If I have an array that is x,y,3 from 0 to 255, it gives a normal RGB image. Is this somehow changable to say colorscheme from the twilight cmap? As a way to make the picture work for colorblind people.
Suppose I have got a black an white image, how do I convert the colour intensity at each point into a numerical value that represents its relativity intensity?
I checked somewhere on the web and found the following:
Intensity = np.asarray(PIL.Image.open('test.jpg'))
What's the difference between asarray and array?
Besides, the shape of the array Intensity is '181L, 187L, 3L'. The size of the image test.jpg is 181x187, so what does the extra '3' represent?
And are there any other better ways of extracting the colour intensity of an image?
thank you.
The image is being opened as a color image, not as a black and white one. The shape is 181x187x3 because of that: the 3 is there because each pixel is an RGB value. Quite often images in black and white are actually stored in an RGB format. For an image image, if np.all(image[:,:,0]==image[:,:,1]) and so on, then you can just choose to use any of them (eg, image[:,:,0]). Alternatively, you could take the mean with np.mean(image,axis=2).
Note too that the range of values will depend on the format, and so depending upon what you mean by color intensity, you may need to normalize them. In the case of a jpeg, they are probably uint8s, so you may want image[:,:,0].astype('float')/255 or something similar.