I have some JPG files and want to automatically determine which are black & white. They are all encoded in RGB.
How can I do this using commandline tools?
Photography Stack Exchange is a question and answer site for professional, enthusiast and amateur photographers. It only takes a minute to sign up.Sign up to join this community
You could start by
converting the image to grayscale and
compareing that to the original image. If the image is already black and white, you'd expect the two images to be very similar; if it's full color, you'd expect them to be different.
Clarification: Given the two comments below, I think I wasn't clear enough here. Certainly, the grayscale version of a B&W image stored as RGB will likely not be exactly the same as the original image, but it should be pretty close. Subtracting the grayscale version from the original will yield a dark frame with a faint ghost of the original image. You could threshold this image to get a completely black frame. A full color image, on the other hand, will be significantly different from its grayscale counterpart, and subtracting the latter from the former will give an image that still has a lot of color even after thresholding (exactly what colors depends on how the grayscale conversion is done).
Another option: Thinking about the problem some more, another option is to convert the image to a neutral white point and then compare the red, green, and blue channels. In a color image, these will have significant differences; in a black and white image, they should be very similar. Again, they might not be exactly the same, depending on how the image was acquired in the first place, but the differences should be small enough that they can be easily filtered out. This is effectively the same idea as the one above, but the approach is perhaps more straightforward.
Building on Romeo's answer:
You can use imagemagick to convert to HSV color space and get statistics on the color distribution.
HSV means Hue, Saturation, Value
For a true grayscale image, saturation must be constantly zero.
You can use the following command:
identify -colorspace HSL -verbose <infile>
and obtain something like the following for a true grayscale image (among other output)
Red: min: 0 (0) max: 0 (0) mean: 0 (0) standard deviation: 0 (0) kurtosis: 0 skewness: 0 Green: min: 0 (0) max: 0 (0) mean: 0 (0) standard deviation: 0 (0) kurtosis: 0 skewness: 0 Blue: min: 1 (0.00392157) max: 255 (1) mean: 116.501 (0.456867) standard deviation: 102.305 (0.401195) kurtosis: -1.82316 skewness: 0.0719237
Apparently Imagemagick does not care to change the name of the components from red, green, blue to HSV , but the mapping is accordingly. Take a note of the Green/Saturation channel, it has to have a max of 0, then you have grayscale.
For non-ideal input images, and for Sepia-like mono-chromatic images I would probably simply look into small variance of hue. Also this might still fail, as unsaturated colors may have any hue value without changing much.
With imagemagic you can use command identify to get info about the image
identify -verbose image.jpg
From the output you can check for standard deviation of red, blue and green. For grayscale images the should have very close values (theoretically equivalent values)
P.S. You can check also this site for some scripts for such tests