Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Real Time Black-White Threshold Image

I have a code that turns a bitmap that has the grey colors into a bitmap of black and white colors, using this code:

// scan through all pixels
for (int x = 0; x < width; ++x) {                                                                                                                                                                                               
  for (int y = 0; y < height; ++y) {                                                                                                                                                                                            
    // get pixel color
    pixel = bitmap.getPixel(x, y);                                                                                                                                                                                              
    A = Color.alpha(pixel);                                                                                                                                                                                                     
    R = Color.red(pixel);                                                                                                                                                                                                       
    G = Color.green(pixel);                                                                                                                                                                                                     
    B = Color.blue(pixel);                                                                                                                                                                                                      
    int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);                                                                                                                                                                    

    // use 128 as threshold, above -> white, below -> black
    if (gray > 128)
    gray = 255;                                                                                                                                                                                                                 
    else
    gray = 0;                                                                                                                                                                                                                   
    // set new pixel color to output bitmap
    bmOut.setPixel(x, y, Color.argb(A, gray, gray, gray));                                                                                                                                                                      
  }
}   

As you can see I travel all the pixels points of the original bitmap and then I compare the components of the color with a given threshold, in this case 128, and then if its above I say its white otherwise it will be a black pixel.

What I want to do now, is a Spinner that can change that threshold value, and then the BW image will be different.

To do this, I would need to draw all the image again, and that is very cpu costing time, its takes time to travel all the pixels again.

Is therey any way to change the image using a different BW threshold in real-time?

Someone told me to use a GIF, and then what I would do, was just changing the lookup table values of the GIF, does anyone has knowledge about this on Android?

like image 729
TiagoM Avatar asked Mar 29 '14 13:03

TiagoM


2 Answers

A little time passed since this question was asked, but I bumped into this looking for something else and happened to have the solution. You can achieve this without OpenCV or any other third party library, using only ColorMatrixColorFilter available since API level 1.

Here are matrices that You can use:

//matrix that changes picture into gray scale
public static ColorMatrix createGreyMatrix() {
    ColorMatrix matrix = new ColorMatrix(new float[] {
            0.2989f, 0.5870f, 0.1140f, 0, 0,
            0.2989f, 0.5870f, 0.1140f, 0, 0,
            0.2989f, 0.5870f, 0.1140f, 0, 0,
            0, 0, 0, 1, 0
    });
    return matrix;
}

// matrix that changes gray scale picture into black and white at given threshold.
// It works this way:
// The matrix after multiplying returns negative values for colors darker than threshold
// and values bigger than 255 for the ones higher. 
// Because the final result is always trimed to bounds (0..255) it will result in bitmap made of black and white pixels only
public static ColorMatrix createThresholdMatrix(int threshold) {
    ColorMatrix matrix = new ColorMatrix(new float[] {
            85.f, 85.f, 85.f, 0.f, -255.f * threshold,
            85.f, 85.f, 85.f, 0.f, -255.f * threshold,
            85.f, 85.f, 85.f, 0.f, -255.f * threshold,
            0f, 0f, 0f, 1f, 0f
    });
    return matrix;
}

And here's how to use them:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;

//load source bitmap and prepare destination bitmap
Bitmap pic = BitmapFactory.decodeResource(getResources(), R.drawable.thePicture, options);
Bitmap result = Bitmap.createBitmap(pic.getWidth(), pic.getHeight(),  Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(result);

//first convert bitmap to grey scale:
bitmapPaint.setColorFilter(new ColorMatrixColorFilter(createGreyMatrix()));
c.drawBitmap(pic, 0, 0, bitmapPaint);

//then convert the resulting bitmap to black and white using threshold matrix 
bitmapPaint.setColorFilter(new ColorMatrixColorFilter(createThresholdMatrix(128)));
c.drawBitmap(result, 0, 0, bitmapPaint);

//voilà! You can now draw the result bitmap anywhere You want:
bitmapPaint.setColorFilter(null);
otherCanvas.drawBitmap(result, null, new Rect(x, y, x + size, y + size), bitmapPaint);

Hope this will help someone.

like image 148
Arsen Avatar answered Oct 23 '22 15:10

Arsen


I recommend you look at using the OpenCV library for Android. Once you have it installed you can use it for quick thresholding among many other commonly used operations on images. The following code fragment will convert your colour bitamp into a gray image and threshold at gray level 128.

// first convert bitmap into OpenCV mat object
Mat imageMat = new Mat (bitmap.getHeight(), bitmap.getWidth(),
                CvType.CV_8U, new Scalar(4));
Bitmap myBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
Utils.bitmapToMat(myBitmap, imageMat);

// now convert to gray
Mat grayMat = new Mat ( bitmap.getHeight(), bitmap.getWidth(),
            CvType.CV_8U, new Scalar(1));
Imgproc.cvtColor(imageMat, grayMat, Imgproc.COLOR_RGB2GRAY, 1);

// get the thresholded image
Mat thresholdMat = new Mat ( bitmap.getHeight(), bitmap.getWidth(),
            CvType.CV_8U, new Scalar(1));
Imgproc.threshold(grayMat, thresholdMat , 128, 255, Imgproc.THRESH_BINARY);

// convert back to bitmap for displaying
Bitmap resultBitmap = Bitmap.createBitmap(bitmap.cols(), bitmap.rows(),
                Bitmap.Config.ARGB_8888);
thresholdMat.convertTo(thresholdMat, CvType.CV_8UC1);
Utils.matToBitmap(thresholdMat, resultBitmap);
like image 3
JacoFourie Avatar answered Oct 23 '22 13:10

JacoFourie