【问题标题】:OpenCV, Android: color detection from particular area or portion of an image?OpenCV,Android:从图像的特定区域或部分进行颜色检测?
【发布时间】:2018-01-24 04:18:22
【问题描述】:

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

我已经设法像这样得到黑色对象下方的矩形区域

    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); 是我想要检测绿色条带的区域,如图所示。这是为了防止应用程序搜索图片上方的任何内容并在其他对象在框架中时导致错误。

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

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

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

我的想法是这样的:

  1. 检测并在黑色对象周围绘制边界矩形(完成)

  2. 找到黑色物体下方的矩形区域(RAT)

  3. 检测并在 RAT 内围绕绿色对象绘制边界矩形(我可以检测并绘制绿色对象的边界矩形,在指定的 RAT 内似乎无法做到)

  4. 如下图所示显示位图(完成)

编辑:

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

CvException [org.opencv.core.CvException: cv::Exception: /build/master_pack-android/opencv/modules/core/src/matrix.cpp:483: 错误: (-215) 0

我的代码:

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

【问题讨论】:

  • Mat croppedMat = new Mat(bottomRect, CvType.CV_8UC3); 给出一个错误,因为没有这个 Mat 构造函数。我猜你要找的是这个:Mat(Mat m, Rect roi) 。下次请先看documentation
  • 嘿@ElouarnLaine 我已经编辑了问题以反映我当前的问题:x 如果您能够找出问题所在,我将不胜感激非常感谢您

标签: java android opencv bitmap


【解决方案1】:

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

提取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 的坐标。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-03
    • 2015-12-15
    • 1970-01-01
    相关资源
    最近更新 更多