首页 > 解决方案 > 在 OpenCV 中应用 GrabCut 算法后获取相同的图像

问题描述

我已经使用 GrabCut 算法分割我的图像我的图像 以检测我的图像中的柑橘(水果)作为前景并从背景中减去它。为此,首先我必须在我的对象(水果)周围选择 2 个点,用于在我的对象(水果)周围绘制矩形,然后我应用抓取算法来减去我的图像的背景。问题是在应用抓取切割算法后,我得到了相同的图像(没有任何背景减法的对象检测)。Bellow是我的Android代码(OpenCV)

public boolean imgProcessingButton(View view) {

            if (mCurrentPhotoPath != null)
                targetChose = false;
            mImageView.setOnTouchListener(new View.OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        if (touchCount == 0) {
                            tl.x = event.getX();
                            tl.y = event.getY();
                            touchCount++;
                        }
                        else if (touchCount == 1) {
                            br.x = event.getX();
                            br.y = event.getY();

                            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);
                            tmpCanvas.drawRect(new RectF((float) tl.x, (float) tl.y, (float) br.x, (float) br.y),
                                    rectPaint);
                            mImageView.setImageDrawable(new BitmapDrawable(getResources(), tmpBm));

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

                    return true;
                }
            });

            return true;}
public boolean imgCutButton(View view) {
            if (mCurrentPhotoPath != null && targetChose) {
                new ProcessImageTask().execute();
                targetChose = false;
            }
            return true;
    }

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);
        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 , dst);
        //displayImage(dst);
        return 0;
    }

    @Override
    protected void onPostExecute(Integer result) {
        super.onPostExecute(result);

        Bitmap jpg = BitmapFactory
                .decodeFile(mCurrentPhotoPath );

        imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
        imageView.setAdjustViewBounds(true);
        imageView.setPadding(2, 2, 2, 2);
        imageView.setImageBitmap(jpg);
        imageView.invalidate();

        dlg.dismiss();
    }
}

标签: androidopencvimage-processingimage-segmentationopencv4android

解决方案


我终于找到了解决我的问题的方法。这是在用于 android 的 opencv 中使用 Grabcut 算法抓取图像剪切背景的代码。

public void grabcutAlgo(Bitmap bit){
Bitmap b = bit.copy(Bitmap.Config.ARGB_8888, true);
Point tl=new Point();
Point br=new Point();
//GrabCut part
Mat img = new Mat();
Utils.bitmapToMat(b, img);
Imgproc.cvtColor(img, img, Imgproc.COLOR_RGBA2RGB);

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);
//Rect rect = new Rect(tl, br);
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();


Imgproc.grabCut(img, firstMask, rect, bgModel, fgModel, 5, Imgproc.GC_INIT_WITH_RECT);
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);
Bitmap grabCutImage = Bitmap.createBitmap(dst.cols(), dst.rows(), Bitmap.Config.ARGB_8888);
Bitmap processedImage = Bitmap.createBitmap(dst.cols(), dst.rows(), Bitmap.Config.RGB_565);
Utils.matToBitmap(dst, grabCutImage);
dst.copyTo(sampleImage);
imageView.setImageBitmap(grabCutImage);
firstMask.release();
source.release();
bgModel.release();
fgModel.release();

}


推荐阅读