Tix
Tix

Reputation: 449

Android OpenCV: color detection giving weird result

I've just learnt how to detect a color from OpenCV Java, Getting region of interest from image.

Ultimately, I want to know how can I detect the AA battery(with and or without black tape)

I'm now trying to detect the battery in the picture, but the battery is not fully black, and in turn giving me weird result:

enter image description here

I covered the battery with black tape and tried again the result seems better but it is detecting the battery in two separate sections:

enter image description here

Code:

private Bitmap findRoiBlack(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();

    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(0, 0, 0);         // lower color border for BLACK
    Scalar upperb = new Scalar(180, 255, 30);      // upper color border for BLACK

    //Scalar lowerb = new Scalar(0, 0, 200);         // lower color border for WHITE
    //Scalar upperb = new Scalar(180, 255, 255);      // upper color border for WHITE
    Core.inRange(hsvMat, lowerb, upperb, 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 > 400) {
            Point rotated_rect_points[] = new Point[4];
            boundingRect.points(rotated_rect_points);

            Rect rect = Imgproc.boundingRect(new MatOfPoint(rotated_rect_points));

            // test vertical ROI orientation
            if (rect.height > rect.width) {
                Imgproc.rectangle(sourceMat, rect.tl(), rect.br(), green, 3);
            }
        }
    }

    roiBitmap = Bitmap.createBitmap(sourceMat.cols(), sourceMat.rows(), Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(sourceMat, roiBitmap);
    return roiBitmap;
}

Upvotes: 0

Views: 290

Answers (1)

Andrii Omelchenko
Andrii Omelchenko

Reputation: 13343

Easiest way - is add color marker to battery. Other way is set solid, well distinguishable background for vertical channel of Your installation (may be even backlight - in this case You should find just black/low brightness object on white/high brightness background). If it's not possible and You have solid background - try to "invert" approach: don't try find battery (because it has many colors) - find background (because it has one solid color) - object with "non background" colors probably battery (and You have additional hints: battery is "vertical" rectangle with 1/4 proportions (AAA battery has 10.5 mm diameter and 44.6 mm length), it is approximately on the vertical center of image and has chromium-plated high brightness elements on top and bottom, etc.).

Upvotes: 2

Related Questions