I want to ignore all other colours. I just want to count the colours between white and yellow(Bright yellow, Light yellow.. all the way to white). and then give a rating of how yellow a certain image is. is that possible?
I have been playing with Bitmap.getPixel() but I can't figure out how to ignore other colours.
In this example, image 1 would be the one select because it has more colour between bright yellow and white.
How can I detect yellowish colours only?
Well I would focus on the HUE of the pixel. Using this code:
// get HSV values for the pixel's colour
float[] pixelColorHsv = new float[3];
Color.colorToHSV(Bitmap.getPixel(x,y), pixelColorHsv);
What is Yellow might be up to you but a range could be between 72 and 49 (you can play with this tool to get an idea) then you can quantify where it is in this range or how high or low the brightness and saturation are.
The Bitmap.getPixel(int x, int y) method returns a Color object with the RGB values for that pixel. Yellow is a combination of red and green, so a straight yellow RGB triple would be (255, 255, 0), right? If you get darker, you lower both of the red and green values. If you get brighter, you bring up the blue value. So basically, you need to find a way to detect how "close" any given pixel's RGB value comes to (255, 255, 0) and then accumulate those closeness values for the entire image. Do the same for the second image, then compare the 2 results.
Related
After reading these tutorials (this & this), I can figure out how to extract any color range including Red, Green, Blue and Yellow, using the Hue value of an HSV image or OpenCV Mat. However this value doesn't have the ability to describe the Gray color that I need to select. So is there any way to extract the Gray pixels of an image using OpenCV?
In HSV/HSL colourspace, the grey pixels are characterised by having Saturation of zero or very close to zero, so that test will discriminate black through grey to white pixels. Then the Value/Lightness will tell you how far along the scale from black to white they actually are, low Lightness/Value is dark grey whereas high Lightness/Value means light grey.
In RGB colourspace, grey pixels are characterised by having all three colour components equal, i.e. R=G=B.
After several notes, and knowing that:
To get have a white-to-dark-gray color out of an HSV image channels you should have the following values together Hue 0 to 360, Sat 0 to 10 & Val 50 to 100 (Check this page to test your own color range).
The OpenCV inRange function doesn't support handling HSV color combinations like this.
I decided to apply the range on each channel alone then getting the intersection of the 3 masks into a final mask that will represent my target white-to-dark-gray color.
Note that in OpenCV H has values from 0 to 180, S and V from 0 to 255. so you need to map your ranges into these limits.
Here is my code:
Mat hueMask1 = new Mat();
Mat satMask2 = new Mat();
Mat valMask3 = new Mat();
Mat white2GrayMask = new Mat();
Imgproc.cvtColor(image, image, Imgproc.COLOR_BGR2HSV);
List<Mat> channels_HSV = new ArrayList<>();
Core.split(image,channels_HSV);
Core.inRange(channels_HSV.get(0),new Scalar(0),new Scalar(180),hueMask1);
Core.inRange(channels_HSV.get(1),new Scalar(0),new Scalar(20),satMask2);
Core.inRange(channels_HSV.get(2),new Scalar(70),new Scalar(255),valMask3);
Core.bitwise_and(hueMask1,satMask2,white2GrayMask);
Core.bitwise_and(white2GrayMask,valMask3,white2GrayMask);
I'm working an image analyzation project that checks the rgb values at set locations in a host of images, and need to be able to know if a certain area is green or blue. Originally I thought I could do this by testing if g>b in the rgb, but I've come to realize that often there can be more blue than green in a green image, due to the mixture with red. How can I tell- possibly a formula or an algorithm, what a color visibly appears to be based on the rgb?
You can convert RGB values to HSB values using the Color classes RGBtoHSB method. The resulting hue value falls between 0-1, with the hue value of green (0,255,0) at 0.33 and blue (0,0,255) at 0.66
float[] hsb = Color.RGBtoHSB(0, 255, 0, null);//green
System.out.println(hsb[0]);
hsb = Color.RGBtoHSB(0, 0, 255, null);//blue
System.out.println(hsb[0]);
From this you could create a metric for hue values 'closer' to green, for instance any hue value < 0.5 is more green than blue.
Below is an image depicting how the colors change in this color space, with hue on the X axis (note in this picture hue varies from 0-360 degrees, whereas the RGBtoHSB returns values 0-1)
Would it be possible to use over 255 of red, green, and blue for colors in java? If so, how would those colors be used? I was wondering because I am making a program that produces rectangles with random colors, but most of the colors are similar. Is there any difference with using colors with values over 255 and colors with values under 255? Jpeg image formats use color values over 255 rgb, so would java be able to too? If I used a jpeg image, would the color still retain it's over 255 rgb color value?
This is my code for generating colors and drawing the shape to the screen:
Random r = new Random();
for(int i = 0;i<=shapes.size()-1;i++){
Shape s = shapes.get(i);
int red = r.nextInt(256);
int green = r.nextInt(256);
int blue = r.nextInt(256);
this.colors.add(new Color(red, green, blue));
//Draw the rectangle
g.setPaint(this.colors.get(i));
g.fill(s);
//Draw the outline
g.setPaint(Color.black);
g.draw(s);
}
I added the shape corresponding to the color in previous code.
"shapes" is my arraylist of shapes. "colors" is my arraylist of colors corresponding to each shape.
It depends on the encoding of color you use, but when it comes down to intensity no. 24-bit means that each color is communicated by - as it says - sending 24 bits: a zero or one. 24 means 3 (the number of color channels) times 8. Thus 8 bit or a byte per channel (red, green and blue). You can only represent 256 possibilities with 8 bit since it is 2^8=2*2*2*2*2*2*2*2=256. So no. For 24-bit colors. 255 is thus simply defined as the maximum intensity of red/green/blue a monitor renders. If you use default Java packages, I think they will (almost) always use 24 bit colors.
Now if you look into image formats, you will see some formats support higher bit rates. This only means that you define colors more precise. In other words if you would use a 48-bit color representation, each color channel will have 16 bit. In that case 65 535 will be the maximum value, but that's (more or less) equivalent to the 255 for a 24-bit color.
Most monitors only support 24-bit colors. More bits are in general only used during rendering (to perform computations on an image). For instance if you implement a raytracer, you must add all kinds of origins of light together. Or if you implement a Window environment where different windows can have different transparency level, you could calculate intermediate results with higher precision to increase the quality of the result.
Some camera's capture color more precisely. This can be useful because industrial printers sometimes make their own ink and one can thus make colors more accurately. That's one of the reasons magazine pictures are typically better than the pictures one prints at home.
A final note is that some renderers or (computer graphics) camera's even use more color channels. A friend implemented a raytracer that rendered rainbows. In order to do that, he implemented a definition of color with seven color channels. You don't need them to display the image on the screen, but you need them to do the calculations on how light interacts with water.
EDIT
About your code:
The problem lies in your code:
The most important problem is probably that:
Random r = new Random();
is called inside the loop. This is a bit inefficient.
Next, it seems that you have precoded the list of colors. In that case, no random generator will alter the colors. Mind that .add simply appends your new Color to the end of the list.
Next you call:
g.setPaint(Color.black);
g.draw(s);
g.setPaint(this.colors.get(i));
g.fill(s);
So you first paint the shape in black and then repaint it in the color you've picked. Why? You can replace it by:
g.setPaint(this.colors.get(i));
g.fill(s);
g.setPaint(Color.black);
g.draw(s);
Finally you can make the construction of a color more efficient by calling:
Color c = new Color(r.nextInt(16777216));
So the resulting program will be something like:
Random r = new Random();
for(int i = 0;i<=shapes.size()-1;i++){
Shape s = shapes.get(i);
Color c = new Color(r.nextInt(16777216));
g.setPaint(c);
g.fill(s);
g.setPaint(Color.black);
g.draw(s);
}
I have an Image with some rectangles inside it .. what i need is to crop only rectangles that have a red border and white background using (Java) or JavaCV.
for example i have an car image with license plate .. each letter at the license plate have red bordered rectangle around it and a white background.
what i am looking for is to crop each letter in a single image .. letters are identified by red bordered rectangle around each one and a white background.
Any suggestions?
Thanks
Change color space to HSV
IplImage* imgHSV = cvCreateImage(cvGetSize(img), 8, 3);
cvCvtColor(img, imgHSV, CV_BGR2HSV);
Get only hue channel:
cvSplit( imgHSV, h_plane, s_plane, v_plane, 0 );
Do the thresholding to find red color:
cvInRangeS(h_plane, cvScalar(x, x, x), cvScalar(x, x, x), imgThreshed);
x - range of red in HSV color model.
After this you will have white and black image, where white color is a red color on your original image (they should be of rectangle shape, as you said).
Then use cvFindContours function.
int contoursCont = cvFindContours( imgThreshed, storage,&contours,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));
To bound box (rectangle) use (for every contour):
CvBox2D box = cvMinAreaRect2( #current_contour#,
CvMemStorage* storage CV_DEFAULT(NULL))
To check the color of background calculate its histogram and check if values of bins are only 255 and 0 (they are values of white and black colors).
Hope, that will be useful!
You might try this:
Find a group of red pixels close to one another
Find all red pixels connected to these, bucket-fill style
Compute the bounding box of all the pixels found
Perhaps check whether the red pixels are all close to the rim of the bounding box
Check whether the interior of the box is mostly white
This should work as long as your boxes are not interrupted and do not overlap.
How to use the colorMatirxFilter to change orange color to green on a bitmap. Code samples would help. Please add explanation for the ColorMatrixFilter matrix.
I want to change the theme color based on user's selection.
As we know orange is not a pure color as Red, Green or Blue.
This means that orange has three components, R,G and B components. Therefore, please try this:
1) Convert the orange (three values) to gray (one value) by using
Gray = 0.3*RED + 0.59*GREEN+0.11*Blue;
2) Then, using ColorMatrixFilter (see Torious's link) set pixel values of those pixels which you want to change as:
Set ZERO (0 values) to Red and Blue components (as pixel values).
Set the Gray value (we just calculated) to Green component (as pixel value).
Then, you get your result.