1

I have a use case where I need to classify some images as grey scale or color. My initial step was based on the feature that grey scale images should have r,g,b values at a pixel, the same values as it is single channel. Were as for color images, r,g,b values at the same pixel may not be the same.

So I am checking by getting the difference between (r,g), (b,g) and (r,b) and if all three has only zero, its grey scale else, its color.

This approach helped me to identify many grey scale images but still there are some images which does not follow this logic. Can anyone specify some good features on which we can classify an image as color or grey scale using opencv?

Do not ask me to check the number of channels and classify, it gives 3 for both the classes as we are loading it in .jpg format.

Thanks in advance

Sreekiran A R
  • 3,123
  • 2
  • 20
  • 41

2 Answers2

1

I suspect, some never were grey-scale images after digitizing (e.g. a color scan of gray-scale picture). Due to noise, there are minimal differences in the RGB values. A low threshold greater than perfect zero should do the trick.

Please note that JPEG totally has a gray-scale option. However, when storing the picture, you request that mode. Compressors usually do not pick it up automatically. Also, you explicitly need to set the flag IMREAD_UNCHANGED while reading with OpenCV's imread.

Hermann
  • 604
  • 7
  • 23
  • IMREAD_UNCHANGED worked for normal image which I converted to grey scale and stored. But, not working for my use case. It is reading as 3 channel only. – Sreekiran A R Aug 10 '18 at 11:06
  • Can you check for the maximum difference between the elements of each pair of channels? – Hermann Aug 10 '18 at 13:27
1

With the method Suggested by @QuangHoang I got a result of 85+% accuracy. Here is the approach explained.

#test image
img=cv2.imread('test.jpg')
r,g,b=cv2.split(img)
#spliting b,g,r and getting differences between them
r_g=np.count_nonzero(abs(r-g))
r_b=np.count_nonzero(abs(r-b))
g_b=np.count_nonzero(abs(g-b))
diff_sum=float(r_g+r_b+g_b)
#finding ratio of diff_sum with respect to size of image
ratio=diff_sum/img.size
if ratio>0.005:
    label='color'
else:
    label='grey'

Thanks for all the suggestions.

Sreekiran A R
  • 3,123
  • 2
  • 20
  • 41