【问题标题】:OpenCV, Java: Color Detection in a certain specified areaOpenCV,Java:在某个指定区域进行颜色检测
【发布时间】:2017-08-17 09:10:41
【问题描述】:

我目前有这张图片:

我设法检测到黑色物体。现在我想检测绿色对象,但我只希望应用程序查找黑色对象下方的绿色对象。我已经有了检测绿色胶带及其工作的代码。只需将其设置为仅在黑色对象下方的区域中即可。

生成的图像仍应如下所示:

P.S 一些变量被命名为“蓝色”,请放心使用绿色标量值。

代码:

//Detect Black
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;
                xBlackCenter = (rect3.br().x+ rect3.tl().x) /2;
                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);







//Set area to detect green
    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));

    Mat sourceMatT = new Mat(roiBitmap.getWidth(), roiBitmap.getHeight(), CvType.CV_8UC3);
    Utils.bitmapToMat(roiBitmap,sourceMatT);

    Bitmap C = Bitmap.createBitmap(sourceMatT.cols(), sourceMatT.rows(), Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(sourceMatT, C);

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


    Mat cropMat = new Mat(dumbMat, bottomRect);
    ImageView imgCropped = (ImageView) findViewById(R.id.cropped_image_view);

    //Utils.matToBitmap(cropMat,C);
    imgCropped.setImageBitmap(C);






//Detect Green
    Bitmap roiBitmap2 = null;
    Mat sourceMat2 = new Mat(C.getWidth(), C.getHeight(), CvType.CV_8UC3);

    Utils.bitmapToMat(C, sourceMat2);
    Mat roiTmp2 = sourceMat2.clone();

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

    // convert mat to HSV format for Core.inRange()
    Imgproc.cvtColor(hsvMat2, hsvMat2, Imgproc.COLOR_RGB2HSV);
    Core.inRange(hsvMat2, testRunL, testRunU, roiTmp2);   // select only blue pixels

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

    // find appropriate bounding rectangles
    for (MatOfPoint contour2 : contours2) {
        MatOfPoint2f areaPoints2 = new MatOfPoint2f(contour2.toArray());
        RotatedRect boundingRect2 = Imgproc.minAreaRect(areaPoints2);

        double rectangleArea2 = boundingRect2.size.area();

        // test min ROI area in pixels
        if (rectangleArea2 > 40) { //214468.32402064091 // 20000
            Point rotated_rect_points2[] = new Point[4];
            boundingRect2.points(rotated_rect_points2);
            Rect rect = Imgproc.boundingRect(new MatOfPoint(rotated_rect_points2));
            Log.e("area green", String.valueOf(boundingRect2.size.area()));
            // test vertical ROI orientation


            if (rect.width > rect.height) {


                if (numRect < 2) {
                    Imgproc.rectangle(sourceMat2, rect.tl(), rect.br(), green, 3);
                    xBlue = (rect.br().x + rect.tl().x) / 2; //center
                    yBlue = rect.br().y; //bottom

                    Log.e("GREEN br,tl", String.valueOf(rect.br().y) + "  " + String.valueOf(rect.tl().y));
                }
            }
        }
    }

    Point firstPoint = new Point(xBlackCenter, yBlack);
    Point secondPoint = new Point(xBlackCenter, yBlue);
    Point middlePoint = new Point(firstPoint.x,
            firstPoint.y + 0.5 * (secondPoint.y - firstPoint.y));

    Scalar lineColor = new Scalar(255, 0, 0, 255);
    int lineWidth = 3;

    Scalar textColor = new Scalar(255, 0, 0, 255);
    //height of bounce = BattHeight IRL / battHeihgt Pixel * line Height Pixel
    double lineHeightCm = (4.65 / battHeight) * findHeight(yBlack, yBlue);
    Log.e("PixelBatt/PixelBounce", "BattH: " + battHeight + " find height " + String.valueOf(findHeight(xBlack, xBlue)) + "!");
    Log.e("Blacky-blueY", String.valueOf(xBlue - xBlack));
    Imgproc.line(sourceMat2, firstPoint, secondPoint, lineColor, lineWidth);
    Imgproc.putText(sourceMat2, String.valueOf(lineHeightCm), middlePoint,
            Core.FONT_HERSHEY_PLAIN, 3.5, textColor);


    roiBitmap2 = Bitmap.createBitmap(sourceMat2.cols(), sourceMat2.rows(), Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(sourceMat2, roiBitmap2);

    TextView tvR = (TextView) findViewById(R.id.tvR);
    tvR.setText("Bounce Height = " + lineHeightCm + "cm");


    return roiBitmap2;
}

错误:

CvException [org.opencv.core.CvException:/build/master_pack-android/opencv/modules/java/generator/src/cpp/utils.cpp:97:错误:(-215)src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols in function void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong​​, jobject, jboolean)

【问题讨论】:

  • 那么到底是什么问题,错误还是找到了绿色对象?
  • 我遇到的问题是让应用程序仅在黑色对象下方查找绿色对象,目前它正在搜索我不想要的整个图像。我发现绿色/黑色没有问题,我只想在特定区域检测绿色。假设有 2 个绿色物体,一个在黑色物体上方的一个下方。我只希望检测到黑色物体下方的绿色
  • 您可以在图像的 下方 部分运行检测。
  • 我不知道如何在图像的“下方”部分运行它...
  • @RickM。 ,这基本上就是我遇到的错误,使用 Rect 提取以下部分似乎给了我错误。如果您查看代码,则有一条注释说 //Set area to detect green 这是我尝试提取“下方”区域的代码部分,但也导致问题中显示的问题。

标签: android opencv


【解决方案1】:

无需在特定区域寻找绿色物体:您可以在整个图像上找到绿色轮廓,然后测试它相对于黑色矩形的坐标。类似的东西:

首先 - 找到黑色矩形。

Rect blackRect = findBlackRect();

然后找到所有绿色物体的轮廓(与您找到黑色的方法相同):

// find green contours
List<MatOfPoint> greenContours = new ArrayList<>();
Imgproc.findContours(roiMat, greenContours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);

然后测试黑色矩形下方的绿色轮廓(具有更大的 Y 坐标)

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

    Point rotated_rect_points[] = new Point[4];
    boundingRect.points(rotated_rect_points);

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

    // test top left Y coord of bounding rectangle of green contour grater than 
    // Y coord of top left of black rectangle 
    if (rect.tl().y > blackRect.tl().y) {
        // that is green contour under black rectangle
        // just draw it
        Imgproc.rectangle(sourceMat, rect.tl(), rect.br(), green, 3);
    }
}

等等……

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 2013-09-09
    • 1970-01-01
    • 2013-09-22
    • 2016-10-17
    • 2021-12-25
    相关资源
    最近更新 更多