anilsathyan7 / Portrait-Segmentation

Real-time portrait segmentation for mobile devices
MIT License
638 stars 133 forks source link

How to assign segmentation results into a Bitmap #9

Closed Roberto7588 closed 4 years ago

Roberto7588 commented 4 years ago

I am new machine learning, and your project is very good for learning. I'm experimenting with your code. In the Android demo, in the function ImageSegmentorFloatMobileUnet.imageblend(...), you assign the segmentation results (segmap) to mskmat: mskmat.put(0,0,segmap[0]); I am doing test without using OpenCV, so, how can assign the segmap result directly into a normal android Bitmap? I don't want to use OpenCV and Mat. Thanks

anilsathyan7 commented 4 years ago

There are other methods to get the output results ...

  1. Array to bitmap: Loop and create bitmap, eg. JejuNet
  2. Array to opencv mat: Current approach - Opencv Mat
  3. Tensorbuffer: Tensorflow buffer, ref: Tflite android support libraray

I started learning about he segmentation pipeline and code from the first link. Finally it seem that the first method is the least efficient and the last one most efficient, with respect to performance. On the other hand, the opencv method helps us for easy/efficient post-processing of images.

Roberto7588 commented 4 years ago

This is what I tried so far, but it didn't work. I also tried with Bitmap.Config.ALPHA_8 bitmap format:

Bitmap test = Bitmap.createBitmap(opsize, opsize, Bitmap.Config.ARGB_8888);

for (int y = 0; y < opsize; y++)
{
    for (int x = 0; x < opsize; x++)
    {
        final int index = opsize * y + x;
        test.setPixel(x, y, (int)segmap[0][index]);
    }
}

Then debugging I saw that the segmap values are float less than 0. Do I need to transform each pixel in segmap with some formula?

anilsathyan7 commented 4 years ago

In my models, the values lie between 0.0 and 1.0 as float since i have used sigmoid function at the output(inside model). So you have to use a threshold, say 0.5 and change the values to 255(1.0) or 0 (0.0) accordingly. Also, see corresponding python inference code for more details.

In general, you may need to apply an argmax function on the softmax or logits output of model to determine the class labels for each pixels, assuming the number of classes>=2. Also refer the link i mentioned previously for more details.

Roberto7588 commented 4 years ago

Thank you, it worked. I did as next, and now I can see mask in the bitmap:

final int index = opsize * y + x;

final int color = segmap[0][index] < 0.5
            ? Color.RED
            : Color.BLUE;

test.setPixel(x, y, color);
anilsathyan7 commented 4 years ago

Closing this issue since it's resolved; but feel free to open another ticket if the problem persists.