Consider 2 or more boxes that look to be the "same" colour, but with different transparencies:
In this example, the left div is rgba(200,200,200,0.8), and the right rgba(150,150,150,0.4). The second row has a red bar behind them to show that their transparencies are different.
I know the left and right divs do not look the same (the left div looks slightly darker). My question is how can I make them so:
Given a colour (r1, g1, b1, a1), how can I work out another "colour" (r2, g2, b2, a2) such that a1 != a2 and the two colours look the "same".
Here's the fiddle I used to generate the above picture: jsfiddle
At the moment, I simply pick some r2, g2, and b2, then fiddle around with a2 until the two colours look similar enough. But there should be a relation between colours and their transparencies that we can use to work this out precisely and for any given colour.
Have a look at this link : https://viget.com/inspire/equating-color-and-transparency.
I hope it will be what you're looking for.
Edit:
Here is an example of application of the formula given in the link above, based on the case you describe in your post, so you can better understand how to use it.
Here is the formula given in the link. I just changed the name of the variables to make them more explicit ("overlay" became "initialValue", "target" became "finalValue"):
finalValue = opacity x initialValue + (1 - opacity) x background
From this, I can deduce the following formula :
opacity = (background - finalValue) / (background - initialValue)
So, back to your example case, the first formula applied to your left div gives a finalValue of :
finalValue = 0.8 x 200 + 0.2 x 255 = 211
So, the objective for your right div is to calculate the opacity necessary to match this final value, from the initial value of 150 :
opacity = (255 - 211) / (255 - 150) = 0.419
If you try rgba(150, 150, 150, 0.419) on your right div, you will see that the final color is the same.
Related
I'd like to convert this graded colored map into a matrix in which to each pixel a percentage of orange is assigned. In particular, taking the color palette of orange at the right of image.
I'd like to assign 100% to the brightest orange at the top and 0% to the black at the bottom. Hence, I'd like to assign to each pixel a percentage, based on the color of that single pixel in relation to the palette.
Finally, my goal consists of averaging these percentages in order to get a sort of mean percentage of orange. For the latter step, I shouldn't have any issue... but I've no idea how to face the former problem.
I am looking for a solution either in R, Matlab or Mathematica
Here's an idea that I had. Suppose you have an image with arbitrary colors; let's solve for a transformation that reduces your color from 3-dimensional space to a single dimension by running an optimizer. The cost function is derived from the error when the original colors are attempted to be recovered by the lossy color transformation.
See the image below for my result, scaled to 100% at the brightest pixel and 0% at the darkest.
img = imread('zpiaD.png');
opt = optimset('Display', 'Iter');
itf = fminsearch(#(itf) min_colormap(img, itf) , zeros(1,3), opt);
[~, rimg] = min_colormap(img, itf);
subplot(2,1,1), imshow(rimg), title 'single color dimension'
subplot(2,1,2)
rimg = double(rimg);
imagesc(100 * (rimg - min(min(rimg))) / (max(max(rimg)) - min(min(rimg)))),
colorbar, title 'scaled'
function [res, timg] = min_colormap(img, itf)
pimg = double(reshape(img, size(img,1)*size(img,2), size(img,3)));
timg = transpose(itf * pimg');
res = sum(((timg * itf) - pimg).^2, 'all');
timg = cast(reshape(timg, size(img,1), size(img,2)), 'uint8');
end
I'm looking for a formula to calculate the RGB of a new color, based on the opacity. Of course, there's already an answer for this (i.e. Calculating opacity value mathematically), especially this answer:
The formula for combining C1 = (R1,G1,B1) and C2 = (R2,G2,B2) into a new color C3, where C2 is overlayed on top of C1 with opacity p is usually ( (1-p)R1 + p*R2, (1-p)*G1 + p*G2, (1-p)*B1 + p*B2 ).
This is great, it works, I get the correct value. However, I need a reliable source for this formula, which I cannot find. Sure, that answer has an link to Wikipedia, which again lacks the source.
If there's any other formula for calculating the color based on the opacity value mathematically and there's a reliable source for such a formula (e.g. book or scientific paper), feel free to share it.
Thanks!
Thanks to anyone who helped. I actually found the answer in this link: http://jcgt.org/published/0004/02/03/paper.pdf
It's a (semi)scientific paper, and the formula is as follows:
Aα * Ac + (1−Aα)*Bα*Bc / Aα + (1−Aα)*Bα
I've tested it on this scenarios:
rgb_div = (80, 85, 250); opacity = 0.2
rgb_bg = (100, 205, 30); opacity = 1
new color = (96, 181, 74)
How would one go about calculating the angle of a vector versus an "up" direction while looking down the axis of another vector? To illustrate what I'm asking, I've drawn two diagrams:
http://i.imgur.com/0JUb8uA.jpg
In this image, you can see the general setup. The green arrows are the Y axis (up is positive, down is negative), the red arrows are the X axis (left is negative, right is positive), and the blue arrows are the Z axis (towards the screen is positive, away is negative).
The cyan and yellow arrows represent two normalized vectors (length = 1) centred around 0, 0, 0. The vectors can be anywhere in 3D space, I'm just using this as an example- the only thing guaranteed is that their length will always be 1 and the up direction will always be Vector(0, 1, 0).
http://i.imgur.com/rdlEesZ.jpg
This is what I'm trying to figure out. I've oriented the camera so it points directly down the cyan arrow. I'm attempting to calculate the angle between the yellow arrow and the green (Y) axis while looking down the line specified by the cyan arrow.
I'm having troubles researching this on my own probably because I lack the vocabulary to adequately define my question (hence the diagrams). It seems like it might be possible to determine a rotation between the cyan arrow and a known axis, then rotate everything (including the yellow arrow) around the origin, at which point it's just a matter of using atan2() to determine the angle based on two coordinates of the yellow vector (ignoring the depth component), but I'm guessing there's probably a simpler way of doing things. What, if anything, might that be?
If you have two vectors v=(v1, v2, v3) and w=(w1, w2, w3), then their dot product is v · w = v1 · w1 + v2 · w2 + v3 · w3. However another expression for their dot product is v · w = |v| |w| cos a, where |v| and |w| are the lengths of the two vectors, and a is the angle between them.
If you're representing these vectors as components (that is, the (v1, v2, v3)), then it's easy to calculate both their dot product and their respective lengths. Then cos a = v · w / (|v| |w|), and take arccos of that.
Working out rotations that would take one into the other is the hard way of doing this.
This is similar to various questions including 1 and 2, but I think they make it sound more complicated than it is.
I've always wondered the easiest way to figure out whether or not a point lies within a triangle, or in this instance, a rectangle cut into half diagonally.
Let's say I have a rectangle that is 64x64 pixels. With this rectangle, I want to return a TRUE value if a passed point is within the upper-left corner of the rectangle, and FALSE if it isn't.
-----
| /|
| / |
|<__|
Horray for bad ASCII art.
Anyway, the hypothetical points for this triangle that would return TRUE would be (0,0) and (63,0) and (0, 63). If a point lands on a line (e.g., 50,0) it would return TRUE as well.
Assuming 0,0 is in the upper-left corner and increases downwards...
I've had a possible solution in my head, but it seems more complicated than it should be - taking the passed Y value, determining where it would be in the rectangle, and figuring out manually where the line would cut at that Y value. E.g, a passed Y value of 16 would be quarter height of the rectangle. And thus, depending on what side you were checking (left or right), the line would either be at 16px or 48px, depending on the direction of the line. In the example above, since we're testing the upper-left corner, at 16px height, the line would be at 48px width
There has to be a better way.
EDIT:
The rectangle could also look like this as well
-----
|\ |
| \ |
|__>|
But I'm figuring in most cases the current answers already provided should still hold up...
Top-left/bottom-right triangles: For all points in the top-left triangle, x+y<=64. Points in the bottom-right triangle have x+y>64.
(for a rectangle of size (w,h) use w*y+h*x-w*h<0)
Top-right/bottom-left triangles: For all points in the bottom-left triangle, x<=y. Points in the top-right triangle have x>y.
(for a rectangle of size (w,h) use h*x-w*y<0)
How did we get there?
For a rectangle of dimensions (w,h) and TL/BR triangles, the equation of the diagonal is (try it out! assign x=0 and check that you get y==h, and assign y=0 and check that x==w)
h*x + w*y - w*h = 0
Points on one side of that line will have
h*x + w*y - w*h > 0
While points on the other will have
h*x + w*y - w*h < 0
Inserting 64 for both w and h, we get:
64x + 64y - 64*64 < 0
Dividing by 64 gets us:
x+y < 64
For TR/BL triangles, the line equation and the resulting inequalities are:
h*x - w*y = 0
h*x - w*y < 0
h*x - w*y > 0
Inserting 64 for w and h, we get
64x-64y < 0
=> x<y
you can represent the triangle with three affine functions
take the unit triangle with corners at (0, 0), (1, 0) and (1, 1). the sides are represented by the three lines
y = 0
x = 1
y = x
So the interior and boundry of the triangle are given as the intersection of the sets
x >= 1
y >= 0
y <= x
so given a point, (x, y), you just need to verify that it satisfies those three inequalities.
You can of course generalize this to any triangle using the fact that any affine function (representing a line) can be written in the form y = mx + b.
The equation for the line looks like this :
y = mx + b
So, if you insert your x and y-Values into that equation, it will probably not hold anymore. Let's reformulate it:
mx + b - y = 0
Same thing, different look. Again, the result is probably not zero. But, the result will now tell you whether it's on the one side of the line or the other.
Now you just have to find out whether the point is inside your rectangle.
Lets assume your right angled triangle has one corner at 0,0 and the diagonal corner at a,b.
So y=mx+c c=0 as we start at the origin.
m=b/a
So y=bx/a
To know which half of the triangle your point (c,d) falls in
if (d<=(bc/a)) {//point is in bottom half}
if (d>(bc/a)) {//point is in top half}
I think...
A simple option is to use a ray casting algorithm. Whilst perhaps a little overkill for what you need, it does have the advantage that it will work with more complex triangles and polygons.
Loosely, the algorithm takes an imaginary point in a direction (infinitely off to the left, for example) and casts a ray to your test point; you then calculate whether each line of your triangle crosses that infinitely long line. If you get an odd number of crossings, your point is inside your triangle; even and you're out of your triangle
2 colors are mixed together. If i have the RGB for the resultant color and RGB for one of the colors mixed, then somehow i could calculate the 2nd color?
I will try to explain visually what i am trying to say. Here is a flickr link
http://www.flickr.com/photos/48150615#N08/4407414157
I know that the circle in the middle has an opacity of 20%
Is there any way to know the color value of the circle so that i can deduct that to get the same color value as the background color.
if i understood the task correctly...
let's do some school math
c is color of initial image, t is color of transparent color, a (for alpha) is transparency, c' is result color.
c' = (1 - a) * t + a * c
you want to find c.
c = (c' - (1 - a) * t) / a
you need to know a, t and c'
Firstly it depends how you're going to mix them. That is, you could average the RGB components (this means blue (0,0,255) + yellow (255,255,0) == grey (128,128,128)), or you could work on Hues, Saturation and Value, which often gives a much more "as expected" result.
Anyway, in either case, it's some simple maths:
if the way to get the average is C3 = (C1 + C2) / 2
then the way to find C2 is C2 = (C3 * 2) - C1
CIELAB color space is specially designed for calculating differences between colors, but it might be a overkill in you case. Probably HSV is easy solution for you.
Just subtract each component. The components are often stored in hexadecimal format, in which case you will need to convert the numbers to decimal or do hex math.