M. Erfan Mowlaei
M. Erfan Mowlaei

Reputation: 1436

How to extract red/green pixels in an image

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

Answers (3)

M. Erfan Mowlaei
M. Erfan Mowlaei

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

roman
roman

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

Vishanth
Vishanth

Reputation: 1370

There are 2 methods that you use from Bitmap.

  • getPixel(int x, int y) // Returns in int the Color at the specified location.
  • getPixels(int[] pixels, int offset, int stride, int x, int y, int width, int height) // Returns in pixels[] a copy of the data in the bitmap.

Upvotes: 0

Related Questions