In black and white image,we can easily calculate the contrast by (total no. of white pixels - total no. of black pixels).
How can I calculate this for color(RGB) image?
Any idea will be appreciated?
You may use the standard Deviation of the grayscale image as measure for the contrast. This is called "RMS contrast". See https://en.wikipedia.org/wiki/Contrast_(vision)#RMS_contrast for Details.
Contrast is defined as the difference between the highest and lowest intensity value of the image. So you can easily calculate it from the respective histogram.
Example: If you have a plain white image, the lowest and highest value are both 255, thus the contrast is 255-255=0. If you have an image with only black (0) and white (255) you have a contrast of 255, the highest possible value.
The same method can be applied for color images if you calculate the luminescence of each pixel (and thus convert the image to greyscale). There are several different methods to convert images to greyscale, you can chose one you like.
To make the approach more sophisticated, it is advisable to ignore a certain percentage of pixels to account for outliers (otherwise a single white and black pixel would lead to "full contrast", regardless of all other pixels). Another approach would be to take the number of dark and light pixels into account, as described by #Yves Daoust. This approach has the flaw that one has to set an arbitrary threshold to determine which pixels count as dark/light (usually 127).
This does not have a single answer. One idea I can think of is to operate on each of the three channels separately, Red, Green and Blue. Compute the histogram of each channel and operate on it.
A simple google search resulted in many relevant algorithms, one of them that I have used is Root Mean Square (standard deviation of the pixel intensities).
Related
I'm trying to come up with an algorithm that would output colorized/modified image according to source image and desired average color of resulting image as an input.
So let's say that I want an average color to be #ffcc00 - then for any given image I can get a new image that has average color of exactly #ffcc00. I don't mind if the resulting image is heavily modified as long as shapes are recognizable.
How should I approach this?
I think you need to look at your #ffcc00 as three distinct parts. You want to make the red channel average become 255, the green channel average become 204 and the blue channel average become zero.
If your image is unsigned 8-bit, all pixels will be in the range 0..255, i.e. no negative values. So the only way to make the red channel average 255 is if all pixels have red=255. Likewise, the only way to make the blue channel average 0 is if you make the blue component of all pixels zero.
That leaves just the green channel. So you have the existing green channel with some mean value and you want to transform that value to 204, so you effectively want to multiply all the green channel pixels by 204/(current mean). If the new mean is higher than the old mean, some pixels will hit 255 and clip, so you may need to iterate multiplying by a little more till you get what you want. Likewise, if the desired new mean is lower than the existing mean, some pixels may clip at zero and you may need to iterate and multiply by a little less till you get what you want.
Have a look here for a more scientific answer.
How to detect color from given text (image)? E.g. I've got this image
You can clearly see the text color is black (rgb 0, 0, 0). This is how it looks when I zoom the image:
Now we can see there are at least 5 different colors.. How can I detect the color that human eye sees? Obviously I might take the most common color from all pixels of the image (excluding the background), but this doesn't always work (e.g. on much smaller text size where the letters are actually 1-2 pixel thick such as:
.
Create a histogram of the text-image (excluding the background of course).
Check if there is a significant and clear peak (you can decide thresholds yourself or empirically). If there is one, that's the colour you are looking for.
If there is no significant peak, which looks like the case in "Search" text, take an average of all the pixel's colour. Roughly, this should be faint (approximation) of the original colour. Now, list the colour of all the (insignificant) peaks and try matching one by one hue/colour of this average. The peak which has hue/colour closest to the average should be your candidate.
Happy coding
Converting a value to a colour is well known, I do understand the following two approaches (very well described in changing rgb color values to represent a value)
Value as shades of grey
Value as brightness of a base colour (e.g. brightness of blue)
But what is the best algorithm when I want to use the full colour range ("all colours"). When I use "greys" with 8bit RGB values, I actually do have a representation of 256 shades (white to black). But if I use the whole range, I could use more shades. Something like this. Also this would be easier to recognize.
Basically I need the algorithm in Javascript, but I guess all code such as C#, Java, pseudo code would do as well. The legend at the bottom shows the encoding, and I am looking for the algorithm for this.
So having a range of values(e.g. 1-1000), I could represent 1 as white and 1000 as black, but I could also represent 1 as yellow and 1000 as blue. But is there a standard algorithm for this? Looking at the example here, it is shown that they use colour intervals. I do not only want to use greys or change the brightness, but use all colours.
This is a visual demonstration (Flash required). Given values a represented in a color scheme, my goal is to calculate the colours.
I do have a linear colour range, e.g. from 1-30000
-- Update --
Here I found that here is something called a LabSpace:
Lab space is a way of representing colours where points that are close to each other are those that look similar to each other to humans.
So what I would need is an algorithm to represent the linear values in this lab space.
There are two basic ways to specify colors. One is a pre-defined list of colors (a palette) and then your color value is an index into this list. This is how old 8-bit color systems worked, and how GIF images still work. There are lists of web-safe colors, eg http://en.wikipedia.org/wiki/Web_colors, that typically fit into an 8-bit value. Often similar colors are adjacent, but sometimes not.
A palette has the advantage of requiring a small amount of data per pixel, but the disadvantage that you're limited in the number of different colors that can be on the screen at the same time.
The other basic way is to specify the coordinates of a color. One way is RGB, with a separate value for each primary color. Another is Hue/Saturation/Luminance. CMYK (Cyan, Magenta, Yellow and sometimes blacK) is used for print. This is what's typically referred to as true color and when you use a phrase like "all colors" it sounds like you're looking for a solution like this. For gradients and such HSL might be a perfect fit for you. For example, a gradient from a color to grey simply reduces the saturation value. If all you want are "pure" colors, then fix the saturation and luminance values and vary the hue.
Nearly all drawing systems require RGB, but the conversion from HSL to RGB is straight forward. http://en.wikipedia.org/wiki/HSL_and_HSV
If you can't spare the full 24 bits per color (8 bits per color, 32-bit color is the same but adds a transparency channel) you can use 15 or 16 bit color. It's the same thing, but instead of 8 bits per color you get 5 each (15 bit) or 5-6-5 (16 bit, green gets the extra bit because our eyes are more sensitive to shades of green). That fits into a short integer.
It depends on the purposes of your datasets.
For example, you can assign a color to each range of values (0-100 - red, 100-200 - green, 200-300 - blue) by changing the brightness within the range.
Horst,
The example you gave does not create gradients. Instead, they use N preset colors from an array and pick the next color as umbr points out. Something like this:
a = { "#ffffff", "#ff00ff", "#ff0000", "#888888", ... };
c = a[pos / 1000];
were pos is your value from 1 to 30,000 and c is the color you want to use. (you'd need to better define the index than pos / 1000 for this to work right in all situations.)
If you want a gradient effect, you can just use the simple math shown on the other answer you pointed out, although if you want to do that with any number of points, it has to be done with triangles. You'll have a lot of work to determine the triangles and properly define every point.
In JavaScript, it will be dog slow. (with OpenGL it would be instantaneous and you would not even have to compute the gradients, and that would be "faster than realtime.")
What you need is a transfer function.
given a float number, a transfer function can generate a color.
see this:
http://http.developer.nvidia.com/GPUGems/gpugems_ch39.html
and this:
http://graphicsrunner.blogspot.com/2009/01/volume-rendering-102-transfer-functions.html
the second article says that the isovalue is between [0,255]. But it doesn't have to be in that range.
Normally, we scale any float number to the [0,1] range, and apply transfer function to get the color value.
I would like to track a color in a set of images.
For this reason I use the algorithm of constant thresholding mentioned in
Introduction to Autonomous Mobile Robots. This method simply marks all those pixels that are among a minimum and a maximum threshold of red, green, blue (or hue, saturation, value in my case).
My problem is that - although HSV is less sensitive to changing light conditions - I still would like to set the thresholds from program to minimize the number of false positives and false negatives. In other words the algorithm would ensure that only a given set of pixels is marked in the end, for example a rectangle on a calibration image.
I know that the problem is a search in a 6-dimensional parameter space and I could come up with possible solutions but I am looking for other programmers' opinion and experience on this subject.
If that matters I try to implement it in C++ with OpenCV.
As far as I understand the question you are looking for procedure to calibrate 6 thresholds (min and max for each of the HSV channels) from a calibration image that contains your tracking marker. To achieve this I would:
first manually delineate the
region, in the calibration image,
where the marker appears
calculate that region's histograms, one for each of the
HSV channels
set the min and max thresholds to the histogram
percentiles 0.05 and 0.95
respectively
Not using the histogram's minimum and maximum values, but rather its 0.05 and 0.95 percentiles helps the measure be more robust to noise.
EDIT:
A modification of the second step:
If you want to minimize the error, you could establish a normilzed histogram of the marker and a normalized histogram of the environment (this can be 2 separate images) and subtract the latter from the first. The resulting marker histogram will have background pixel values attenuated. This will affect the values of the above mentioned percentiles.
Let's say I query for
http://images.google.com.sg/images?q=sky&imgcolor=black
and I get all the black color sky, how actually does the algorithm behind work?
Based on this paper published by Google engineers Henry Rowley, Shumeet Baluja, and Dr. Yushi Jing, it seems the most important implication of your question about recognizing colors in images relates to google's "saferank" algorithm for pictures that can detect flesh-tones without any text around it.
The paper begins by describing by describing the "classical" methods, which are typically based on normalizing color brightness and then using a "Gaussian Distribution," or using a three-dimensional histogram built up using the RGB values in pixels (each color is a 8bit integer value from 0-255 representing how much . of that color is included in the pixel). Methods have also been introduced that rely on properties such as "luminance" (often incorrectly called "luminosity"), which is the density of luminous intensity to the naked eye from a given image.
The google paper mentions that they will need to process roughly 10^9 images with their algorithm so it needs to be as efficient as possible. To achieve this, they perform the majority of their calculations on an ROI (region of interest) which is a rectangle centered in the image and inset by 1/6 of the image dimensions on all sides. Once they've determined the ROI, they have many different algorithms that are then applied to the image including Face-Detection algs, Color Constancy algs, and others, which as a whole find statistical trends in the image's coloring and most importantly find the color shades with the highest frequency in the statistical distribution.
They use other features such as Entropy , Edge-Detection, and texture-definitions to
In order to extract lines from the images, they use the OpenCV implementation (Bradski, 2000) of the probabilistic Hough transform (Kiryati et al., 1991) computed on the edges of the skin color connected components, which allows them to find straight lines which are probably not body parts and additionally allows them to better determine which colors are most important in an image, which is a key factor in their Image Color Search.
For more on the technicalities of this topic including the math equations and etc, read the google paper linked to in the beginning and look at the Research section of their web site.
Very interesting question and subject!
Images are just pixels. Pixels are just RGB values. We know what black is in RGB, so we can look for it in an image.
Well, one method is, in very basic terms:
Given a corpus of images, determine the high concentrations of a given color range (this is actually fairly trivial), store this data, index accordingly (index the images according to colors determined from the previous step). Now, you have essentially the same sort of thing as finding documents containing certain words.
This is a very, very basic description of one possible method.
There are various ways of extracting color from an image, and I think other answers addressed them (K-Means, distributions, etc).
Assuming you have extracted the colors, there are a few ways to search by color. One slow, but obvious approach would be to calculate the distance between the search color and the dominant colors of the image using some metric (e.g. Color Difference), and then weight the results based on "closeness."
Another, much faster, approach would be to essentially downscale the resolution of your color space. Rather than deal with all possible RGB color values, limit the extraction to a smaller range like Google does (just Blue, Green, Black, Yellow, etc). Then the user can search with a limited set of color swatches and calculating color distance becomes trivial.