Ask Your Question
2

How to remove black background from grabcut output image in OpenCV android ?

asked 2013-11-24 12:09:27 -0600

Dexter gravatar image

updated 2015-10-02 10:31:36 -0600

image description

Hi, I am using OpenCV android library grabcut() method to extract an image from background, but the problem is that the output bitmap contains black background which I do not want please note that original image does not have any black background it is actually white and I am able to successfully extract the fish image from that but the output contains this kind of black background. I am attaching the code for your reference, I am new to opencv and don't have much understanding about it and grabcut algorithm also so kindly help me out.

public class Grabcut extends Activity {
    ImageView iv;
    Bitmap bitmap;
    Canvas canvas;
    Scalar color = new Scalar(255, 0, 0, 255);
    Point tl, br;
    int counter;
    Bitmap bitmapResult, bitmapBackground;
    Mat dst = new Mat();
    final String pathToImage  = Environment.getExternalStorageDirectory()+"/gcut.png";
    public static final String TAG = "Grabcut demo";
    static {
          if (!OpenCVLoader.initDebug()) {
            // Handle initialization error
          }
        }
    @Override
    public void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);
        setContentView(R.layout.grabcut_main);
        iv = (ImageView) this.findViewById(R.id.imageView);


        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.grabcut);
        Log.d(TAG, "bitmap: " + bitmap.getWidth() + "x" + bitmap.getHeight());


        bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
        Log.d(TAG, "bitmap 8888: " + bitmap.getWidth() + "x" + bitmap.getHeight());


        //GrabCut part
        Mat img = new Mat();
        Utils.bitmapToMat(bitmap, img);
        Log.d(TAG, "img: " + img);

        int r = img.rows();
        int c = img.cols();

        Point p1 = new Point(c/5, r/5);
        Point p2 = new Point(c-c/5, r-r/8);

        Rect rect = new Rect(p1,p2);
        //Rect rect = new Rect(50,30, 100,200);
        Log.d(TAG, "rect: " + rect);

        Mat mask = new Mat();
        debugger(""+mask.type());
        mask.setTo(new Scalar(125));
        Mat fgdModel = new Mat();
        fgdModel.setTo(new Scalar(255, 255, 255));
        Mat bgdModel = new Mat();
        bgdModel.setTo(new Scalar(255, 255, 255));

        Mat imgC3 = new Mat();  
        Imgproc.cvtColor(img, imgC3, Imgproc.COLOR_RGBA2RGB);
        Log.d(TAG, "imgC3: " + imgC3);

        Log.d(TAG, "Grabcut begins");
        Imgproc.grabCut(imgC3, mask, rect, bgdModel, fgdModel, 5, Imgproc.GC_INIT_WITH_RECT);

        Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(3.0));


        Core.compare(mask, source, mask, Core.CMP_EQ);
        Mat foreground = new Mat(img.size(), CvType.CV_8UC3, new Scalar(255, 255, 255));
        img.copyTo(foreground, mask);
        Core.rectangle(img, p1, p2, color);

        Mat background = new Mat();
        try {
            background = Utils.loadResource(getApplicationContext(),
                    R.drawable.wall2 );
        } catch (IOException e) {

            e.printStackTrace();
        }
        Mat tmp = new Mat();
        Imgproc.resize(background, tmp, img.size());

        background = tmp;

        Mat tempMask = new Mat(foreground.size(), CvType.CV_8UC1, new Scalar(255, 255, 255));
        Imgproc.cvtColor(foreground, tempMask, 6/* COLOR_BGR2GRAY */);
        //Imgproc.threshold(tempMask, tempMask, 254, 255, 1 /* THRESH_BINARY_INV */);

        Mat vals = new Mat(1, 1, CvType.CV_8UC3, new Scalar(0.0));
        dst = new Mat();
        background.setTo(vals, tempMask);
        Imgproc.resize(foreground, tmp, mask.size());
        foreground = tmp;
        Core.add(background, foreground, dst, tempMask);

        //convert to Bitmap
        Log.d(TAG, "Convert to Bitmap");
        Utils.matToBitmap(dst, bitmap);

        iv.setBackgroundResource(R.drawable.wall2);
        iv.setImageBitmap(bitmap);
        //release MAT part
        img.release();
        imgC3.release();
        mask.release();
        fgdModel.release();
        bgdModel.release();

    }

    public void debugger(String s){
        Log.v("","########### "+s);
    }
}

I have ... (more)

edit retag flag offensive close merge delete

5 answers

Sort by ยป oldest newest most voted
4

answered 2013-11-25 05:01:46 -0600

Haris gravatar image

updated 2013-11-25 05:03:08 -0600

You can easily solve this by reconstruct your image with alpha channel using the following step

  • Convert your source image to Gray scale.
  • Threshold the image to create alpha channel with complete transparency in black background region and zero transparency in foreground object region .
  • Split the original image in to three single channel.
  • Create the final result by merging three single channel and alpha(BGRA order).
  • Use the newly created image above your wall image.

And here is the C++ code for the above steps, re-write in Java as your need.

Mat src=imread("0.jpg",1);
Mat dst;//(src.rows,src.cols,CV_8UC4);
Mat tmp,alpha;

cvtColor(src,tmp,CV_BGR2GRAY);
threshold(tmp,alpha,100,255,THRESH_BINARY);

Mat rgb[3];
split(src,rgb);

Mat rgba[4]={rgb[0],rgb[1],rgb[2],alpha};
merge(rgba,4,dst);
imwrite("dst.png",dst);

Source Image without alpha.

image description

Result with alpha

image description

edit flag offensive delete link more

Comments

1

Nice answer. You really put some effort into it.

StevenPuttemans gravatar imageStevenPuttemans ( 2013-11-25 06:15:41 -0600 )edit
1

Thank you...

Haris gravatar imageHaris ( 2013-11-25 07:07:59 -0600 )edit
2

Thanks a lot Haris, I am really grateful to you.

Dexter gravatar imageDexter ( 2013-11-30 09:36:54 -0600 )edit
2

You are welcome.

Haris gravatar imageHaris ( 2013-11-30 23:58:32 -0600 )edit
1

Can you give me your java code to remove the block background.Very Thanks

Opencv_lover gravatar imageOpencv_lover ( 2014-04-28 22:18:23 -0600 )edit

Can you give me your java code to remove the block background.Very Thanks

Farrakh Javed gravatar imageFarrakh Javed ( 2014-05-20 06:37:52 -0600 )edit

The code is right there?

StevenPuttemans gravatar imageStevenPuttemans ( 2014-05-20 06:40:28 -0600 )edit

I'm not able to convert to java code for alpha and tmp. Kindly tell me how aplha is populated?

Farrakh Javed gravatar imageFarrakh Javed ( 2014-05-20 07:01:19 -0600 )edit

Please reply as soon as possible. Thanks in advance.

Farrakh Javed gravatar imageFarrakh Javed ( 2014-05-20 07:02:00 -0600 )edit

I think you should start reading on grabcut first ... it seems you do not understand the principles of the algorithm!

StevenPuttemans gravatar imageStevenPuttemans ( 2014-05-20 07:06:11 -0600 )edit

You are right. I'm using opencv4Adnroid library. so i think i am not able to do that.

Farrakh Javed gravatar imageFarrakh Javed ( 2014-05-20 07:31:15 -0600 )edit

But what if the foreground contains black pixels?

nena gravatar imagenena ( 2014-07-09 07:23:15 -0600 )edit
1

@ nena, I do suggest opening a complete new question since then everyone will see what you want. Now only the topic participators get a notice. You can reference this topic in your own question.

StevenPuttemans gravatar imageStevenPuttemans ( 2014-07-09 07:32:41 -0600 )edit
1

@nena As @StevenPuttemans suggest, it's better to open a new question with code and sample image. And about your question, I assume the background is some color object and foreground is black, in that case you can use Threshold Binary, Inverted to create alpha and then merge it with other channels.

Haris gravatar imageHaris ( 2014-07-10 03:33:17 -0600 )edit
3

answered 2014-10-01 18:26:30 -0600

crazymichel1 gravatar image

updated 2014-10-01 22:46:11 -0600

Haris gravatar image

Here is my working java code for Haris answer:

`

 /**

 * Make the black background of a PNG-Bitmap-Image transparent.
 * code based on example at http://j.mp/1uCxOV5
 * @Param image png bitmap image
 * @return output image
 */

private static Bitmap makeBlackTransparent(Bitmap image) {
    // convert image to matrix
    Mat src = new Mat(image.getWidth(), image.getHeight(), CvType.CV_8UC4);
    Utils.bitmapToMat(image, src);

    // init new matrices
    Mat dst = new Mat(image.getWidth(), image.getHeight(), CvType.CV_8UC4);
    Mat tmp = new Mat(image.getWidth(), image.getHeight(), CvType.CV_8UC4);
    Mat alpha = new Mat(image.getWidth(), image.getHeight(), CvType.CV_8UC4);

    // convert image to grayscale
    Imgproc.cvtColor(src, tmp, Imgproc.COLOR_BGR2GRAY);

    // threshold the image to create alpha channel with complete transparency in black background region and zero transparency in foreground object region.
    Imgproc.threshold(tmp, alpha, 100, 255, Imgproc.THRESH_BINARY);

    // split the original image into three single channel.
    List<Mat> rgb = new ArrayList<Mat>(3);
    Core.split(src, rgb);

    // Create the final result by merging three single channel and alpha(BGRA order)
    List<Mat> rgba = new ArrayList<Mat>(4);
    rgba.add(rgb.get(0));
    rgba.add(rgb.get(1));
    rgba.add(rgb.get(2));
    rgba.add(alpha);
    Core.merge(rgba, dst);

    // convert matrix to output bitmap
    Bitmap output = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(dst, output);
    return output;
}`
edit flag offensive delete link more
0

answered 2018-04-28 07:39:21 -0600

14051598-023 gravatar image

Why colors in output image are changed. I have used image of orange(fruit) and after applying this code of grabcut that orange(fruit)'s color has been changed into intense yellowImage I used is this .And output that I get is thisimage description

edit flag offensive delete link more
0

answered 2018-01-26 01:41:26 -0600

Use it. After using grabcut, the result background is transparent.

public Bitmap removeBackground(Bitmap bitmap) {
    //GrabCut part
    Mat img = new Mat();
    Utils.bitmapToMat(bitmap, img);

    int r = img.rows();
    int c = img.cols();
    Point p1 = new Point(c / 100, r / 100);
    Point p2 = new Point(c - c / 100, r - r / 100);
    Rect rect = new Rect(p1, p2);

    Mat mask = new Mat();
    Mat fgdModel = new Mat();
    Mat bgdModel = new Mat();

    Mat imgC3 = new Mat();
    Imgproc.cvtColor(img, imgC3, Imgproc.COLOR_RGBA2RGB);

    Imgproc.grabCut(imgC3, mask, rect, bgdModel, fgdModel, 5, Imgproc.
            GC_INIT_WITH_RECT);

    Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(3.0));
    Core.compare(mask, source/* GC_PR_FGD */, mask, Core.CMP_EQ);

    //This is important. You must use Scalar(255,255, 255,255), not Scalar(255,255,255)
    Mat foreground = new Mat(img.size(), CvType.CV_8UC3, new Scalar(255,
            255, 255,255));
    img.copyTo(foreground, mask);

    // convert matrix to output bitmap
    bitmap = Bitmap.createBitmap((int) foreground.size().width,
            (int) foreground.size().height,
            Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(foreground, bitmap);
    return bitmap;
}
edit flag offensive delete link more
-1

answered 2013-12-09 00:20:22 -0600

Joystna gravatar image

updated 2013-12-09 00:21:53 -0600

Hello Mr Haris,

can i get your help for my grabcut project.

please email me on [email protected]

Thank you

edit flag offensive delete link more

Comments

2

Better to post your problem here then every one can help you.

Haris gravatar imageHaris ( 2013-12-09 03:45:52 -0600 )edit

what would be the reason if this code still dont work ?

NomiYaqoob gravatar imageNomiYaqoob ( 2017-02-21 12:12:32 -0600 )edit

I am using an image over javacameraview

NomiYaqoob gravatar imageNomiYaqoob ( 2017-02-21 12:13:22 -0600 )edit

Question Tools

Stats

Asked: 2013-11-24 12:09:27 -0600

Seen: 33,165 times

Last updated: Oct 01 '14