Android OpenCV Detection Improvement

I am currently developing an application that will define circles from photos. I managed to write code for this, but it either makes false negatives or false positives if I get a little off the PC screen. How can I improve the result? I mean, there are many applications that detect small and fuzzy circles.

[Update]

I messed around with values ​​in GaussianBlur and HoughCircles . changes to Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 2, 2); before Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 9, 9); and double param1 = 70, param2 = 72; up to double param1 = 50, param2 = 52; improves the result, but not enough.

  Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_8UC1); Mat grayMat = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_8UC1); Utils.bitmapToMat(bitmap, mat); int colorChannels = (mat.channels() == 3) ? Imgproc.COLOR_BGR2GRAY : ((mat.channels() == 4) ? Imgproc.COLOR_BGRA2GRAY : 1); Imgproc.cvtColor(mat, grayMat, colorChannels); Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 2, 2); // accumulator value double dp = 1.2d; // minimum distance between the center coordinates of detected circles in pixels double minDist = 100; int minRadius = 0, maxRadius = 0; double param1 = 70, param2 = 72; Mat circles = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_8UC1); Imgproc.HoughCircles(grayMat, circles, Imgproc.CV_HOUGH_GRADIENT, dp, minDist, param1, param2, minRadius, maxRadius); int numberOfCircles = 9; if (numberOfCircles > circles.cols()){ numberOfCircles = circles.cols(); } for (int i=0; i<numberOfCircles; i++) { double[] circleCoordinates = circles.get(0, i); if(circleCoordinates == null){ break; } int x = (int) circleCoordinates[0], y = (int) circleCoordinates[1]; Point center = new Point(x, y); android.graphics.Point centerC = new android.graphics.Point(x, y); int radius = (int) circleCoordinates[2]; Core.circle(mat, center, radius, new Scalar(0, 255, 0), 4); Core.rectangle(mat, new Point(x - 5, y - 5), new Point(x + 5, y + 5), new Scalar(0, 128, 255), -1); 

Thanks in advance.

I am currently using these A-shaped dots to check the code, but I want to detect even smaller circles in the photo. enter image description here

+6
source share
3 answers

I think if you want to detect only white circles, you need to implement a color definition. This will not only significantly improve the quality of detection, but also eliminate a lot of false positives and negatives. Using a color definition is pretty simple, as it is already present in OpenCV. To do this, use the Core.inRange function. Learn more about this here . But probably this tutorial will be the best for you. It was written in Python, but it is understandable, and you only need to change a few lines to make it work for Android. Hope this helps :)

0
source

In general, making param1 and param2 smaller reduces the threshold for circle recognition, so there will be more false positives [detecting a circle where there is none] and less false negatives (not detecting a circle where there is one).

Parameter 2 sets the circle detection threshold. If the number is less, more laps in total will be detected.

Parameter 1 sets the sensitivity threshold for the Canny edge detector. If the number is smaller, weaker circles are more often found than the larger number.

As in the case of computer vision or machine learning, if it does not work reliably and you do not know why, try changing some parameters. :-D

Failure with less than nine laps occurs from hard coding the number of laps to nine. If the number of frames is less than nine, the program tries to access outside the Mat array.

I do not have a system for testing some OpenCV at the moment, but I can write code. My only caveat is that you might need circles.rows instead of circles.cols . Edit: also circles are NULL if it has 0 entries.

 int numberOfCircles = 9; if (circles == null) numberOfCircles = 0; else if (numberOfCircles > circles.cols) numberOfCircles = circles.cols; for (int i=0; i<numberOfCircles; i++) { double[] circleCoordinates = circles.get(0, i); ... 
0
source

Try it.

  Mat input = new Mat(); Mat rgb = new Mat(); Mat output = new Mat(); Bitmap bitmap = BitmapFactory.decodeFile(mCurrentImagePath, bitOpts); input = Utils.bitmapToMat(bitmap); FeatureDetector fast = FeatureDetector.create(FeatureDetector.FAST); List<KeyPoint> keypoints = new ArrayList<KeyPoint>(); fast.detect(input, keypoints); Imgproc.cvtColor(input, rgb, Imgproc.COLOR_RGBA2RGB); Features2d.drawKeypoints(rgb, keypoints, rgb); Imgproc.cvtColor(rgb, output, Imgproc.COLOR_RGB2RGBA); Utils.matToBitmap(output, bitmap); //SHOW IMAGE mImageView.setImageBitmap(bitmap); input.release(); rgb.release(); output.release(); 
0
source

All Articles