http://dribbble.com/colors/1a15a1?percent=5&variance=50
I understand the color minimum slider--you would count the color of each pixel, then create a ratio for a particular color based on the total pixels of the image (10 blue:100 total) = 10% blue.
But what's the logic behind the color variance slider? Looking at the RGB values of these colors http://en.wikipedia.org/wiki/Web_colors#X11_color_names some patterns are apparent, but imagining a sql table full of pictures and their pixel data, anyone have an idea on how to calculate variance?
I too think you are right for the color minimum. Color variance is easy too. If you select a small variance you will get images with a small count of colors used on it. Logically 0% variance must bring an image of a single color only.
I don't think you have to store pixels at all, logically for storing a new image it goes like this:
Read image file
Find how many different color there are in it
Store image path and number of different colors on it.
Then on retriving the image would go like this:
Ask the user what variance he likes
Let's say variance = 60%
Read distinct maximum numbers of colors for an image
MaxColors = 100% (let's say max=18 colors per image)
Turn 60% to integer
18 = 100%
x = 60% then
18*60=100*x then 100*x=1080 then x=10.8
Make 10.8 round so it becomes x=11
Retrieve from database all images that have 11 or more colors on them
Display these images as the result
So no need to store any pixel at all, just a single integer that indicates how many colors consist of an image.
Related
I'm having some trouble exporting the color values of a an equalized image, in order to recolor those equalized areas of grey.
$imagick = new \Imagick(realpath($imagePath));
$imagick->modulateImage(100,0,100);
$imagick->quantizeImage(
13,
Imagick::COLORSPACE_TRANSPARENT,
0,
true,
false
);
This results in a greyscale image created by 13 different luminance levels. Now, what I can't understand how to do is to export the colors of the 13 luminance levels to an array, in order to recolor them using opaquePaintImage.
Right now I'm just recoloring RGBA values, which is not as accurate as I would like.
Please also note, that I'm also interested in how to recolor a range of RGBA values. As in, recolor 230-255 to red, recolor 210-230 to orange, etc.
That would be even better, almost. Any ideas?
In ImageMagick, there is a -fuzz XX% to allow a range of values (some percent tolerance about some particular color. See the fuzz option in OpaquePaintImage at http://us3.php.net/manual/en/imagick.opaquepaintimage.php
In Imagemagick, there is -unique-colors that lists one of every color in the image. See UniqueImageColors at http://us3.php.net/manual/en/imagick.uniqueimagecolors.php
I want to get the values of pixels in a circumference in an image, and plot them.
I know Circumference is C=2*pi*radius, but I am uncertain about how to iterate through all the points in a circle to get the pixel data.
To get a single pixel, this would work. But I need to get pixel values along a circles circumference. how should I iterate through to get that data?
$pixel=getPixel($image, $x, $y);
look at answers here 3D sphere boundary
it is 3D equivalent of your problem so it may help but if you need also the pixel order to be right then most likely is this not for you.
If you want speed use Bresenham
but for newbies it can be difficult to implement and even more to understand
if you want simplicity instead (or for start) then:
use parametric circle equation
x=x0+r*cos(t)
y=y0+r*sin(t)
which get you pixel position for the circle boundary while t= <0,2*pi) [rad] use deg or rad according to your sin,cos functions
pixels only
circle circumference is 2*pi*r [pixels] so step for parameter t should be small enough to reach as many points
dt <= 2*pi/2*pi*r // whole circle / number of pixels
dt <= 1/r // let use half of that for safety
so for extracting points use this C++ code:
int x0=...,y0=...,r=...; // input values
int xx=x0+r+r,yy=y0,x,y;
double t,dt=0.5/r;
for (t=0.0;t<2.0*M_PI;t+=dt)
{
x=x0+int(double(double(r)*cos(t)));
y=y0+int(double(double(r)*sin(t)));
if ((xx!=x)&&(yy!=y)) // check if the coordinates crossed pixel barrier
{
xx=x; yy=y;
// here do what you need to do with pixel x,y
}
}
if there are holes inside your perimeter then lower the dt more. The less it is the smaller step you use but it also slows down the whole thing. You can have r as double or has its copy to avoid 2 int/double conversions. xx,yy are last used pixel coordinates to avoid processing single pixel multiple times.
At start it is set point that is not inside circle for safety. if r==0 then you should set dt to some safety value like dt=M_PI;
One way to do this would be to copy the low level code used to plot the pixels when creating the image of a circle on the screen. This works by incrementing (or decrementing) one of the co-ordinates and then adjusting the other one so as to keep the same distance from the centre of the circle. To ensure it is symmetrical, you make sure that each octant of the circle is plotted in exactly the same way. Details at http://www.asksatyam.com/2011/01/bresenhams-circle-algorithm_22.html (Or http://en.wikipedia.org/wiki/Midpoint_circle_algorithm of course).
I have the next problem.
I have a base color with couple of different shades of that color.
Example:
Base color: #4085c5
Shade: #005cb1
Now, I have a different color (let's say #d60620), but no shades of it. From the color I would like to calculate shades, that have similar difference as colors mentioned in first paragraph.
First I tried calculating difference of RGB elements and applying them to second color, but the result was not like I expected to be.
Than I tried with converting color to HSV, reading saturation value and applying the difference to second color, but again the resulting color was still weird.
The formula was something like: (HSV(BaseColor)[S] - HSV(Shade)[S]) + HSV(SecondColor)[H]
Does anyone know how this problem could be solved? I know I am doing something wrong, but I don't know what. :)
There are two ways to darken a color:
Subtract an equal amount from R,G,B. This increases the saturation. Obviously you can only subtract an mount equal to the least of the R,G,B values.
Multiply R,G,B by a value less than 1.0. This leaves the saturation more or less intact.
Similarly, there are two ways to lighten a color:
Add an equal amount to R,G,B. This decreases the saturation.
Multiply R,G,B by a value greater than 1.0. This increases the vividness of the color and thus the apparent saturation.
Your example appears to have done both - subtracting 0x40 from each value and multiplying by 1.33.
Using your second color, we can subtract 06 from each resulting in #d0000a but this is not dark enough. Multiplying it by 0.735 results in #990013.
Your first two colours both have a "H" (hue) value of 209, and varying values for "S" and "V".
This common hue is what defines the second colour as being a "shade" of the first colour.
To find alternative shades of your third colour, use an RGB to HSV conversion to find its hue, modify its S and V values as desired, and then convert back to RGB.
I have an application that has about one hundred users. We have a calender view in which every user can have multiple entries. Every entry of the same user should have the same color, but different users should have different colors. At the moment we have manually defined about 25 colors in an array, and the color a user gets is determined by
$color = $colors[$userid % count($colors)];
We don't want to manually add colors for every new user, and selecting a color for each user seems a bit tedious too.
Is there a simple function to map a number (the users id) to a color (preferably RGB)? The next question that rises is; Is there a way to limit the function to a certain types of colors (ie. only colors in which white letters are readable)?
I don't have a solution, per se, but a suggestion.
First, since you want each user's colors to be unique but random, you could get started with some kind of numerical hash function. That gets you a random number that's most likely unique. if your hash function is decent and your users are in the hundreds that should suffice.
Now you need to turn that into colors, preferably on the dark end of the spectrum. If you go with RGB, You need three numbers. To keep them dark, lets say you keep the total or R, G and B under 200. That's a guess, of course, but it should be pretty dark. Pick a random number [index] between 1 and 3 - that's the R, G or B you're going to start with. Get a number between 0 and 200, and set record it for color[index1]. Now pick one of the remaining indexes, 1-3. For this, pick a number between 0 and color[index1] that you already have. Set the remaining number to 200-color[index1]-color[index2]. Now you have a randomish RGB value that should contrast with white.
I realize I never got much use from that hash function up front - maybe ditch it and just use the userid as a random(seed).
You want to work in the hue-saturation-lightness or hue-saturation-value (HSL or HSV) space.
http://en.wikipedia.org/wiki/HSL_and_HSV
Start by defining some colors based on hue and saturation, and set the lightness to the highest tolerable level that makes the text readable.
Then you can fix the hue and saturation for these colors and decrease the lightness.
So say you started by choosing 25 tolerable colors with different hues and maximum/minimum tolerable lightness.
To generate a color for an index you pick the base color to start with base = id % 25 You then decrease the luminance depending on the index within that color index = (Math.floor(id/25)). Set the luminance somewhere within the tolerable luminance range based on that value. So let's say we will have 5 luminance values per color, set the luminance to
lightness = maxLightness - index*(maxLightness / 4*minLightness)
This simply varies the lightness for each color. You can choose to vary saturation and hue slightly if you would prefer. Converting between HSV and RGB is a well documented procedure.
PHP HSV to RGB formula comprehension
I'm looking for a way to sort images as in the following screenshot:
http://www.pixolution.de/sites/LargeImages_en.html
I've looked at all the threads on this topic on stackoverflow but none of the proposed solutions even come close to giving me the image above.
Approaches I've tried:
for each image, build histogram of rgb colors in descending order of occurrence
for each histogram, calculate a distance from black (r:0,g:0,b:0) as follows:
for color in image_histogram:
total_distance += color.percentage_of_image * distance(BLACK_RGB, color.rgb)
then sort images by their distances
I was hoping that images of similar color distribution would end up with a similar distance and result in a visual ordering by color. This was not the case, it seems to somewhat work but not like in the image above.
For the distance function, I've tried euclidean distance, hsv sorting (h->s->v) and even Lab distance sorting. None of which has helped
If anyone has a better approach, I would love to know!
I've never done something like this myself, so forgive me if the following approach is naive:
For each image, boil it down to 1 average RGB value by summing the R, G, B values of all pixels, and divide by the total # pixels. Normalize the components to [0..1]
Plot the image in your 2D color space based on the RGB values. This can be a 2D projection of a 3D (r, g, b) vector transformation.
you could convert to HSV and sort by H
Hue is what most people think of when they think "color"
see: RGB to HSV in PHP
Group similar colors using the distance between them and not between them and black, and use the average color in the image.
You might want to check out ImagePlot. I'm not sure if the algorithms behind the system are available, but you can certainly download and run your image collection through the free software to analyze them.
This software is used in many interesting visualizations of massive image collections, millions+
Info: http://lab.softwarestudies.com/p/imageplot.html#whatsnew
Source: https://github.com/culturevis/imageplot