目前我正在开发一款应用,可以检测照片中的圆圈。我已经设法为此编写了一个代码,但如果我从PC屏幕稍微离开电话,它可能会出现漏报或误报。如何改进结果呢?我的意思是,有很多应用可以检测出小而不清楚的圈子。
[更新]
我正在摆弄GaussianBlur
和HoughCircles
中的值。更改
Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 2, 2);
至Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 9, 9);
和param1 = 70, param2 = 72;
加倍double param1 = 50, param2 = 52;
会改善结果,但还不够。
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);
提前致谢。
现在我使用那些A形点测试代码,但我想在照片上检测更小的圆圈。
答案 0 :(得分:1)
我认为,如果您只想检测白色圆圈,则需要实现颜色检测。它不仅可以大大提高检测质量,还可以消除大量误报和误报。使用颜色检测非常简单,因为它已经存在于OpenCV中。对于此使用Core.inRange
功能。您可以找到有关它的更多信息here。但对你来说最好的事情可能就是关注this教程。它是用Python编写的,但它是可以理解的,你需要只改变几行才能让它适用于android。希望这会有所帮助:)
答案 1 :(得分:0)
一般来说,使param1和param2变小会放宽识别圆圈的阈值,因此会有更多的误报[检测到没有的圆圈]和更少的假阴性[没有检测到有圆的圆圈]。
Param2设置圆检测阈值。如果数字较小,一般会检测到更多的圆圈。
Param1设置Canny边缘检测器的灵敏度阈值。如果数字较小,则更可能检测到较暗的圆圈而不是较大的数字。
与计算机视觉或机器学习中的任何内容一样,如果它无法正常工作且您不知道原因,请尝试更改一些参数。 :-D
少于九个圈子时的崩溃来自将圈数硬编码为九个。当少于九个圆圈时,程序会尝试超出Mat数组的范围。
我目前没有系统来测试一些OpenCV,但我可以编写一些代码。我唯一需要注意的是,您可能需要circles.rows
而不是circles.cols
。编辑:同样,如果圆圈为0,则圆圈为空。
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);
...
答案 2 :(得分:0)
试试这个。
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();