From an image, how do I determine the shade? - database

For a database app I'm trying to determine the average shade of a section of photo, against a colour scale.
Being a novice I'm finding this very difficult to explain so I've created a simple diagram showing exactly what I'm trying to achieve.
http://www.knockyoursocksoff.com/shade/
If anybody has the time to give me some ideas I'd be very grateful.
Best wishes,
Warren.

If you are using color photos, you should first convert the selected area from RBG (red, green, blue) to HSL/HSV (article).
HSL stands for "hue, saturation, lightness".1 The number you are interested in is the lightness.
In the most general terms, the lightness refers to how you perceive the brightness of a colored surface. It's hard to use the red/green/blue components to say whether a patch of red is brighter/darker than, say, a patch of blue. Converting to HSL takes care of that problem.
Once you have done the conversion, you can simply average the lightness values of your selected area.
Quick note on lightness values: Technically, you can't simply average the lightness values because the perception of lightness is not linear (article). But, unless you are writing a deeply scientific application, simply averaging the lightness will give you an "accurate enough" value.
1 In Adobe Photoshop, they call it HSB (hue, saturation, brightness)

I think I would start by just averaging the pixel values:
for x = start_x to end_x
for y = stary_y to end_y
total += getPixel(x,y)
shade = total / (xlen*ylen)
Its going to be more complicated if you're doing it in color.

Related

How to identify real red pixels?

I'm wirtting a program that changes all the image pixels to grayscale except for the red ones. At first, i thought it would be easier, but I'm having trouble trying to find the best way to determine if a pixel is red or not.
The first method I tried was a formula: Green < Red/2 && Blue < Red/1.5
results:
michael jordan
goldhill
Michael Jordan's image shows some not red pixels that pass the formula, like #7F3222 and #B15432. So i tried a different method, hue >= 345 || hue <= 9, trying to limit only the red part of the color wheel.
results:
michael jordan 2
goldhill 2
Michael Jordan's image now has less not red pixels and goldhill's image has more red pixels than before but still not what I want.
My methods are incorrect or just some adjustments are missing? if they're incorrect, how can I solve this problem?
Your question "How to identify 'real' red pixels", begs the question "what a red pixel actually is, especially if it has to be 'real'".
The RGB (red, green, blue) color model is not well suited to answer that question, therefore you should use the HSV (hue, saturation, value) model.
Hue defines the color in degrees (0 - 360 degrees)
Saturation defines the intensity of the color (0 - 100 %)
Value or Brightness defines the luminosity (0 - 100 %)
Steps:
convert RGB to HSV
if the H value is not red (+/- 30 degrees, you'll have to define a threshold range of what you consider to be red, 'real' red would be 0 degrees)
set S to 0 (zero), by doing so we remove the saturation of the color, which results in a gray shade
leave the brightness (V) as it is (or play around with it and see how it effects the results)
convert HSV to RGB
Convert from RGB to HSV and vice versa:
RGB to HSV
HSV to RGB
More info on HSV:
https://en.wikipedia.org/wiki/HSL_and_HSV
"All cats are gray in the dark"
Implement a dynamic color range. Adjust the 'red' range based on the brightness and/or saturation of the current pixel. Put a weight scale (on how much they affect the range in %) on the saturation and brightness values to determine your range ... play around to achieve the best results.
You used RGB, and HSV method, which it is good, and both are ok.
The problem is about defining red. Hue (or R) is not enough: it contains many other colours (in the broader sense): browns are dark/unsaturated reds (or oranges). Pink is also a tint of red (so red + white, so unsaturated).
So in your first method, I would add a condition: R > 127 (you must check yourself a good threshold). And possibly change the other conditions with a higher ratio of R to G and B and possibly adding also the ration R to (G+B). The first new added condition is about reds (and not "dark reds/browns), and brightness. Your two conditions are about "hue" (hue is defined by the top two values), and the last condition I wrote is about saturation.
You can do in a similar way for HSV: filter H (as you did), but you must filter also V (you want just bright reds), and also an high saturation, so you must filter all channels.
You should test yourself the saturation levels. The problem is that eyes adapt quickly to colours, so some images with a lot of redish colours are seen normally (less redish) by humans, but more red by above calculation. Etc. (so usually for such works there is some sliders to modify, e.v. you can try to automatize, but you need to find overall hue and brightness of image, and possibly complex methods, see CIECAM).

changing brightness of the RGB colour

I heard that simple
R*=f;
G*=f;
B*=f;
where f is a scalar value 0 .. 1.0 or more
Is not to much proper way of changing brightnes
of the color, but i cannot find some code snippet
to obtain something better (without to much studying
of a color theory)
Could maybe someone give me such snipped here? TNX
Convert the colour to HSL or HSV, then adjust the lightness (L) or value (V). If needed, convert back to RGB.
Because 0,0,0 is black and 255,255,255 is white, (with a grayscale inbetween) your formula is indeed a very good approximation for changing the brightness of a given color value.
It is not exact in terms of perceived brightness but works well enough for most applications.
A simple conversion from RGB to Lightness is:
L = 1/3 * (R+G+B)
As you may see from this formula, f*L and your approach are identical.

shadow and shading

I have read lots of ray tracer algorithm on the web. But, I have no clear understanding of the shading and shadow. Is below pseudocode correct written according to my understanding ?
for each primitive
check for intersection
if there is one
do color be half of the background color
Ishadow = true
break
for each ambient light in environment
calculate light contribution to the color
if ( Ishadow == false )
for each point light
calculate diffuse shading
calculate reflection direction
calculate specular light
trace for reflection ray // (i)
add color returned from i after multiplied by some coefficient
trace for refraction ray // (ii)
add color returned from ii after multiplied by some coefficient
return color value calculated until this point
You should integrate your shadows with the normal ray-tracing path:
For every screen-pixel you send a ray through the scene and you eventually determine the closest object-intersection: at the point of the closest object-intersection you would at first read out the pixel color (texture of the object at that point), aside from calculating reflection-vector etc (using the normal-vector) you would now additionally cast a ray from that intersection-point to each of the light-sources in your scene: if these rays intersect other objects before hitting the light-sources then the intersection-point is in shadow and you can adapt the final color of that point accordingly.
The trouble with pseudocode is that it is easy to get "pseudo" enough that it becomes the same well of ambiguity that we are trying to avoid by getting away from natural languages. "Color be half of the background color?" The fact that this line appears before you iterate through your light sources is confusing. How can you be setting Ishadow before you iterate over light sources?
Maybe a better description would be:
given a ray in space
find nearest object with which ray intersects
for each point light
if normal at surface of intersected object points toward light (use dot product for this)
cast a ray into space from the surface toward the light
if ray intersection is closer than light* light is shadowed at this point
*If you're seeing strange artifacts in your shadows, there is a mistake that is made by every single programmer when they write their first ray tracer. Floating point (or double-precision) math is imprecise and you will frequently (about half the time) re-intersect yourself when doing a shadow trace. The explanation is a bit hard to describe without diagrams, but let me see what I can do.
If you have an intersection point on the surface of a sphere, under most circumstances, that point's representation in a floating point register is not mathematically exact. It is either slightly inside or slightly outside the sphere. If it is inside the sphere and you try to run an intersection test to a light source, the nearest intersection will be the sphere itself. The intersection distance will be very small, so you can simply reject any shadow ray intersection that is closer than, say .000001 units. If your geometry is all convex and incapable of legitimately shadowing itself, then you can simply skip testing the sphere when doing shadow tests.

Silverlight - Brush banding

Can someone tell me how to increase the number of "color bands" on a Silverlight gradient brush?
The question is marked as answered below, but it really isn't a solution to use bitmaps instead of gradient brushes as my users can modify their background dynamically. This is most obvious when full screen gradients are used.
how to make the brush smooth without lines in the middle
Unfortunately, I can only give you half an answer - the general principles on why this happens and how to avoid it. As to the implementation in SL, I can only give you some general ideas as I'm not an expert there.
Those bands result from the limited color depth of the display. To reduce the effect, the gradient has to be made slightly noisy. The simplest way to do is to calculate the color from the gradient as a floating number, and then round it to an integer in a weighted, random manner - like this:
correct_value = linear_gradient(x,y) // e.g 25.3
whole_part = round_down(correct_value) // 25
frac_part = correct_value - whole_part // 0.3
color_used = whole_part
if (true_with_probability(frac_part)):
color_used = color_used + 1 // color_used == 25 with 70% chance
// 26 with 30% chance
Here is an example of using this technique (on the left is the effect of simply rounding to the nearest integer, right is rounding with noise):
As to how to implement that in your case - I assume there would be some way to create a custom Brush object that would allow you to do the calculations per pixel, or alternatively some sort of shader functionality which could help. If those are not possible, you can also simply generate a bitmap using this logic, and use that bitmap as the brush (I believe this would be ImageBrush, but that's just from googling).
Perhaps somebody with more Silverlight knowledge can chime in and provide the best implementation in this case.

comparing bmps for brightness

I have a two bmp files of the same scene and I would like determine if one is more bright than the other.
Similarly I have a set of bmps with different contrasts and another set of bmps with different saturation.
How do I compare these images for brightness,contrast and saturation ? These test images are saved by a tool provided by the sensor manufacturer.
I am using gcc 4.5.
To compare the brightness of two images you need to compare the grey value of the pixels (yes, one by one). In the RGB colour space the brightness (grey value) is the mean of R,G and B, so you have brightness = (R+G+B) / 3
Comparing the contrast and especially the saturation will prove to be not that easy, for a start you could have a look at HSL and HSV but in general I'd suggest to get a good book on the image processing topic.
The answer of (R+G+B)/3 is really not even a good approximation of brightness (at least from what we know today)!
[BRIGHTNESS]
What you really SHOULD do is convert to another color scale and compare the brightness using that channel of a color scale that incorporates brightness into it. Look here!!!
Formula to determine brightness of RGB color
there are a great coupld of answers here that talk about conversion or RGB into luminance, etc...
[CONTRAST]
Contrast is a function of the spread of the pixel values throughout the full range of possible pixel values. One understands the contrast by putting together a histogram of all the pixels (where the x axis represents the a pixel value, and the y axis represents how many pixels are of that value), and analyzing the histogram to understand if there is good distribution throught the entire range, or not. Comparing contrast can be done many ways, but potentially a good starting point, would be to find the pixel-value center point (average of the histogram data) of each image, and potentially some histogram width parameter (where lets say the width is about the center point and is large enough to incorporate 90% of all pixels), and compare the center and width parameters of both images. This is ONLY a starting point.
[SATURATION]
To compare saturation, one might convert the image to the HSL colour space. The S in HSL stands for Saturation. Comparing saturation within this colour space becomes exactly like comparing brightness as outlined above!!!

Resources