Reputation: 11
I have to determine if an image is monochromatic. I mean by monochromatic not only Black and white.. it could be Sepia, like Red or blue shaded, or even mixed Red and blue shaded a.s.o (mono color scaled) ?
I think we can say that the scale goes from black (0,0,0) to White (255,255,255) bu it is not linear.. it's a specific curve on each color channel
I hope I am clear :)
Upvotes: 1
Views: 1661
Reputation: 207520
If you think of a greyscale image such as this:
all the RGB triplets present in the image will be on, or near, the straight line joining RGB[0,0,0] i.e. black to RGB[255,255,255] i.e. white in the RGB colour cube:
And that is the case with all monochromatic images - all the RGB triplets will occur near to a straight line in the RGB colour cube. In a cyanotype the straight line will pass through dark blue and light blue. In a sepia image the line will pass through brown and light brown, and in a red-blue duotone the straight line will join the red and blue points within the RGB cube.
Let's look at some images and their scatterplots...
greyscale
cyanotype
duotone
sepia
I think a technique that may work for you is to fit a straight line to the point-cloud in the RGB colour-cube of your image and then look at the least squares error and if that is small, the points lie on a line and your image is monochromatic. I think that line is called the "3D Orthogonal Distance Regression (ODR) line" - see here.
I have attempted the maths now. Basically, I believe I can compute the SVD of the triplets and get the variances contained within each of the 3 Principal Components. If all the RGB triplets lie on a straight line, then all the variance will be along that line, in the first Principal Component and it will be 100% and the second and third components will be zero. If the RGB triplets lie largely in the first component with a smaller percentage in the second and none in the third that would mean they fall largely on a single line and only tend to stray in a single perpendicular direction from that line so the point cloud will look like a long flat ellipse. If the second and third components are reasonably large, the point cloud is 3-d cigar shaped. If the first component does not contain a very significant percentage of the variance, the RGB triplets do not fall on a straight line.
#!/usr/local/bin/python3
import sys
import numpy as np
from skimage import io
from skimage.transform import resize
if len(sys.argv) != 2:
sys.exit("Usage: mono.py filename")
path = sys.argv[1]
im = io.imread(path)
# Down-res image to make SVD time reasonable
im = resize(im,(128,128))
# Form list of all RGB triplets present in image
triplets = im.reshape(-1,3)
# Get mean on all axes
means = triplets.mean(axis=0)
# Calculate SVD
uu, dd, vv = np.linalg.svd(triplets - means)
# dd holds the variance in each of the PCA directions
# The key factor is what percentage of the variance is held in the first direction
PC1var = dd[0]*100./dd.sum()
PC2var = dd[1]*100./dd.sum()
PC3var = dd[2]*100./dd.sum()
print(f"PC1 variance: {PC1var}")
print(f"PC2 variance: {PC2var}")
print(f"PC3 variance: {PC3var}")
Running the above code against my test images gives results of 90+% and gives values around 60% for normal, non-monochromatic photos. Please do some tests before putting this into production!!!
For my own reference as much as anything, I extracted the triplets into CSV files like this:
#!/usr/local/bin/python3
import numpy as np
from skimage import io
images = ["greyscale","tintype", "sepia", "duotone", "cyanotype"]
for i in images:
# Load image
im = io.imread(i + ".jpg")
# Form list of all RGB triplets
triplets = im.reshape(-1,3)
with open(i + ".dat",'w') as f:
for t in triplets:
f.write(f"{t[0]} {t[1]} {t[2]}\n")
And I did the 3-d scatterplots with gnuplot like this:
#!/usr/bin/env gnuplot --persist
set xrange [0:255]
set yrange [0:255]
set zrange [0:255]
set ticslevel 0
splot "cyanotype.dat" u 1:2:3 with points
Keywords: Python, image processing, monochromatic, cyanotype, tintype, duotone, greyscale, Gnuplot, splot, 3D, 3-d, triplets, cloud. point cloud, RGB colour-cube.
Upvotes: 10