Kadir Beytorun
Kadir Beytorun

Reputation: 43

Determine if certain parts of an RGB image are colored or grayscale using numpy

I am trying to determine if certain parts of an RGB image are colored or grayscale, using python, opencv and numpy libraries. To be more spesific, in an RGB image I determine face locations using neural networks and when that image contains printed photos I would like to find out if the face location in that image is grayscale or colored.

an example picture for the task mentioned earlier

What I tried so far:

            red_average = np.average(rgb_image_crop[:,:,0])
            green_average = np.average(rgb_image_crop[:,:,1])
            blue_average = np.average(rgb_image_crop[:,:,2])

            highest_distance = max(abs(red_average-green_average), abs(red_average-blue_average), abs(green_average-blue_average))
            if highest_distance> 15:
                print("this crop is colored")
            else:
                print("this crop is grayscale")

After finding the location of faces, faces are cropped and named "rgb_image_crop". I basically split the R, G, B channels using numpy and took their averages separately. My logic was that grayscale images would have R, G, B pixel values close to each other compared to colored images and this method worked with average performance.

But I was wondering is there a more sophisticated approach than this with higher success hopefully? I looked through other questions, but everyone was just asking to determine if an image file is B/W or RGB.

Edit after concluding the results: I have tried various methods in computer vision and then tried training CNN classifier using a dataset I created. Apparently CNN networks cannot learn colors much but mostly they learn textures and results were really disappointing. I trained a Darknet YOLOV4 based classifier and tests with real life examples failed to give satisfactory outcomes. Mark's suggestion has been the most stable one and after that the one I mentioned in my question. I will try to implement Mark's solution using hardware acceleration and make it use less CPU resources.

Upvotes: 3

Views: 362

Answers (2)

Mark Setchell
Mark Setchell

Reputation: 207465

You can use Numpy peak-to-peak across the 3rd dimension to get difference between smallest and largest RGB value at each pixel location. Then threshold that and count the outliers:

RGBrange = np.ptp(im, axis=2)
coloured = RGBrange > 10

You might also get some ideas here.

Upvotes: 4

halilbeytorun
halilbeytorun

Reputation: 61

How about finding the max difference in every pixel of the cropped image and then taking the STD of them. With the gray scaled image, that value must be small compared with colored ones.

Upvotes: 1

Related Questions