Saving HSV values into RGB image in Android - android

I have a HSV array which looks like,
double HSV[][][] = new double[100][100][3];
HSV[:][:][0] = H
HSV[:][:][1] = S
HSV[:][:][2] = V
I wish to convert my HSV array to a RGB bitmap image in Android. I know it can be done using
Color.HSVToColor()
method, but i am really new to Android programming small explanation with example will be useful.

Use this first:
http://developer.android.com/reference/android/graphics/Color.html#HSVToColor(float[])
public static int HSVToColor (float[] hsv)
Added in API level 1
Convert HSV components to an ARGB color. Alpha set to 0xFF. hsv[0] is Hue [0 .. 360) hsv[1] is Saturation [0...1] hsv[2] is Value [0...1] If hsv values are out of range, they are pinned.
Parameters
hsv 3 element array which holds the input HSV components.
Returns
the resulting argh color
Then second is use below link,
How to create image from RGB values in android

Related

YUV420 Image color detection like HSV color range

I'm receiving YUV420 image data in byte[] on every onDrawFrame(). I need to find out the colors present in the image from the byte array given. How can I extract U and V value for each pixel and use them to determine if the specific color is present in that image (something like HSV color range).
I've separated UV array from original image data like this:
byte[] data = image.getData();
int inputYLength = image.getWidth() * image.getHeight();
int inputUVLength = image.getWidth() * image.getHeight() / 2;
ByteBuffer uvBuffer = ByteBuffer.allocateDirect(inputUVLength);
uvBuffer.put(image.getData(), inputYLength, inputUVLength);
uvBuffer.position(0);
uvBuffer holds byte values for U and V components. How to use this for color detection?
The U and V components of your image are down-sampled relative to the Y component. So the first step is either:
to upsample the U and V to match the Y, or
down-sample the Y to match the U and V.
Which one you do depends on what resolution you need for the final phase of determining the Hue.
The second step is to convert the YUV from the first step into RGB.
The third step is to convert the RGB from the second step into HSL (Hue, Saturation and Lightness).
The final step is to select the H (Hue) corresponding to the colours you want.
This answer links to the formulae you need.

OpenCV InRange parameter

I'm using OpenCV on Android to find circles of specific colour's in real time. My first step is to keep only pixels which corresponds to my defined color i'm looking for (red or green in this example). Example Image.
For this purpose i'm using the method inRange().
Here is my Question: What kind of color model (RGB, BGR, HSV, ..) is required as lower-/upper-bound color parameter's? And: what is a good practice to define these color bounds in respect to natural brightness changes?
matRgba = inputFrame.rgba();
Scalar lowerColorBound = Scalar(0.0, 0.0, 0.0); // Blue, Green, Red?
Scalar upperColorBound = Scalar(0.0, 0.0, 0.0);
// convert to HSV, necessary to use inRange()
Imgproc.cvtColor(matRgba, matRgba, Imgproc.COLOR_RGB2HSV);
// keep only the pixels defined by lower and upper bound range
Core.inRange(matRgba, lowerColorBound, upperColorBound, matRgba);
The required color model for the inRange(src, lowerb, upperb, dst) function in OpenCV is HSV.
The lowerb and upperb parameters specify the required lower and upper color bounds in the HSV format. In OpenCV, for HSV, Hue range is [0,179], Saturation range is [0,255] and Value range is [0,255].
For object tracking applications a possible practice (as suggested in the official documentation) to define these two color bounds can be:
Start from a color to track in RGB format.
Convert the color to the HSV format. Let (H, S, V) be its value.
Assign the value (H - deltaH, minS, minV) to lowerb and the value (H - deltaH, maxS, maxV) to upperb.
Possible starting values for the parameters defined in step 3 can be:
deltaH = 10
minS = 100, minV = 100
maxS = 255, maxV = 255
Then you can adjust them to narrow down or enlarge the H, S, V intervals as needed.

Calculate opacity and saturation from color given in signed integer format

In my android app I have a color pick activity using Lars Werkman ColorPicker View. I'd like to start this activity setting the color picker and the opacity saturation bars to the values of the previously selected color. the color picker is easy but the opacity and saturation bars need some calculation first.
How can i calculate these two values given the signed-integer form of the color?
float[] hsv = new float[3];
Color.colorToHSV(currentColor, hsv); //hsv for hue, saturation, value
float saturation = hsv[1];
float value = hsv[2];
int opacity = Color.alpha(currentColor);

Android changing a color's brightness

I want to change the brightness of any given color (Note: I am not talking about screen brightness), I have looked at the Color class, it has a few methods for conversions between RGB and HSV, I'm a newbie in this area. To start with, how do I change the brightness of red, if its value is spefied in RGB (#FF0000)?
The easiest way would be to convert the color to HSL (not HSV! they are different - see http://en.wikipedia.org/wiki/HSL_and_HSV) and change the L component - increase to make it brighter, decrease to make it darker.
Considering that you are talking about brightness (color enhance) and not luminance (white amount), your model is the HSV (aka HSB) and not HSL.
On fast briefing, if you enhance the V channel on HSV over, lets say... some blue, you have a "more blue" color. If you enhance the L channel on HSL model you have a more "clear and washed" blue.
The android.graphics.Color class have built-in support to HSV model. Use Color.colorToHSV() and Color.HSVToColor() to edit the brightness value (or hue, or saturation, if you like).
On HSV model, H (hue) define the base color, S (saturation) control the amount of gray and V controls the brightness. So, if you enhance V and decrease S at same time, you gets more luminance, in pratice.
For starters, you need to remember two things -
To reduce brightness, you can change red from #FF0000 to #AA0000 or #880000 - basically reduce the Red component.
You can also try reducing opacity - often you'll realize that it works better than just reducing brightness.
You can use Color.colorToHSV to convert the color to HSV, then change the brightness of the HSV color, then use Color.HSVToColor to convert it back to a color int. For example, the following code sets the brightness to 0.5:
#ColorInt int originalColor = /*your original color*/;
float[] hsv = new float[3]; //Create an array to pass to the colorToHSV function
Color.colorToHSV(originalColor, hsv); //Put the HSV components in the array created above
hsv[2] = 0.5f; //Whatever brightness you want to set. 0 is black, 1 is the pure color.
#ColorInt int newColor = Color.HSVToColor(hsv); //Convert it back to a ColorInt

RGB value to HSL converter

Google maps api v3 allows "styles" to be applied to the map, including setting the color of various features. However, the color format it uses is HSL (or what seems like it):
hue (an RGB hex string)
lightness (a floating point value between -100 and 100)
saturation (a floating point value between -100 and 100)
(from the docs)
I managed to find RGB to HSL converters online, but I am unsure how to specify the converted values in a way that google maps will accept. For instance, a typical HSL value given by a converter would be: 209° 72% 49%
How does that HSL value map to the parameters I specified from the google maps api? i.e. how does a hue degree value map to an RGB hex string and how does a percentage map to a floating point value between -100 and 100?
I am still uncertain how to do the conversion. I need to, given an RGB value, quickly convert it to what google maps expects so that the color will be identical...
Since the hue argument expects RGB, you can use the original color as the hue.
rgb2hsl.py:
#!/usr/bin/env python
def rgb2hsl(r, g, b):
#Hue: the RGB string
H = (r<<16) + (g<<8) + b
H = "0x%06X" % H
#convert to [0 - 1] range
r = float(r) / 0xFF
g = float(g) / 0xFF
b = float(b) / 0xFF
#http://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
M = max(r,g,b)
m = min(r,g,b)
C = M - m
#Lightness
L = (M + m) / 2
#Saturation (HSL)
if L == 0:
S = 0
elif L <= .5:
S = C/(2*L)
else:
S = C/(2 - 2*L)
#gmaps wants values from -100 to 100
S = int(round(S * 200 - 100))
L = int(round(L * 200 - 100))
return (H, S, L)
def main(r, g, b):
r = int(r, base=16)
g = int(g, base=16)
b = int(b, base=16)
print rgb2hsl(r,g,b)
if __name__ == '__main__':
from sys import argv
main(*argv[1:])
Example:
$ ./rgb2hsl.py F0 FF FF
('0xF0FFFF', 100, 94)
Result:
Below is a screenshot showing the body set to a rgb background color (#2800E2 in this case), and a google map with styled road-geometry, using the values calculated as above ('0x2800E2', 100, -11).
It's pretty clear that google uses your styling to create around six different colors centered on the given color, with the outlines being closest to the input. I believe this is as close as it gets.
From experimentation with: http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html
For water, gmaps subtracts a gamma of .5. To get the exact color you want, use the calculations above, and add that .5 gamma back.
like:
{
featureType: "water",
elementType: "geometry",
stylers: [
{ hue: "#2800e2" },
{ saturation: 100 },
{ lightness: -11 },
{ gamma: 0.5 },
]
}
We coded a tool which exactly does want you want. It takes hexadecimal RGB values and generates the needed HSL code. It comes with a preview and Google Map JavaScript API V3 code output. Enjoy ;D
http://googlemapscolorizr.stadtwerk.org/
From the linked page:
Note: while hue takes an HTML hex color value, it only uses this value to determine the basic color (its orientation around the color wheel), not its saturation or lightness, which are indicated separately as percentage changes. For example, the hue for pure green may be defined as "#00ff00" or "#000100" within the hue property and both hues will be identical. (Both values point to pure green in the HSL color model.) RGB hue values which consist of equal parts Red, Green and Blue — such as "#000000" (black) and "#FFFFFF" (white) and all the pure shades of grey — do not indicate a hue whatsoever, as none of those values indicate an orientation in the HSL coordinate space. To indicate black, white or grey, you must remove all saturation (set the value to -100) and adjust lightness instead.
At least as I read it, that means you need to convert your angle based on a color wheel. For example, let's assume 0 degrees is pure red, 120 degrees is pure blue and 240 degrees is pure green. You'd then take your angle, figure out which two primaries it falls between, and interpolate to determine how much of each primary to use. In theory you should probably use a quadratic interpolation -- but chances are that you can get by reasonably well with linear.
Using that, 90 degrees (for example) is 90/120 = 3/4ths of the way from red to blue, so your hex number for the hue would be 0x00010003 -- or any other number that had green set to 0, and a 1:3 ratio between red and blue.
I needed to match colors exactly. So I used the tool that #stadt.werk offers (http://googlemapscolorizr.stadtwerk.org/) to get close.
But then I ran into the problem explained by #bukzor where the Google Maps API creates variations on your shade, none of which seem to be exactly what I specified.
So I pulled up the map in a browser, took a screenshot of just the area with the two shades that weren't quite matching, opened it up in an image editor (pixlr.com, in my case), used the color-sucker tool to get the saturation and lightness for the shade, adjusted my saturation and/or lightness in the Google API call by 1, and repeated until I got something that seems to match perfectly.
It is possible, of course, that Google Maps API will do different things with the colors on different devices/browsers/etc., but so far, so good.
Tedious, yes, but it works.

Categories

Resources