首页 > 解决方案 > 检测矩形并将图像裁剪成碎片Android OpenCV

问题描述

嗨,我正在使用 Java 开发一个小型 Android 项目,其中一个功能是检测矩形(包含数据)并将图像裁剪成几个不同的图像(取决于图像包含的矩形。)然后将图像存储在内部存储(用于其他过程)。

我是openCV的新手。我还没有做过任何 openCV 项目。有没有人可以帮助我指导我如何实现这一目标?我找到了一些帮助,但它们都在 python 中,我的知识很少。提前致谢。

附加图片

标签: javaandroidopencvimage-processing

解决方案


在无数次尝试和错误之后,我找到了检测矩形的解决方案。我仍然需要进行裁剪部分,但这并不难。感谢这篇文章使用 openCv 在 java 中检查轮廓。 这就是我所做的——

public class ProcessesdResult extends AppCompatActivity {

   TextView tvProcessedText;
   Bitmap image;
   String photoPath;
   Mat imageMat;
   ImageView ProcessedImage;


   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       OpenCVLoader.initDebug();

       setContentView(R.layout.activity_processesd_result);

       Intent intenttakeattendance = getIntent();
       String fname = intenttakeattendance.getStringExtra("fname");

       String root = Environment.getExternalStorageDirectory().toString();
       File myDir = new File(root);

       photoPath = myDir+"/sams_images/"+ fname;
       BitmapFactory.Options options = new BitmapFactory.Options();
       options.inPreferredConfig = Bitmap.Config.ARGB_8888;
       image = BitmapFactory.decodeFile(photoPath, options);

       ProcessedImage = findViewById(R.id.processedimage);

       // tvProcessedText = findViewById(R.id.tvprocessedtext);
       //imageProcess(image);
       imageCrop(image);
   }


   public void imageCrop(Bitmap bitmap){

       imageMat=new Mat();

       Utils.bitmapToMat(bitmap,imageMat);
       Mat imgSource=imageMat.clone();

       Mat imageHSV = new Mat(imgSource.size(), CvType.CV_8UC4);
       Mat imageBlurr = new Mat(imgSource.size(),CvType.CV_8UC4);
       Mat imageA = new Mat(imgSource.size(), CvType.CV_32F);
       Imgproc.cvtColor(imgSource, imageHSV, Imgproc.COLOR_BGR2GRAY);
       Imgproc.GaussianBlur(imageHSV, imageBlurr, new Size(5,5), 0);
       Imgproc.adaptiveThreshold(imageBlurr, imageA, 255,Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY,7, 5);

       List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
       Imgproc.findContours(imageA, contours, new Mat(), Imgproc.RETR_LIST,Imgproc.CHAIN_APPROX_SIMPLE);

       Vector<Mat> rectangles = new Vector<Mat>();

       for(int i=0; i< contours.size();i++){
           if (Imgproc.contourArea(contours.get(i)) > 50 )
             {
               Rect rect = Imgproc.boundingRect(contours.get(i));
               if ((rect.height > 30 && rect.height < 120) && (rect.width > 120 && rect.width < 500))
                 {
                    Rect rec = new Rect(rect.x, rect.y, rect.width, rect.height);
                    Mat roi = imageMat.submat(rec);
                    String filename = myDir.toString() + "/" + i + ".png";
                    Imgcodecs.imwrite(filename, roi);
                    rectangles.add(new Mat(imgSource, rec));
                    Imgproc.rectangle(imgSource, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 0, 255));

                 }
            }
       }

       Bitmap analyzed=Bitmap.createBitmap(imgSource.cols(),imgSource.rows(),Bitmap.Config.ARGB_8888);
       Utils.matToBitmap(imgSource,analyzed);

       saveTempImage(analyzed);
       ProcessedImage.setImageBitmap(analyzed);

   }


/*------------------------------------ Store Image -------------------------------------------*/
   public void saveTempImage(Bitmap bitmap) {
        if (isExternalStorageWritable()) {
            saveImage(bitmap);
        }else{
               Toast.makeText(this, "Please provide permission to write on the Storage!", Toast.LENGTH_SHORT).show();
        }
    }

    private void saveImage(Bitmap finalBitmap) {

        String root = Environment.getExternalStorageDirectory().toString();
        File myDir = new File(root + "/sams_images");

        if (! myDir.exists()){
            myDir.mkdir();
           // If you require it to make the entire directory path including parents,
           // use directory.mkdirs(); here instead.
       }

       String  timeStamp = new SimpleDateFormat("yyyyMMdd_HHmm").format(new Date());
       String fname = timeStamp +".jpg";

       File file = new File(myDir, fname);
       if (file.exists()) file.delete ();
       try {
           FileOutputStream out = new FileOutputStream(file);
           finalBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
           out.flush();
           out.close();

       } catch (Exception e) {
           e.printStackTrace();
         }
   }

   /* Checks if external storage is available for read and write */
   public boolean isExternalStorageWritable() {
       String state = Environment.getExternalStorageState();
       if (Environment.MEDIA_MOUNTED.equals(state)) {
           return true;
       }
       return false;
   }
/*------------------------------------ ************* -----------------------------------------*/


}

这是结果

但是还有一个问题。为此,我得到了内部 vontour 和外部轮廓。我尝试使用 RECT_EXTERNAL 但根本没有检测到轮廓..


推荐阅读