如何提取图像中的红色/绿色像素

时间:2015-01-12 08:16:18

标签: android opencv image-processing

我需要在位图/图像中提取红色/绿色像素,但我不知道该怎么做。 使用OpenCV是一个选择,但我不知道如何使用它,此外它会增加我的应用程序的大小,所以我更喜欢一段代码或其他较轻的库来做到这一点。'由上下文的方式是android。

更新

这是我目前使用的代码,但它并不好,我想要更自动化的内容。

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);
}

3 个答案:

答案 0 :(得分:2)

您可以使用

打开位图
Bitmap img = BitmapFactory.decodeFile("path/to/img.jpg");


然后,您可以使用

提取像素值
int pixel = img.getPixel(x,y);


并提取特定的RGB值

int red = Color.red(pixel);
int green = Color.green(pixel);


然后,您可以循环显示像素,检查您感兴趣的值,以及当值不是“绿色足够”时,您可以将像素的值设置为例如。白色(这不是测试,只是从记忆中写的)

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);
    }
}   


然后,您可以检查边缘开始的位置,并仅提取图像的该部分。
如果您需要更复杂的东西,您可能会重新考虑使用OpenCV。还有例如这一个http://libccv.org/。但是,之前我没有使用它,所以我不能说它是否完全符合您的要求。

答案 1 :(得分:0)

您可以使用Bitmap中的两种方法。

  • getPixel(int x,int y) //返回int指定位置的Color。
  • getPixels(int [] pixels,int offset,int stride,int x,int y,int width,int height) //以像素[]的形式返回位图中数据的副本

答案 2 :(得分:0)

考虑到我的背景是黑色的,我提出这种方法希望它适用于其他人(因为它是基于java的,它不是那么有效所以你应该考虑在处理之前压缩图像):

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);
}