2017-08-16 98 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的座標一致。

相關問題