嗨,我正在尝试从开放的简历中实现抓取剪切算法。我从本地存储中选择图像,然后对其进行抓取剪切。问题是,当我在位图上调用设置图像位图时,在进行抓取剪切后,图像未加载到图像视图中。这是完整的代码。我实际上对open cv及其库并不十分熟悉,所以我发现它是从git hub获得的。其开放的cv 3.4.1
MainActivity:
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();
Log.i(TAG,"hmmm? its done ");
dlg.dismiss();
}
}
当我尝试将抓取切割的位图设置为图像视图时,在后执行方法中出现问题。根据上述日志标签,位图不为null。我似乎在日志中也找不到任何错误。
activity_main:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imgDisplay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
我意识到我得到了一张很小的图片,有点像一个坏点,因此为什么位图不为空。但是,在具有开放cv 2.x版本的Windows com上运行此代码可以使我获得截取的图像。