I have an image in grayscale and colored form,and
I want to know the pixel grayscale equation?
so I trace the same pixels on both images
red=119 green=198 blue=122
red=169 green=169 blue=169
red=0 green=133 blue=184
red=119 green=119 blue=119
red=119 green=74 blue=180
red=94 green=94 blue=94
what is the equation?
The following equation brings the same results (round to the nearest integer) :
gray = 0.1313*r + 0.6781*g + 0.1566*b;
(used this site for solving the 3 unknown equation as suggested in Nikita's comment)
"Grayscale: Converting color to grayscale"
Note that the 0.299, 0.587 and 0.114 are absolutes for each colors weight as they all have different luminance. In simple terms, green is lighter than red and blue where blue is the darkest of three.
More info can be found here.
Related
I'm trying to generate RGB colors with the same perceived brightness.
The function R*0.2126+ G*0.7152+ B*0.0722 is said to calculate the perceived brightness (or equivalent grayscale color) for a given an RGB color.
Assuming we use the interval [0,1] for all RGB values, we can calculate the following:
yellow = RGB(1,1,0) => brightness=0.9278
blue = RGB(0,0,1) => brightness=0.0722
So, in order to make the yellow tone just as dim as the blue one i can simply perform this simple calculation on yellow for each of the RGB components:
dim_yellow = yellow * 0.0722 / 0.9278
However, when doing the opposite thing, thus "scaling" up the blue color to the same perceived brightness as the original yellow, the B component obviously exceeds 1, which cannot be displayed on a computer screen.
I guess the missing brightness from the excess B component could be "redistributed" to the R and G components, faking a brighter blue color. So what is the best general method to calculate those final RGB values?
THESE AREN'T THE MATHS YOU'RE LOOKING FOR
The function R*0.2126+ G*0.7152+ B*0.0722 is said to calculate the perceived brightness (or equivalent grayscale color) for a given an RGB color.
No this is incorrect, or at least incomplete. Yes, R*0.2126+ G*0.7152+ B*0.0722 are the spectral coefficients, but that is not the complete story.
First, Don't use the term brightness in this context. Brightness is not a measure of light, it is a perception, not a measurable quantity. When we are talking about light and colorimetry, use the term "luminance" (L or Y). Luminance is a linear measure of light, not perception.
Perceptual lightness, or L* (Lstar) from CIELAB, is based on human perception of changes in luminance. It is close to a power curve of about 0.43.
sRGB, the colorspace typically used for computer monitors and the web, is not linear like light, and it is also not exactly like the perceptual L* curve. sRGB's transfer curve is close to a 1/2.2 power curve. That is, the sRGB data/signal is raised to the power of 0.455, and then the monitor applies a power of 2.2.
WHAT'S BROKEN
Your math isn't working because you are not taking the transfer curves into account. You must linearize the sRGB values before applying the coefficients. Then the sum of these will equal a luminance of 1.
#FFFF00 in sRGB equals 0.9278 in luminance, but this is an sRGB value of 96.76% or an L* value of 97.14%
#0000FF in sRGB equals 0.0722 in luminance, but this is an sRGB value of 29.79% or an L* value of 32.3%
Here's a chart of some values, expanding on your example:
So to answer the rest of your question, to get a blue that matches a higher luminance than the monitor is capable of requires desaturating it, adding R and G to increase the lightness.
In this chart, we have the fully saturated but darker red and green to match the 7% blue luminance, then we have 18% luminance (as in an 18% grey card), and here we have to desaturate the blue to bring the luminance value up.
HOW TO CALC
First, you need to linearize the sRGB components, and THEN apply the coefficients, if you need to determine luminance. If you come up with some values doing math on linearized components, then you need to re-gamma encode to get back to sRGB.
I've discussed this is several other answers, such as this here.
I recommend you to use HSV color model instead of RGB since you can easily achive what you want only modifying Value(Brightness) component.
The wiki page also contains how to convert RGB to HSV and back
EDIT:
Try to use CIELAB color space since it approximate human's vision
I am having one image with illumination gradient. I need to do illumination correction before the thresholding. Is there any easy way to do the illumination correction in R or any easy maths? EBImage package doesn't have functionality for this.
One method is called flatfield correction. Basically, you multiply your image by :
correctionMatrix = mean(flatfieldImage) / flatFieldImage
where flatfield is an image with only the background (your gradient) and mean(flatfield) is the mean of your flatfield image (a scalar). If you do the element-wise division, correctionMatrix will be lower than 1 for high intensity background, and over 1 for lower intensity background. The multiplication between correctionMatrix and your image will have a fairly uniform background, and thresholding should work.
If you don't have access to a background image (your gradient only), then you can smooth your image enough to get only the gradient. It's less precise, but should work also.
A color can be represented as mixture of Red,Green and Blue.
Ex: (255,51,153)=pink
Is there an any good formula to get distinct colors by changing one variable?
such as (10x,22x,2x^2). So when x=1,2,3,4,.... It will give separate colors like Red,Green,Cyan,Blue.....etc.
Perhaps you'd be more interested in using HSL/HSV colors. Define the saturation and lightness and adjust the hue to get different colors. Check out the HSL and HSV wiki to learn more. A 15 to 30 degree adjustment of hue will result in a distinctly different color without messing with saturation or lightness.
An example of hsl in CSS is as follows.
<h1 style="color:hsl(0,50%,100%);">HSL Test</h1> //this will be red
The first value at 0 is red and advancing by 120 degrees will bring you to green and another 120 will bring you to blue and the last 120 will bring you back to red since the degree system is based on the 360 degrees of a circle. So 0 and 360 are the same just 60 & 420. The next two values are percentage based from 0% to 100% to define the intensity of that property. They're hard to explain so I made a quick fiddle that demonstrates this.
So to answer your question there is a good formula to adjust color it just depends on how exactly you want to change it. In the RGB world you can make things darker by lowering values uniformly and the opposite by heightening them. You can increase the different color presences by adjusting the individual color values as expected. However if you're trying to cycle the entire color wheel then this is difficult (although entirely possible) using RGB values. The real lesson to take away is that there are a number of ways to define a specific color and with each one different ways to traverse the spectrum. HSL and HSLA are very intuitive for many people since it's values don't really have to be guessed at. Pick a specific hue off the color wheel, Remember ROYGBIV as you imagine a value from 0-359. Define a saturation based on how bold you want the color to be and then a lightness based on how bright. It's far more useful then RGB in the large majority of cases as you'll see in that fiddle. Making a subset of the entire color spectrum with javascript only takes a few lines of code.
There is a similar question here
This javascript library can help you Name the Color Javascript Lib
A Demo of the library
Using only CSS, can a quadrilateral with an inner angle that is greater than 180 degrees be created by manipulating a single rectangle? I know that an arbitrary convex quadrilateral can be created from a standard rectangle using CSS3 transformations.
I have been able to create concave polygons using multiple rectangles in several different ways (sometimes with the help of hiding overflow); some combination of:
Adjacent rectangles. This is a problem because visual discrepancies occur at the seams due to anti-aliasing, which is more obvious with a high-contrast background. The effect can be particularly bad when used in conjunction with a rotation (other than a "nice" rotation like 45 degrees). The rectangles also have a maddening tendency to be oddly aligned at various levels of zoom.
Overlapping rectangles, whereby the quadrilateral is composed of the union of the rectangles (the color of each rectangle is the color of the quadrilateral). This is a problem when the color of the quadrilateral uses an alpha channel, because the overlapping area appears darker.
Overlapping rectangles, whereby the quadrilateral is composed of the difference of the rectangles (the color of at least one rectangle is the color of the background). This is a problem when simulating a shadow by drawing the same shape at an offset, because the overlapping area of the foreground "erases" any underlying shadow.
[EDIT] An example of a concave quadrilateral (a kind of "Star Trek" symbol) using #1 and #3 above can be seen here.
I would like to have a concave quadrilateral with a simulated inset shadow (dark foreground color with alpha channel, light shadow color with alpha channel), which is why #2 and #3 above are problematic. An actual shadow seems out of the question at this point; I havent had very good experience with the shadows of tweaked elements.
So, any possibility to do this by manipulating a single rectangle? Or, is there some other way that I haven't considered?
[EDIT]
I think this is possible to a limited degree, but it's kind of a cheat: Use a single-character text whose glyph is already a concave quadrilateral in some reasonably safe font (for example, U+27A4, black rightwards arrowhead in Arial Unicode), then transform the crap out of it. This would have problems for cross-browser alignment with other elements of the page, however.
I'm pretty sure there's not, because while CSS relies on matrix transforms, it's not a free coordinate transform - the box coordinates are contrained via reflections:
If we have a rectangle (p1,p2,p3,p4) with p1 opposite p3 and p2 opposite p4, then the CSS representation of this rectangle is an a shape defined using only three points: p1, p2, p3 and then implied point p4 that is always computed as {p2 reflected over the midpoint of line p1-p3}. Any manipulation of the three real coordinates for the rectangle will lead to a change in the fourth, implied coordinate.
This makes it impossible to get a concave quadrilateral.
How to compute similarity between two colors in RGBA color space? (where the background color is unknown of course)
I need to remap an RGBA image to a palette of RGBA colors by finding the best palette entry for each pixel in the image*.
In the RGB color space the most similar color can be assumed to be the one with the smallest euclidean distance. However, this approach doesn't work in RGBA, e.g., Euclidean distance from rgba(0,0,0,0) to rgba(0,0,0,50%) is smaller than to rgba(100%,100%,100%,1%), but the latter looks much better.
I'm using premultiplied RGBA color space:
r = r×a
g = g×a
b = b×a
and I've tried this formula (edit: See the answer below for better formula):
Δr² + Δg² + Δb² + 3 × Δa²
but it doesn't look optimal — in images with semitransparent gradients it finds wrong colors that cause discontinuities/sharp edges. Linear proportions between opaque colors and alpha seem fishy.
What's the optimal formula?
*) for simplicity of this question I'm ignoring error diffusion, gamma and psychovisual color spaces.
Slightly related: if you want to find nearest color in this non-Euclidean RGBA space, vp-trees are the best.
Finally, I've found it! After thorough testing and experimentation my conclusions are:
The correct way is to calculate maximum possible difference between the two colors.
Formulas with any kind of estimated average/typical difference had room for discontinuities.
I was unable to find a working formula that calculates the distance without blending RGBA colors with some backgrounds.
There is no need to take every possible background color into account. It can be simplified down to blending maximum and minimum separately for each of R/G/B channels:
blend the channel in both colors with channel=0 as the background, measure squared difference
blend the channel in both colors with channel=max as the background, measure squared difference
take higher of the two.
Fortunately blending with "white" and "black" is trivial when you use premultiplied alpha.
The complete formula for premultiplied alpha color space is:
rgb *= a // colors must be premultiplied
max((r₁-r₂)², (r₁-r₂ - a₁+a₂)²) +
max((g₁-g₂)², (g₁-g₂ - a₁+a₂)²) +
max((b₁-b₂)², (b₁-b₂ - a₁+a₂)²)
C Source including SSE2 implementation.
Several principles:
When two colors have same alpha, rgbaDistance = rgbDistance * ( alpha / 255). Compatible with RGB color distance algorithm when both alpha are 255.
All Colors with very low alpha are similar.
The rgbaDistance between two colors with same RGB is linearly dependent on delta Alpha.
double DistanceSquared(Color a, Color b)
{
int deltaR = a.R - b.R;
int deltaG = a.G - b.G;
int deltaB = a.B - b.B;
int deltaAlpha = a.A - b.A;
double rgbDistanceSquared = (deltaR * deltaR + deltaG * deltaG + deltaB * deltaB) / 3.0;
return deltaAlpha * deltaAlpha / 2.0 + rgbDistanceSquared * a.A * b.A / (255 * 255);
}
My idea is integrating once over all possible background colors and averaging the square error.
i.e. for each component calculate(using red channel as example here)
Integral from 0 to 1 ((r1*a1+rB*(1-a1))-(r2*a2+rB*(1-a2)))^2*drB
which if I calculated correctly evaluates to:
dA=a1-a2
dRA=r1*a1-r2*a2
errorR=dRA^2+dA*dRA+dA^2/3
And then sum these over R, G and B.
First of all, a very interesting problem :)
I don't have a full solution (at least not yet), but there are 2 obvious extreme cases we should consider:
When Δa==0 the problem is similiar to RGB space
When Δa==1 the problem is only on the alpha 1-dim space
So the formula (which is very similar to the one you stated) that would satisfy that is:
(Δr² + Δg² + Δb²) × (1-(1-Δa)²) + Δa² or (Δr² + Δg² + Δb²) × (1-Δa²) + Δa²
In any case, it would probably be something like (Δr² + Δg² + Δb²) × f(Δa) + Δa²
If I were you, I would try to simulate it with various RGBA pairs and various background colors to find the best f(Δa) function. Not very mathematic, but will give you a close enough answer
I've never done it, but theory and practice say that converting the RGB values in the image and the palette to luminance–chrominance will help you find the best matches. I'd leave the alpha channel alone, as transparency should have little to nothing to do with the 'looking better' part.
This xmass I made some photomosaics for presents using open-source software that matches fragments of the original image to a collection of images. That seems like a harder problem than the one you're trying to solve. One of them programs was metapixel.
Lastly, the best option should be to use an existing library to convert the image to a format, like PNG, in which you can control the palette.