Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android OpenCV Color detection

Currently I'm developing an app that will detect colored circles. I'm trying to do this by following this tutorial, where guy detects red circles on image with Python. I've written the same code, just for Java.

                    Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(),
                            CvType.CV_8UC3);

                    Mat hsv_image = new Mat();
                    Utils.bitmapToMat(bitmap, mat);
                    Imgproc.cvtColor(mat, hsv_image, Imgproc.COLOR_BGR2HSV);

                    Mat lower_red_hue_range = new Mat();
                    Mat upper_red_hue_range = new Mat();

                    Core.inRange(hsv_image, new Scalar(0, 100, 100), new Scalar(10, 255, 255), lower_red_hue_range);
                    Core.inRange(hsv_image, new Scalar(160, 100, 100), new Scalar(179, 255, 255), upper_red_hue_range);
                    Utils.matToBitmap(hsv_image, bitmap);
                mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
                image.setImageBitmap(mutableBitmap);

Image I use is identical to one from tutorial: enter image description here

This is image with applied BGR2HSV: enter image description here

When I execute the code using lower red hue range, it detects the blue circle. When I use upper red hue range it gives me black bmp(doesn't detect anything). How can it be? What am I doing wrong? This is literally copy moved from python to Java. Why's the result different then? Thanks in advance.

like image 551
Oleksandr Firsov Avatar asked Apr 29 '26 18:04

Oleksandr Firsov


1 Answers

Your mat is of CvType.CV_8UC1 image, i.e. you are working on a grayscale image. Try with CvType.CV_8UC3

Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_8UC3);

hsv_image should look like this:

enter image description here

How to select a custom range:


You may want to detect a green circle. Well, in HSV, tipically the range is:

H in [0,360]
S,V in [0,100]

However, for CV_8UC3 images, each component H,S,V can be represented by only 256 values at most, since it's stored in 1 byte. So, in OpenCV, the ranges H,S,V for CV_8UC3 are:

H in [0,180] <- halved to fit in the range
S,V in [0,255] <- stretched to fit the range

So to switch from typical range to OpenCV range you need to:

opencv_H = typical_H / 2;
opencv_S = typical_S * 2.55; 
opencv_V = typical_V * 2.55;

So, green colors are around the value of hue of 120. The hue can have a value in the interval [0,360]. However, for Mat3b HSV images, the range for H is in [0,180], i.e. is halved so it can fit in a 8 bit representation with at most 256 possible values. So, you want the H value to be around 120 / 2 = 60, say from 50 to 70. You also set a minimum value for S,V to 100 in order to prevent very dark (almost black) colors.

Mat green_hue_range
inRange(hsv_image, cv::Scalar(50, 100, 100), cv::Scalar(70, 255, 255), green_hue_range);
like image 170
Miki Avatar answered May 01 '26 10:05

Miki