android - 在 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();
}
}
解决方案
我终于找到了解决我的问题的方法。这是在用于 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();
}
推荐阅读
- vim - 如何在 Vim 中找到 hi-ColorColumn 的可用颜色
- python - python - 地理分箱 - 地理边界内的平均值
- python - 标签在模板中称为字符串
- c# - 如何在 MVC 视图页面中使用我的 c# 类文件中定义的枚举
- r - 运行脚本后,我在下面收到一条警告消息
- java - 如何解决Java Spring中日期的一日偏移问题
- javascript - 使用映射更改内部数组对象值与外部数组值
- node.js - 我可以在 Mongo DB 中使用点字符 (.) 作为字段名称吗?
- c# - 尝试创建多个唯一的短 URL
- javascript - React 使 axios 获取,返回错误:CORS 策略:请求的资源上不存在“Access-Control-Allow-Origin”标头