OpenCV,Java:某个指定区域的颜色检测

时间:2017-08-17 09:10:41

标签: android opencv

我目前有这张图片:

image

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

结果图像仍应如下所示: enter image description here

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

代码:

//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:error:(215)src.dims == 2 &安培;&安培; info.height ==(uint32_t)src.rows&amp;&amp; info.width ==(uint32_t)src.cols in function void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv *,jclass,jlong​​,jobject,jboolean)

1 个答案:

答案 0 :(得分:3)

无需在特定区域中找到绿色物体:您可以在整个图像上找到绿色轮廓,然后只测试相对于黑色矩形的坐标。这样的事情:

首先 - 找到黑色矩形。

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

等等......