Reputation: 1436
I need to extract red/green pixels in a bitmap/Image but I have no idea how to do it. Using OpenCV would be a choice but I don't know how to use it and besides it will increase the size of my app so I would prefer a piece of code or other lighter library to do so.'By the way the context is android.
Update
Here's the code I use currently but it's no good and I want something more automated.
public int getDominantColor(Bitmap bitmap,int RGB_SELECTOR, int Rval, int Gval, int Bval) {//RGB_SELECTOR => 0==getting red colors and 1==getting green color
if (null == bitmap) return Color.TRANSPARENT;
//Log.e("func called with",Integer.toString(RGB_SELECTOR));
int redBucket = 0;
int greenBucket = 0;
int blueBucket = 0;
int alphaBucket = 0;
boolean hasAlpha = bitmap.hasAlpha();
int pixelCount = bitmap.getWidth() * bitmap.getHeight();
int[] pixels = new int[pixelCount];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
int true_pixels_count = 0;
for (int y = 0, h = bitmap.getHeight(); y < h; y++)
{
for (int x = 0, w = bitmap.getWidth(); x < w; x++)
{
int color = pixels[x + y * w]; // x + y * width
if(RGB_SELECTOR == 0 && ((color >> 16) & 0xFF)>Rval &&
((color >> 8) & 0xFF)<Gval && ((color & 0xFF))<Bval){//R
redBucket += (color >> 16) & 0xFF; // Color.red
greenBucket += (color >> 8) & 0xFF; // Color.green
blueBucket += (color & 0xFF); // Color.blue
if (hasAlpha) alphaBucket += (color >>> 24); // Color.alpha
true_pixels_count++;
}else if(RGB_SELECTOR == 1 && (((color >> 16) & 0xFF)<Rval &&
((color >> 8) & 0xFF)>Gval && ((color & 0xFF))<Bval) ||
(((color >> 16) & 0xFF)<0x96 &&
((color >> 8) & 0xFF)>0xBE && ((color & 0xFF))<0x14)){//G
redBucket += (color >> 16) & 0xFF; // Color.red
greenBucket += (color >> 8) & 0xFF; // Color.green
blueBucket += (color & 0xFF); // Color.blue
if (hasAlpha) alphaBucket += (color >>> 24); // Color.alpha
true_pixels_count++;
}else if(RGB_SELECTOR == 2 && ((color >> 16) & 0xFF)<Rval &&
((color >> 8) & 0xFF)<Gval && ((color & 0xFF))>Bval) {//B
redBucket += (color >> 16) & 0xFF; // Color.red
greenBucket += (color >> 8) & 0xFF; // Color.green
blueBucket += (color & 0xFF); // Color.blue
if (hasAlpha) alphaBucket += (color >>> 24); // Color.alpha
true_pixels_count++;
}
else {
bitmap.setPixel(x,y,Color.WHITE);
}
}
}
//Log.e("func ended with",Integer.toString(RGB_SELECTOR));
return Color.argb(
(hasAlpha) ? (alphaBucket / true_pixels_count) : 255,
redBucket / true_pixels_count,
greenBucket / true_pixels_count,
blueBucket / true_pixels_count);
}
Upvotes: 0
Views: 1054
Reputation: 1436
Considering my background is black I cam up with this method hope it works for other people(since it's java based it's not so efficient so you should consider compacting image before process):
public int getDominantColor(Bitmap bitmap) {//gets dominiant color and filters image at the same time
if (null == bitmap) return Color.TRANSPARENT;
final int recognitionThreshold = 0x30;
int redBucket = 0;
int greenBucket = 0;
int blueBucket = 0;
int alphaBucket = 0;
boolean hasAlpha = bitmap.hasAlpha();
int pixelCount = bitmap.getWidth() * bitmap.getHeight();
int[] pixels = new int[pixelCount];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
pixelCount = 0;
float[] hsl = new float[3];
for (int y = 0, h = bitmap.getHeight(); y < h; y++)
{
for (int x = 0, w = bitmap.getWidth(); x < w; x++)
{
int color = pixels[x + y * w]; // x + y * width
Color.colorToHSV(color,hsl);
if((hsl[2]>=0.2f && hsl[2]<=0.8f) && ((((color>>16)&0xFF) > recognitionThreshold) ||(((color>>8)&0xFF) > recognitionThreshold))){//you can change Luminiance threshold and green/red threshold for better results but this worked for my case pretty well
redBucket += (color >> 16) & 0xFF; // Color.red
greenBucket += (color >> 8) & 0xFF; // Color.green
blueBucket += (color & 0xFF); // Color.blue
pixelCount++;
if (hasAlpha) alphaBucket += (color >>> 24); // Color.alpha
}else {
//this pixel is not my favorite so I color it to white
bitmap.setPixel(x,y,Color.WHITE);
}
}
}
return Color.argb(
(hasAlpha) ? (alphaBucket / pixelCount) : 255,
redBucket / pixelCount,
greenBucket / pixelCount,
blueBucket / pixelCount);
}
Upvotes: 0
Reputation: 66
You can open a bitmap with
Bitmap img = BitmapFactory.decodeFile("path/to/img.jpg");
You can then extract pixel values with
int pixel = img.getPixel(x,y);
And to extract the particular RGB value
int red = Color.red(pixel);
int green = Color.green(pixel);
You could then loop through the pixels, check the values you are interested in, and when the values are not let's say "green-enough", you set the values of the pixel to e.g. white (this is not tested, just wrote from memory)
for (int row = 0; row < img.getWidth(); row++) {
for (int col = 0; col < img.getHeight(); row++) {
// Use the previous functions to get the
// color you are interested in.
int interestingColor = getMyColor(row, col);
// Check if the color is within certain
// range that is "acceptable". If not,
// make it white.
if(!isInRange(interestingColor))
img.setPixel(row, col, Color.WHITE);
}
}
Then you could check where the edges begin and extract only that portion of the image.
If you require something more complicated, you might reconsider using OpenCV. There is also e.g. this one http://libccv.org/. However, I didn't use it before, so I cannot say if it does exactly what you want.
Upvotes: 2
Reputation: 1370
There are 2 methods that you use from Bitmap.
Upvotes: 0