OpenCV Java,从图像中获取感兴趣的区域

时间:2017-08-08 07:04:39

标签: java android opencv

我正在尝试检测图像中的某个区域(矩形),并获得其上限和下限,但即时卡在我必须获得感兴趣区域的位置。

从这张图片开始:

Starting image

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

Blue ROI

我转换了Alexander Reynolds here回答的python代码, 但我似乎无法查看结果,因为我收到了错误:

  

java.lang.IllegalArgumentException:bmp == null

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);
    }

1 个答案:

答案 0 :(得分:3)

您可以尝试调用此方法:

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>

你将得到类似的东西:

enter image description here

NB!也许您应该根据Alexander Reynolds here所述的条件(如您所知)调整Scalar lowerbupperb

  

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

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

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

Micka there

400中的if (rectangleArea > 400)也可能需要根据投资回报率的最小区域进行调整。