2017-08-16 99 views
1

我想检测黑色物体下方的整个区域。OpenCV,Android:来自特定区域或图像部分的颜色检测?

我已经成功地得到下面的黑色物体的矩形区域,像这样

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); 这d给我一个错误。

下面是它会是什么样子,我认为:

  1. Detect and draw bounding rectangle around black object (Done)

  2. Find rectangle area(RAT) below black object

  3. Detect and draw bounding rectangle around green object within the RAT(I can detect and draw bounding rectangle for green object, cant seem to do it WITHIN the specified RAT)

  4. Display bitmap like shown in image below(done)

enter image description here

编辑:

检测的黑色物体后,将边界RECT绘制,目前正在roiBitmap。裁剪roiBitmap,并试图在imageview来显示它(我会检测到来自该位图,它真实最终裁剪出来的绿色带)是给我的错误:

CvException [org.opencv.core.CvException: cv::Exception: /build/master_pack-android/opencv/modules/core/src/matrix.cpp:483: error: (-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

'Mat croppedMat = new Mat(bottomRect,CvType.CV_8UC3);'给出一个错误,因为没有这个_Mat_构造函数。我想你要找的是这个:“垫子(Mat m,Rect roi)'。下一次,请首先查看[documentation](http://docs.opencv.org/java/3.1.0/)。 –

+0

嘿@ElouarnLaine我已经编辑了这个问题来反映我目前的问题:如果你能够弄清楚什么是错误的,我会非常感谢一些帮助非常感谢 – Tix

回答

3

您可以“提取”图像的一部分,然后在整个提取区域中查找轮廓,然后修正查找轮廓的坐标。类似的东西:

提取部分 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); 

成立轮廓的正确COORDS(添加到它的XY coords,相应的,topLeftXtopLeftY正确放置在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变量您将得到建立在提取的区域对象上的rects列表,但已经与sourceMat的坐标一致。

相关问题