android - OpenCV,Java:特定区域中的颜色检测

标签 android opencv

我目前有这张图片:

image

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

生成的图像仍应如下所示:
enter image description here

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: error: (-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)

最佳答案

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

首先-找到黑色矩形。

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

等等...

关于android - OpenCV,Java:特定区域中的颜色检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45730980/

相关文章:

opencv - 裁剪和旋转图片 OpenCV

opencv - 使用鼠标的OpenCV访问像素值

java - 如何使用 AES 将字符串加密为仅包含特定字符的字符串?

android - 为什么安卓:soundEffectsEnabled ="true" does not playing any sounds for onClick?

opencv - Python 3 是否支持 OpenCV?

opencv - 在opencv2.4.6中加载图像

python-2.7 - 为什么OpenCV在视频处理过程中会检索此错误?错误:(-215)scn == 3 || scn == 4在函数cv::cvtColor中

用于处理 session 、cookie、post/get、keep-alive 和异步的 Android HTTP 库

java - 如何从 webview 获取当前 url?

java - ProgressDialog不会显示 - 多线程