OpenCV Java,从图像获取感兴趣的区域 [英] OpenCV Java, Getting region of interest from image

查看:138
本文介绍了OpenCV Java,从图像获取感兴趣的区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试检测图像中的某个区域(矩形),并获取其上限和下限,但是我卡在了必须获取感兴趣区域的点上.

I am trying to detect a certain area(rectangle) in an image, and get its upper and lower bounds, but im stuck at the point where i have to get the Region of interest.

从这张图片开始:

我想像这样得到感兴趣的区域

I want to get the area of interest like so:

我转换了亚历山大·雷诺兹(Alexander Reynolds)回答的python代码

I converted the python code answered by Alexander Reynolds here, But i cant seem to view the result as I'm getting an error:

java.lang.IllegalArgumentException:bmp == null

java.lang.IllegalArgumentException: bmp == null

at

Utils.matToBitmap(roiMat,temp);

        bitmap = constructor.getBmp();
        Mat srcMat = new Mat();
        Utils.bitmapToMat(bitmap, srcMat);

        Mat hsvMat = new Mat();
        Imgproc.cvtColor(srcMat,hsvMat,Imgproc.COLOR_BGR2HSV);

        Mat roiMat;
        Range rowRange = new Range(95, 436); //95 837, top left// 436,837 top right,,//95 895,, btm left, //436, 895 btm right
        Range colRange = new Range(837, 895);
        roiMat = new Mat(hsvMat, colRange, rowRange); // public Mat(Mat m, Range rowRange, Range colRange)

        Utils.matToBitmap(roiMat, temp);
        ImageView imageView = (ImageView) findViewById(R.id.imageView);
        imageView.setImageBitmap(temp);
    }

推荐答案

您可以尝试调用此方法:

You can try call this method:

private Bitmap findRoi(Bitmap sourceBitmap) {
    Bitmap roiBitmap = null;
    Scalar green = new Scalar(0, 255, 0, 255);
    Mat sourceMat = new Mat(sourceBitmap.getWidth(), sourceBitmap.getHeight(), CvType.CV_8UC3);
    Utils.bitmapToMat(sourceBitmap, sourceMat);
    Mat roiTmp = sourceMat.clone();

    final Mat hsvMat = new Mat();
    sourceMat.copyTo(hsvMat);

    // convert mat to HSV format for Core.inRange()
    Imgproc.cvtColor(hsvMat, hsvMat, Imgproc.COLOR_RGB2HSV);

    Scalar lowerb = new Scalar(85, 50, 40);         // lower color border for BLUE
    Scalar upperb = new Scalar(135, 255, 255);      // upper color border for BLUE
    Core.inRange(hsvMat, lowerb, upperb, roiTmp);   // select only blue pixels

    // find contours
    List<MatOfPoint> contours = new ArrayList<>();
    List<RotatedRect> boundingRects = new ArrayList<>();
    Imgproc.findContours(roiTmp, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);

    // find appropriate bounding rectangles
    for (MatOfPoint contour : contours) {
        MatOfPoint2f areaPoints = new MatOfPoint2f(contour.toArray());
        RotatedRect boundingRect = Imgproc.minAreaRect(areaPoints);

        double rectangleArea = boundingRect.size.area();

        // test min ROI area in pixels
        if (rectangleArea > 400) {
            Point rotated_rect_points[] = new Point[4];
            boundingRect.points(rotated_rect_points);

            Rect rect = Imgproc.boundingRect(new MatOfPoint(rotated_rect_points));

            // test horizontal ROI orientation
            if (rect.width > rect.height) {
                Imgproc.rectangle(sourceMat, rect.tl(), rect.br(), green, 3);
            }
        }
    }

    roiBitmap = Bitmap.createBitmap(sourceMat.cols(), sourceMat.rows(), Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(sourceMat, roiBitmap);
    return roiBitmap;
}

例如,通过单击按钮

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (!OpenCVLoader.initDebug()) {
        Log.d(TAG, "OpenCVLoader.initDebug() - ERROR");
    } else {
        Log.d(TAG, "OpenCVLoader.initDebug() - OK");
    }

    mImageView = (ImageView) findViewById(R.id.source_image_view);
    mProcessButton = (Button) findViewById(R.id.process_button);

    mProcessButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Bitmap bmSource = BitmapFactory.decodeResource(getResources(), R.drawable.test);
            Bitmap bmRoi = findRoi(bmSource);

            mImageView.setImageBitmap(bmRoi);
        }
    });
}

activity_main.xml是:

<?xml version="1.0" encoding="utf-8"?>
<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="com.test.opencv.opencvstackoverflow.MainActivity">

    <ImageView
        android:id="@+id/source_image_view"
        android:layout_above="@+id/process_button"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitCenter"
        app:srcCompat="@drawable/test"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"
        />

    <Button
        android:id="@+id/process_button"
        android:text="Find ROI"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentEnd="true"/>

</RelativeLayout>

您将得到类似的结果:

NB!也许您应该根据 Alexander Reynolds所述(根据您的了解),根据您的状况调整Scalar lowerbupperb. 此处:

NB! Maybe You should adjust Scalar lowerb and upperb according to Your condition as described (as You know) by Alexander Reynolds here:

此ROI仅包含蓝色像素,因此我可以找到平均蓝色值, 蓝色值的标准偏差用作 inRange().

This ROI contains only blue pixels, so I can find the mean blue value, and the standard deviation of the blue values to use as the values for inRange().

mu, sig = cv2.meanStdDev(roi)
a = 9

blue_mask = cv2.inRange(hsv, mu-a*sig, mu+a*sig)

Micka .

400可能还需要根据ROI的最小面积进行调整.

Also 400 in if (rectangleArea > 400) may needs to be adjusted according minimal area of ROI.

这篇关于OpenCV Java,从图像获取感兴趣的区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆