java - OpenCV、安卓 : color detection from particular area or portion of an image?

标签 java android opencv bitmap

我想检测黑色物体下方的整个区域。

我已经成功地获得了黑色物体下方的矩形区域,如下所示

    Point leftPoint = new Point(0,yValueBlack); //far left, black object height
    Point rightPoint = new Point(sourceBitmap.getWidth(),sourceBitmap.getHeight()); //btm right of entire bitmap

    Rect bottomRect = new Rect(leftPoint,rightPoint);

由此Rect bottomRect = new Rect(leftPoint,rightPoint); 是我想要检测绿色 strip 的区域,如图所示。这是为了防止应用程序搜索图片上方的任何内容并在其他对象位于框架中时导致错误。

我有一个由边界矩形包围的黑色对象的位图,我只想检测 Rect bottomRect = new Rect(leftPoint,rightPoint); 从该位图中绘制绿色 strip 的边界矩形。

我定义垫子尺寸的方式是这样的 Mat sourceMat = new Mat(sourceBitmap.getWidth(), sourceBitmap.getHeight(), CvType.CV_8UC3);

但是,当我尝试使用相同的方法来定义我的垫子尺寸以适合黑色对象下方的矩形区域时,如下所示: Mat croppedMat = new Mat(bottomRect, CvType.CV_8UC3); 它会给我一个错误。

这就是我认为的样子:

  1. Detect and draw bounding rectangle around black object (Done)

  2. Find rectangle area(RAT) below black object

  3. Detect and draw bounding rectangle around green object within the RAT(I can detect and draw bounding rectangle for green object, cant seem to do it WITHIN the specified RAT)

  4. Display bitmap like shown in image below(done)

enter image description here

编辑:

检测到黑色物体后,绘制边界矩形,当前位于 roiBitmap 。裁剪roiBitmap并尝试在 imageview 中显示它(我将从最终裁剪掉的位图中检测到绿色胶带。)给我错误:

CvException [org.opencv.core.CvException: cv::Exception: /build/master_pack-android/opencv/modules/core/src/matrix.cpp:483: error: (-215) 0 <= _rowRange.start && _rowRange.start <= _rowRange.end && _rowRange.end <= m.rows in function cv::Mat::Mat(const cv::Mat&, const cv::Range&, const cv::Range&)

我的代码:

private Bitmap findCombine(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();
        bitmapWidth = sourceBitmap.getWidth();
        Log.e("bitmapWidth", String.valueOf(bitmapWidth));
        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

        Scalar lowerblack = new Scalar(0, 0, 0);         // lower color border for BLACK
        Scalar upperblack = new Scalar(180, 255, 40);      // upper color border for BLACK

        Scalar testRunL = new Scalar(60, 50, 40); // lower Green   83 100 51
        Scalar testRunU = new Scalar(90, 255, 255); // upper Green

        Core.inRange(hsvMat, lowerblack, upperblack, 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 > 1300 && rectangleArea < 500000) {//400000
                Point rotated_rect_points[] = new Point[4];
                boundingRect.points(rotated_rect_points);
                Rect rect3 = Imgproc.boundingRect(new MatOfPoint(rotated_rect_points));

                Log.e("blackArea", String.valueOf(rect3.area()));
                // test horizontal ROI orientation
                if (rect3.height > rect3.width) {
                    Imgproc.rectangle(sourceMat, rect3.tl(), rect3.br(), green, 3);
                    xBlack = rect3.br().x;
                    yBlack = rect3.br().y;//bottom
                    battHeight = (rect3.br().y - rect3.tl().y); //batt height in pixel
                    Log.e("BLACKBR, TL", String.valueOf(rect3.br().y) + "," + String.valueOf(rect3.tl().y));
                }

            }

        }
  

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


    Point leftPoint = new Point(0, yBlack); //far left, black object height
    Point rightPoint = new Point(roiBitmap.getWidth(), roiBitmap.getHeight()); //btm right of entire bitmap

    Rect bottomRect = new Rect(leftPoint, rightPoint);
    double rectWidth = sourceBitmap.getWidth() - 0;
    double rectHeight = sourceBitmap.getHeight() - yBlack;
    Log.e("rectWidth", String.valueOf(rectWidth));
    Log.e("rectHeight", String.valueOf(rectHeight));
    Size bottomRectSize = new Size(rectHeight, rectWidth);

    Bitmap cropBitmap = null;
    Bitmap sourceBitmapT = null;

    Mat sourceMatT = new Mat(sourceBitmap.getWidth(), sourceBitmap.getHeight(), CvType.CV_8UC3);
    Log.e("sourceMatT, BottomRect","SMT "+ String.valueOf(sourceMatT.size()) + " bottomRect " + String.valueOf(bottomRect.size()));


    Mat cropMat = new Mat(sourceMatT, bottomRect);
    ImageView imgCropped = (ImageView) findViewById(R.id.cropped_image_view);
    Utils.bitmapToMat(roiBitmap, sourceMatT);
    //mgCropped.setImageBitmap(sourceBitmapT);

    Utils.matToBitmap(cropMat, cropBitmap);
    imgCropped.setImageBitmap(cropBitmap);

Log.e("sourceMatT, BottomRect","SMT "+ String.valueOf(sourceMatT.size()) + " bottomRect " + String.valueOf(bottomRect.size()));

返回给我这些值:

sourceMatT, BottomRect: SMT 1920x1080 bottomRect 1080x656

最佳答案

您可以“提取”图像的一部分,然后在整个提取区域中查找轮廓,然后纠正查找轮廓的坐标。类似这样的事情:

提取sourceMat的一部分:

// set top left position and dimensions of extracted area
int topLeftX = ...;
int topLeftY = ...;
int width = ...;
int height = ...;

// create Rect object for extracted area
Rect extractedRect = new Rect (topLeftX, topLeftY, width, height);

// create Mat from sourceMat
Mat extractedMat = new Mat(sourceMat, extractedRect);

在整个提取区域上查找轮廓/矩形或其他内容:

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

建立轮廓的正确坐标(添加到其XY坐标,相应的topLeftXtopLeftY用于正确放置在 sourceMat 上):

List<Rect> rectsOnSourcemat = new ArrayList<>();

for (MatOfPoint contour : contours) {
    MatOfPoint2f contourPoints = new MatOfPoint2f(contour.toArray());
    RotatedRect boundingRect = Imgproc.minAreaRect(areaPoints);
    Point rotated_rect_points[] = new Point[4];
    boundingRect.points(rotated_rect_points);

    // correct coords here for sourceMat:
    for (int ixPoint = 0; ixPoint < 4; ixPoint++) {
        rotated_rect_points[ixPoint].x += topLeftX;  
        rotated_rect_points[ixPoint].y += topLeftY;  
    }

    // crate bounding rect for sourceMat
    Rect rect = Imgproc.boundingRect(new MatOfPoint(rotated_rect_points));
    rectsOnSourcemat.add(rect);
}

现在在 rectsOnSourcemat 变量中,您将获得基于提取的区域对象的矩形列表,但已经包含 sourceMat 的坐标。

关于java - OpenCV、安卓 : color detection from particular area or portion of an image?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45706489/

相关文章:

python - 使用python从图像中过滤掉小网格线

python - 如何修复OpenCV Numpy错误,对象不可迭代

opencv - 使用 Opencv 进行人脸识别

java - 在本地机器上运行的 Web 应用程序

java - 使用 Fragments 和 ViewPager 的良好做法

android - 为位图图像添加透明度

android - Facebook Android SDK : AccessToken. refreshCurrentAccessTokenAsync() 不延长到期时间

java - 朱尼特 : How to cover CompletableFuture Code

java - 当温度更新时更新java中gui上的jlabel温度

android - 如何在谷歌地图android中点击标记时显示文本