Comparing Pixel Values

Started by
5 comments, last by TheAdmiral 16 years, 4 months ago
Lets say I have one image of 10 pixels, and another of 1 pixel. I need to see which of the 10 pixels best matches the other image - not value wise, but how a human would see it. For example, two shades of blue. First I used: r2+toleration < r1 < r2-toleration g2+toleration < g1 < g2-toleration b2+toleration < b1 < b2-toleration Second, I used Euclidean distance on the RGB aka (r1-r2)^2+(g1-g2)^2+(b1-b2)^2 < toleration It didn't not work well - it worked pretty badly in fact. I also tried using HSB - but no luck. [So far, #1 worked the best for me - best for shades of a color, but not good enough :( ] Can anyone suggest some better ways to do it? P.S. Does anyone know how to convert HSB to 3D space?
Advertisement
Better colour-spaces exist for this kind of business. In particular, I'd recommend YCC. A weighted Euclidean distance-function in this space would give far better results than anything linear in RGB or even HSL.

The most important coordinate is luma. I couldn't say anything certain about the two chroma components, but I suspect the red is more significant than blue (at middling intensities). IIRC, the the eye is far more sensitive to intensities in the blue hue at very low exposure, green at typical-to-high exposure, with red being fairly constant. I don't really know how or if this translates to hue-sensitivity. I'm sure Google knows a lot more, but you'll probably want to take that into consideration if working in HDR. Otherwise you may have success with something along the lines of:

float3 ycc1 = RGBToYCrCb(rgb1);float3 ycc2 = RGBToYCrCb(rgb3);float3 ycc_dist = abs(ycc1 - ycc2);const float3 WEIGHTS = float3(0.814, 0.453, 0.362);float perceived_distance = dot(ycc_dist, WEIGHTS);

Understand that the weights there came entirely off the top of my head (I normalised 9:5:4), and that better values have almost certainly been researched, if you know where to look. The implementation of the RGB-YCC conversion is linear (a matrix multiplication); details here.
Ring3 Circus - Diary of a programmer, journal of a hacker.
The correct weights how the human eye percepts colors is

R = 0.3
G = 0.59
B = 0.11
Quote:Original post by FoxHunter2
The correct weights how the human eye percepts colors is

R = 0.3
G = 0.59
B = 0.11

Where did you get this from? It look suspiciously similar to the intensity weightings of the perceived RGB luminosities, which is a totally different thing.
Ring3 Circus - Diary of a programmer, journal of a hacker.
Quote:Original post by TheAdmiral
Where did you get this from? It look suspiciously similar to the intensity weightings of the perceived RGB luminosities, which is a totally different thing.


Well yes, I was actually talking about luminosities, as described here:
http://en.wikipedia.org/wiki/Grayscale

Sorry if that caused any confusion.
Quote:Original post by TheAdmiral
Better colour-spaces exist for this kind of business. In particular, I'd recommend YCC. A weighted Euclidean distance-function in this space would give far better results than anything linear in RGB or even HSL.

The most important coordinate is luma. I couldn't say anything certain about the two chroma components, but I suspect the red is more significant than blue (at middling intensities). IIRC, the the eye is far more sensitive to intensities in the blue hue at very low exposure, green at typical-to-high exposure, with red being fairly constant. I don't really know how or if this translates to hue-sensitivity. I'm sure Google knows a lot more, but you'll probably want to take that into consideration if working in HDR. Otherwise you may have success with something along the lines of:

float3 ycc1 = RGBToYCrCb(rgb1);float3 ycc2 = RGBToYCrCb(rgb3);float3 ycc_dist = abs(ycc1 - ycc2);const float3 WEIGHTS = float3(0.814, 0.453, 0.362);float perceived_distance = dot(ycc_dist, WEIGHTS);

Understand that the weights there came entirely off the top of my head (I normalised 9:5:4), and that better values have almost certainly been researched, if you know where to look. The implementation of the RGB-YCC conversion is linear (a matrix multiplication); details here.


Thank you.

Which method and color-space would be most effective for comparing gray-scale colors?
Quote:Original post by Dansas
Which method and color-space would be most effective for comparing gray-scale colors?

Well, the same algorithm would be used, but you could take the obvious short-cut that the luma is equal to any of the RGB components, and both chromas are zero. So...

float distance = abs(col1.r - col2.r);

This will give you the true lightness/luminosity distance. If you are looking for a subjective measure, perhaps of perceived luminance or intensity then you'll need to work a bit harder and have access to a lot more information, such as the display type, gamma ramps and so forth. Such accuracy will not carry from one computer to another, so it's not really viable for gaming.
Ring3 Circus - Diary of a programmer, journal of a hacker.

This topic is closed to new replies.

Advertisement