java opencv检测和裁剪圆形/椭圆形

wr98u20j  于 2021-06-29  发布在  Java
关注(0)|答案(0)|浏览(303)

我正在尝试检测和裁剪不同尺寸的圆形/椭圆形。
这是一个图像的例子,我正试图做检测和croping。输入图像
结果我试图在前面提到的图像是3个裁剪图像
像这样:
分段部分1、分段部分2、分段部分3
另一个图像可能是这样的:不同的图像
就像上一张图片一样,我也在尝试对这张图片做同样的处理。形状比第一个小得多。
这可以通过算法实现吗?或者我应该寻找一个类似机器学习的解决方案吗?
注:最终图像已应用以下过滤器:高斯模糊,灰度,阈值,轮廓和形态膨胀。
[编辑]
我编写的代码(未按预期工作):
findreference()在图像中间找到一个形状并返回其矩形。

private Rect findReference(Mat inputImage) {
        // clone the image
        Mat original = inputImage.clone();

        // find the center of the image
        double[] centers = {(double)inputImage.width()/2, (double)inputImage.height()/2};
        Point image_center = new Point(centers);

        // finding the contours
        ArrayList<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        Mat hierarchy = new Mat();
        Imgproc.findContours(inputImage, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

        // finding best bounding rectangle for a contour whose distance is closer to the image center that other ones
        double d_min = Double.MAX_VALUE;
        Rect rect_min = new Rect();

        for (MatOfPoint contour : contours) {
            Rect rec = Imgproc.boundingRect(contour);

            // find the best candidates
            if (rec.height > inputImage.height()/2 & rec.width > inputImage.width()/2){
                continue;
            }

            Point pt1 = new Point((double)rec.x, (double)rec.y);
            Point center = new Point(rec.x+(double)(rec.width)/2, rec.y + (double)(rec.height)/2);
            double d = Math.sqrt(Math.pow((double)(pt1.x-image_center.x),2) + Math.pow((double)(pt1.y -image_center.y), 2));
            if (d < d_min)
            {
                d_min = d;
                rect_min = rec;
            }

        }
//        showReference( rect_min, original);

        return rect_min;
    }

我使用矩形作为参考,创建了一个大的和一个小的,这样类似的形状适合在尺寸更小和更大的矩形。
findallellipses()尝试在更小和更大的矩形中找到相似的形状。然后在找到的形状周围画椭圆。

private Mat findAllEllipses(Rect referenceRect, Mat inputImage) {
        float per = 0.5f;
        float perSquare = 0.05f;

        Rect biggerRect = new Rect();
        Rect smallerRect = new Rect();

        biggerRect.width = (int) (referenceRect.width / per);
        biggerRect.height = (int) (referenceRect.height / per);

        smallerRect.width = (int) (referenceRect.width * per);
        smallerRect.height = (int) (referenceRect.height * per);

        System.out.println("reference rectangle height: " + referenceRect.height + " width: " + referenceRect.width);
        System.out.println("[" + 0 +"]: biggerRect.height: " + biggerRect.height + " biggerRect.width: " + biggerRect.width);
        System.out.println("[" + 0 +"]: smallerRect.height: " + smallerRect.height + " smallerRect.width: " + smallerRect.width);

        //Finding Contours
        List<MatOfPoint> contours = new ArrayList<>();
        Mat hierarchey = new Mat();
        Imgproc.findContours(inputImage, contours, hierarchey, Imgproc.RETR_TREE,
                Imgproc.CHAIN_APPROX_SIMPLE);

        System.out.println("the numbers of found contours is: " + contours.size());
        int sum = 0;
        //Empty rectangle
        RotatedRect[] rec = new RotatedRect[contours.size()];
        for (int i = 0; i < contours.size(); i++) {
            rec[i] = new RotatedRect();
            if(contours.get(i).toArray().length >= 5 ){
                Rect foundRect = Imgproc.boundingRect(contours.get(i));
//                Rect foundBigger = new Rect();
//                Rect foundSmaller = new Rect();
//
//                foundBigger.width = (int) (foundBigger.width + foundBigger.width * per);
//                foundBigger.height = (int) (foundBigger.height + foundBigger.height * per);
//
//                foundSmaller.width = (int) (foundRect.width - foundRect.width * per);
//                foundSmaller.height = (int) (foundRect.height - foundRect.height * per);
                if (
                         (biggerRect.height >= foundRect.height && biggerRect.width >= foundRect.width)
                         && (smallerRect.height <= foundRect.height && smallerRect.width <= foundRect.width)
                         && (((foundRect.width - foundRect.width * perSquare) <= foundRect.height) && ((foundRect.width + foundRect.width * perSquare) >= foundRect.height))
                         && (((foundRect.height - foundRect.height * perSquare) <= foundRect.width) && ((foundRect.height + foundRect.height * perSquare) >= foundRect.width))
                ) {

                    System.out.println("[" + i +"]: foundRect.width: " + foundRect.width + " foundRect.height: " + foundRect.height);
                    System.out.println("----------------");
                    rec[i] = Imgproc.fitEllipse(new MatOfPoint2f(contours.get(i).toArray()));
                    sum++;
                }
            }

            Scalar color_elli = new Scalar(190, 0, 0);
            Imgproc.ellipse(inputImage, rec[i], color_elli, 5);
        }
        System.out.println("found ellipses: " + sum);

//        trytest(ImageUtils.doResizeMat(outputImage),0,0);
        return inputImage;
    }

不幸的是,有几个变量被硬编码到方法中。
这是用来制作更小和更大的矩形(用作百分比)

float per = 0.5f;

persquare用于使形状更接近正方形(宽度和高度波动)

float perSquare = 0.05f;

这段代码可能适用于某些图像,而在其他图像上找不到单个形状,就像我提到的,这些形状是圆形/椭圆形的,大小不同。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题