簡體   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