Plotting HSV channel histograms from a BGR image Opencv

3.2k Views Asked by At

I have B,G,R histograms that look like the following: Image Histogram for B channel of an image

Description: On the X axis, I have the values from 0-255, that each pixel ranges from, and on Y axis, I have the number of pixels that have that particular X value.
My code for the same is:

hist1 = cv2.calcHist([image],[0],None,[256],[0,256])
plt.plot(hist1, color='b')
plt.xlabel("Value (blue)")
plt.ylabel("Number of pixels")
plt.title('Image Histogram For Blue Channel')
plt.show()

My question is, that I need to get the same plot - X axis with values, and Y axis with number of pixels, for HSV channels. Basically, instead of B, G, and R plots, I need the same histogram, but one that gets H, S, I.

I got the following code:

img2 = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = img2[:,:,0], img2[:,:,1], img2[:,:,2]
hist_h = cv2.calcHist([h],[0],None,[256],[0,256])
#hist_s = cv2.calcHist([s],[0],None,[256],[0,256])
#hist_v = cv2.calcHist([v],[0],None,[256],[0,256])
plt.plot(hist_h, color='r', label="hue")

Which gives me the following plot: Hue plot for an image

But from what I've read so far, BGR and HSV are different color spaces. So, I want to know, that when I'm using the calcHist function after converting to HSV, and then splitting into three channels, those channels by default are H,S and V? It's not that they're actually only BGR, but just simply mislabelled H, S and V? I just want to verify how both the methods are practically the same, but BGR and HSV are different color spaces.

Edit: Here's the source image Image

1

There are 1 best solutions below

4
Mark Setchell On

Most likely you have a synthetic image with nothing in the red and green channels and some random data centred on 128 in the blue channel.

When you go to HSV colourspace, all the hues are centred on 110 which corresponds to 220 degrees which is blue in the regular 0..360 HSV range. Remember OpenCV uses a range of 0..180 for Hue when using uint8 so that it fits in uint8's range of 0..255. So you effectively need to multiply the 110 you see in your Hue histogram by 2... making 220 which is blue.

See bottom part of this figure.


As you seem so uncertain of your plotting, I made histograms of the HSV channels for you below. I used a different tool to generate them, but don't let that bother you - in fact confirmation from a different tool is always a good sign.

First, here are the Hue (left), Saturation (centre) and Value (right) channels side-by-side:

enter image description here


Now the Hue histogram:

enter image description here

This tells you all the hues in the image are similar - i.e. various shades of blue.


Now the Saturation histogram:

enter image description here

This tells you that the colours in the image are generally low-to-medium saturated with no really vivid colours.


And finally, the Value histogram:

enter image description here

This tells you the image is generally mid-brightness, with no dark shadows and a small peak of brighter areas on the right of the histogram corresponding to where the white parts are in the original.