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

时间:2017-08-16 06:30:12

标签: java android opencv bitmap

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

我设法让黑色物体下方的矩形区域如此

    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.   
  3. 在黑色对象下面找到矩形区域(RAT)

  4.   
  5. 在RAT中检测并绘制绿色对象周围的边界矩形(我可以检测并绘制绿色对象的边界矩形,似乎无法在指定的RAT中进行)

  6.   
  7. 显示位图,如下图所示(已完成)

  8.   

enter image description here

修改

在检测到黑色物体后,绘制了边界矩形并且当前在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

1 个答案:

答案 0 :(得分:3)

你可以&#34;提取&#34;图像的一部分,然后在整个提取区域中找到轮廓,然后校正找到轮廓的坐标。这样的事情:

提取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,以便正确放置{{1} }):

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