Ask Your Question

Revision history [back]

android grab cut open cv not getting bit map displayed in image view.

I am running a grab cut algorithm where the user can choose an image he wants to grab cut in his external storage on android phone. Problem is during the onPostExecute method of async task I get a super tiny bitmap that looks somewhat like a dead pixel and I can't even see the image. I have tried the same code on open cv 2.x version and it worked fine but when I switch over to open cv 3.4.0 I can't see the result being displayed.

MainActivity.

private int STORAGE_PERMISSION_CODE = 1;
private static String TAG = "GrabCutActivity";
static final int REQUEST_OPEN_IMAGE = 1;
String mCurrentPhotoPath;
Bitmap mBitmap;
ImageView mImageView;
int touchCount = 0;
Point tl;
Point br;
boolean targetChose = false;
ProgressDialog dlg;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (!OpenCVLoader.initDebug()) {
        Log.e(this.getClass().getSimpleName(), "  OpenCVLoader.initDebug(), not working.");
    } else {
        Log.d(this.getClass().getSimpleName(), "  OpenCVLoader.initDebug(), working.");
    }


    mImageView = findViewById(R.id.imgDisplay);
    dlg = new ProgressDialog(this);
    tl = new Point();
    br = new Point();
    if (!OpenCVLoader.initDebug()) {
        Log.i(TAG,"load successful");
    }
}

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main,menu);
    return true;
}




private void setPic() {
    // use to compress image
    int targetW = mImageView.getWidth();
    int targetH = mImageView.getHeight();

    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    int scaleFactor = Math.min(photoW / targetW, photoH / targetH);

    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    mBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
    mImageView.setImageBitmap(mBitmap);
    Log.i(TAG,"set pic here");

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case REQUEST_OPEN_IMAGE:
            if (resultCode == RESULT_OK) {
                Uri imgUri = data.getData();
                String[] filePathColumn = { MediaStore.Images.Media.DATA };

                // used to get file path from uri.
                Cursor cursor = getContentResolver().query(imgUri, filePathColumn,
                        null, null, null);
                cursor.moveToFirst();

                int colIndex = cursor.getColumnIndex(filePathColumn[0]);
                mCurrentPhotoPath = cursor.getString(colIndex);
                Log.i(TAG,mCurrentPhotoPath);
                cursor.close();
                setPic();
            }
            break;
    }
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    switch (id) {
        case R.id.action_open_img:
            if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE )==
                    PackageManager.PERMISSION_GRANTED) {
                Intent getPictureIntent = new Intent(Intent.ACTION_GET_CONTENT);
                getPictureIntent.setType("image/*");
                Intent pickPictureIntent = new Intent(Intent.ACTION_PICK,
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                Intent chooserIntent = Intent.createChooser(getPictureIntent, "Select Image");
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[]{
                        pickPictureIntent
                });
                startActivityForResult(chooserIntent, REQUEST_OPEN_IMAGE);
            } else {
                requestStoragePermission();
                Toast.makeText(MainActivity.this, "No permission?", Toast.LENGTH_SHORT).show();
            }
            return true;
        case R.id.action_choose_target:
            if (mCurrentPhotoPath != null)
                targetChose = false;
            mImageView.setOnTouchListener(new View.OnTouchListener() {

                //what happens when user touches the image
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    // event.getAction() returns what type of action performed by the user
                    // ACTION_DOWN means make your finger touch the screen.
                    // ACTION_UP opposite
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        if (touchCount == 0) {
                            tl.x = event.getX();
                            tl.y = event.getY();

                            Log.i(TAG,"x " + tl.x + " y " + tl.y);
                            touchCount++;
                        }
                        else if (touchCount == 1) {
                            br.x = event.getX();
                            br.y = event.getY();
                            Log.i(TAG,"br.x " + br.x + " br.y " + br.y);
                            Paint rectPaint = new Paint();
                            rectPaint.setARGB(255, 255, 0, 0);
                            rectPaint.setStyle(Paint.Style.STROKE);
                            rectPaint.setStrokeWidth(3);
                            Bitmap tmpBm = Bitmap.createBitmap(mBitmap.getWidth(),
                                    mBitmap.getHeight(), Bitmap.Config.RGB_565);
                            Canvas tmpCanvas = new Canvas(tmpBm);

                            tmpCanvas.drawBitmap(mBitmap, 0, 0, null);
                            tl.x = tl.x * (float)tmpCanvas.getWidth() / v.getRight();
                            tl.y = tl.y * (float)tmpCanvas.getHeight() / v.getBottom();
                            br.x = br.x * (float)tmpCanvas.getWidth() / v.getRight();
                            br.y = br.y * (float)tmpCanvas.getHeight() / v.getBottom();
                            tmpCanvas.drawRect(new RectF((float) tl.x, (float) tl.y, (float) br.x, (float) br.y),
                                    rectPaint);
                            Log.i(TAG,"tl x: " + (float)tl.x + " tl.y " + (float)tl.y + " br.x " + (float)br.x + " br.y " + (float)br.y);
                            mImageView.setImageDrawable(new BitmapDrawable(getResources(), tmpBm));

                            targetChose = true;
                            touchCount = 0;
                            mImageView.setOnTouchListener(null);
                        }
                    }
                    return true;
                }
            });

            return true;
        case R.id.action_cut_image:
            if (mCurrentPhotoPath != null && targetChose) {
                new ProcessImageTask().execute();
                targetChose = false;
            }
            return true;
    }

    return super.onOptionsItemSelected(item);
}

private void requestStoragePermission() {
    ActivityCompat.requestPermissions(MainActivity.this,
            new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},STORAGE_PERMISSION_CODE);
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == STORAGE_PERMISSION_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(MainActivity.this,"Permission Granted",Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(MainActivity.this,"permission denied",Toast.LENGTH_SHORT).show();
        }

    }
}

private class ProcessImageTask extends AsyncTask<Integer, Integer, Integer> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        dlg.setMessage("Processing Image...");
        dlg.setCancelable(false);
        dlg.setIndeterminate(true);
        dlg.show();
    }

    @Override
    protected Integer doInBackground(Integer... params) {
        Mat img = Imgcodecs.imread(mCurrentPhotoPath);
        Mat background = new Mat(img.size(), CvType.CV_8UC3,
                new Scalar(255, 255, 255));
        Mat firstMask = new Mat();
        Mat bgModel = new Mat();
        Mat fgModel = new Mat();
        Mat mask;
        Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(Imgproc.GC_PR_FGD));
        Mat dst = new Mat();
        Rect rect = new Rect(tl, br);

        Imgproc.grabCut(img, firstMask, rect, bgModel, fgModel,
                5, Imgproc.GC_INIT_WITH_RECT);
        Log.i(TAG,"grab cut works here");
        Core.compare(firstMask, source, firstMask, Core.CMP_EQ);

        Mat foreground = new Mat(img.size(), CvType.CV_8UC3,
                new Scalar(255, 255, 255));
        img.copyTo(foreground, firstMask);

        Scalar color = new Scalar(255, 0, 0, 255);
        Imgproc.rectangle(img, tl, br, color);

        Mat tmp = new Mat();
        Imgproc.resize(background, tmp, img.size());
        background = tmp;
        mask = new Mat(foreground.size(), CvType.CV_8UC1,
                new Scalar(255, 255, 255));

        Imgproc.cvtColor(foreground, mask, Imgproc.COLOR_BGR2GRAY);
        Imgproc.threshold(mask, mask, 254, 255, Imgproc.THRESH_BINARY_INV);
        System.out.println();
        Mat vals = new Mat(1, 1, CvType.CV_8UC3, new Scalar(0.0));
        background.copyTo(dst);

        background.setTo(vals, mask);

        Core.add(background, foreground, dst, mask);

        firstMask.release();
        source.release();
        bgModel.release();
        fgModel.release();
        vals.release();

        Imgcodecs.imwrite(mCurrentPhotoPath + ".png", dst);
        Log.i(TAG,"grabcut done");

        return 0;
    }

    @Override
    protected void onPostExecute(Integer result) {
        super.onPostExecute(result);
        Log.i(TAG,"postExecute");

        Bitmap jpg = BitmapFactory
                .decodeFile(mCurrentPhotoPath + ".png");
        boolean isNull = jpg == null;
        Log.i(TAG,"bitmap is " + isNull);

        mImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
        mImageView.setAdjustViewBounds(true);
        mImageView.setPadding(2, 2, 2, 2);
        mImageView.setImageBitmap(jpg);
        mImageView.invalidate();
        mImageView.setVisibility(View.VISIBLE);

        Log.i(TAG,"hmmm? its done ");
        dlg.dismiss();
    }
}

I checked that my bitmap is not null its just super small, I am also not sure how to go about resolving this issue either.

android grab cut open cv not getting bit map displayed in image view.

I am running a grab cut algorithm where the user can choose an image he wants to grab cut in his external storage on android phone. Problem is during the onPostExecute method of async task I get a super tiny bitmap that looks somewhat like a dead pixel and I can't even see the image. I have tried the same code on open cv 2.x version and it worked fine but when I switch over to open cv 3.4.0 I can't see the result being displayed.

MainActivity.

private int STORAGE_PERMISSION_CODE = 1;
private static String TAG = "GrabCutActivity";
static final int REQUEST_OPEN_IMAGE = 1;
String mCurrentPhotoPath;
Bitmap mBitmap;
ImageView mImageView;
int touchCount = 0;
Point tl;
Point br;
boolean targetChose = false;
ProgressDialog dlg;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (!OpenCVLoader.initDebug()) {
        Log.e(this.getClass().getSimpleName(), "  OpenCVLoader.initDebug(), not working.");
    } else {
        Log.d(this.getClass().getSimpleName(), "  OpenCVLoader.initDebug(), working.");
    }


    mImageView = findViewById(R.id.imgDisplay);
    dlg = new ProgressDialog(this);
    tl = new Point();
    br = new Point();
    if (!OpenCVLoader.initDebug()) {
        Log.i(TAG,"load successful");
    }
}

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main,menu);
    return true;
}




private void setPic() {
    // use to compress image
    int targetW = mImageView.getWidth();
    int targetH = mImageView.getHeight();

    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    int scaleFactor = Math.min(photoW / targetW, photoH / targetH);

    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    mBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
    mImageView.setImageBitmap(mBitmap);
    Log.i(TAG,"set pic here");

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case REQUEST_OPEN_IMAGE:
            if (resultCode == RESULT_OK) {
                Uri imgUri = data.getData();
                String[] filePathColumn = { MediaStore.Images.Media.DATA };

                // used to get file path from uri.
                Cursor cursor = getContentResolver().query(imgUri, filePathColumn,
                        null, null, null);
                cursor.moveToFirst();

                int colIndex = cursor.getColumnIndex(filePathColumn[0]);
                mCurrentPhotoPath = cursor.getString(colIndex);
                Log.i(TAG,mCurrentPhotoPath);
                cursor.close();
                setPic();
            }
            break;
    }
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    switch (id) {
        case R.id.action_open_img:
            if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE )==
                    PackageManager.PERMISSION_GRANTED) {
                Intent getPictureIntent = new Intent(Intent.ACTION_GET_CONTENT);
                getPictureIntent.setType("image/*");
                Intent pickPictureIntent = new Intent(Intent.ACTION_PICK,
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                Intent chooserIntent = Intent.createChooser(getPictureIntent, "Select Image");
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[]{
                        pickPictureIntent
                });
                startActivityForResult(chooserIntent, REQUEST_OPEN_IMAGE);
            } else {
                requestStoragePermission();
                Toast.makeText(MainActivity.this, "No permission?", Toast.LENGTH_SHORT).show();
            }
            return true;
        case R.id.action_choose_target:
            if (mCurrentPhotoPath != null)
                targetChose = false;
            mImageView.setOnTouchListener(new View.OnTouchListener() {

                //what happens when user touches the image
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    // event.getAction() returns what type of action performed by the user
                    // ACTION_DOWN means make your finger touch the screen.
                    // ACTION_UP opposite
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        if (touchCount == 0) {
                            tl.x = event.getX();
                            tl.y = event.getY();

                            Log.i(TAG,"x " + tl.x + " y " + tl.y);
                            touchCount++;
                        }
                        else if (touchCount == 1) {
                            br.x = event.getX();
                            br.y = event.getY();
                            Log.i(TAG,"br.x " + br.x + " br.y " + br.y);
                            Paint rectPaint = new Paint();
                            rectPaint.setARGB(255, 255, 0, 0);
                            rectPaint.setStyle(Paint.Style.STROKE);
                            rectPaint.setStrokeWidth(3);
                            Bitmap tmpBm = Bitmap.createBitmap(mBitmap.getWidth(),
                                    mBitmap.getHeight(), Bitmap.Config.RGB_565);
                            Canvas tmpCanvas = new Canvas(tmpBm);

                            tmpCanvas.drawBitmap(mBitmap, 0, 0, null);
                            tl.x = tl.x * (float)tmpCanvas.getWidth() / v.getRight();
                            tl.y = tl.y * (float)tmpCanvas.getHeight() / v.getBottom();
                            br.x = br.x * (float)tmpCanvas.getWidth() / v.getRight();
                            br.y = br.y * (float)tmpCanvas.getHeight() / v.getBottom();
                            tmpCanvas.drawRect(new RectF((float) tl.x, (float) tl.y, (float) br.x, (float) br.y),
                                    rectPaint);
                            Log.i(TAG,"tl x: " + (float)tl.x + " tl.y " + (float)tl.y + " br.x " + (float)br.x + " br.y " + (float)br.y);
                            mImageView.setImageDrawable(new BitmapDrawable(getResources(), tmpBm));

                            targetChose = true;
                            touchCount = 0;
                            mImageView.setOnTouchListener(null);
                        }
                    }
                    return true;
                }
            });

            return true;
        case R.id.action_cut_image:
            if (mCurrentPhotoPath != null && targetChose) {
                new ProcessImageTask().execute();
                targetChose = false;
            }
            return true;
    }

    return super.onOptionsItemSelected(item);
}

private void requestStoragePermission() {
    ActivityCompat.requestPermissions(MainActivity.this,
            new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},STORAGE_PERMISSION_CODE);
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == STORAGE_PERMISSION_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(MainActivity.this,"Permission Granted",Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(MainActivity.this,"permission denied",Toast.LENGTH_SHORT).show();
        }

    }
}

private class ProcessImageTask extends AsyncTask<Integer, Integer, Integer> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        dlg.setMessage("Processing Image...");
        dlg.setCancelable(false);
        dlg.setIndeterminate(true);
        dlg.show();
    }

    @Override
    protected Integer doInBackground(Integer... params) {
        Mat img = Imgcodecs.imread(mCurrentPhotoPath);
        Mat background = new Mat(img.size(), CvType.CV_8UC3,
                new Scalar(255, 255, 255));
        Mat firstMask = new Mat();
        Mat bgModel = new Mat();
        Mat fgModel = new Mat();
        Mat mask;
        Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(Imgproc.GC_PR_FGD));
        Mat dst = new Mat();
        Rect rect = new Rect(tl, br);

        Imgproc.grabCut(img, firstMask, rect, bgModel, fgModel,
                5, Imgproc.GC_INIT_WITH_RECT);
        Log.i(TAG,"grab cut works here");
        Core.compare(firstMask, source, firstMask, Core.CMP_EQ);

        Mat foreground = new Mat(img.size(), CvType.CV_8UC3,
                new Scalar(255, 255, 255));
        img.copyTo(foreground, firstMask);

        Scalar color = new Scalar(255, 0, 0, 255);
        Imgproc.rectangle(img, tl, br, color);

        Mat tmp = new Mat();
        Imgproc.resize(background, tmp, img.size());
        background = tmp;
        mask = new Mat(foreground.size(), CvType.CV_8UC1,
                new Scalar(255, 255, 255));

        Imgproc.cvtColor(foreground, mask, Imgproc.COLOR_BGR2GRAY);
        Imgproc.threshold(mask, mask, 254, 255, Imgproc.THRESH_BINARY_INV);
        System.out.println();
        Mat vals = new Mat(1, 1, CvType.CV_8UC3, new Scalar(0.0));
        background.copyTo(dst);

        background.setTo(vals, mask);

        Core.add(background, foreground, dst, mask);

        firstMask.release();
        source.release();
        bgModel.release();
        fgModel.release();
        vals.release();

        Imgcodecs.imwrite(mCurrentPhotoPath + ".png", dst);
        Log.i(TAG,"grabcut done");

        return 0;
    }

    @Override
    protected void onPostExecute(Integer result) {
        super.onPostExecute(result);
        Log.i(TAG,"postExecute");

        Bitmap jpg = BitmapFactory
                .decodeFile(mCurrentPhotoPath + ".png");
        boolean isNull = jpg == null;
        Log.i(TAG,"bitmap is " + isNull);

        mImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
        mImageView.setAdjustViewBounds(true);
        mImageView.setPadding(2, 2, 2, 2);
        mImageView.setImageBitmap(jpg);
        mImageView.invalidate();
        mImageView.setVisibility(View.VISIBLE);

        Log.i(TAG,"hmmm? its done ");
        dlg.dismiss();
    }
}

I checked that my bitmap is not null its just super small, I am also not sure how to go about resolving this issue either.