繁体   English   中英

Android的OpenCV:从图像的特定区域或部分进行颜色检测?

[英]OpenCV, Android: color detection from particular area or portion of an image?

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

我设法让黑色物体下面的矩形区域像这样

    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. 显示位图,如下图所示(完成)

在此处输入图片说明

编辑:

在检测到黑色对象之后,将绘制边界rect,当前该矩形位于roiBitmap 裁剪roiBitmap ,并试图以显示它(我会检测到来自该位图,它最终真实裁切掉的绿色带) imageview是给我的错误:

CvException [org.opencv.core.CvException:cv :: Exception:/build/master_pack-android/opencv/modules/core/src/matrix.cpp:483:错误:(-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坐标,对应topLeftX topLeftY的正确放置的topLeftXsourceMat ):

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变量中,您将获得基于提取的区域对象建立的rectsOnSourcemat列表,但已经有了sourceMat坐标。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM