【问题标题】:Android OpenCV Improving detection qualityAndroid OpenCV 提高检测质量
【发布时间】:2015-07-15 05:29:27
【问题描述】:

目前我正在开发一个应用程序,它将检测照片中的圆圈。我已经设法为此编写了一个代码,但如果我让手机远离 PC 屏幕,它要么会出现误报,要么会出现误报。如何改进结果?我的意思是,有很多应用程序可以检测到小而不清楚的圆圈。

[更新]

我在摆弄GaussianBlurHoughCircles 中的值。改变 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 形点来测试代码,但我想检测照片上更小的圆圈。

【问题讨论】:

  • 您是否尝试过 param1 和 param2 的不同参数集?
  • 没有。我没有。你认为我应该如何尝试改变它们。增加参数 2?
  • 我的第一个猜测是减少 param2。你会有更多的误报,但我认为处理误报比处理误报更容易。其次,尝试减少 param1。这提高了 Canny 边缘检测器的灵敏度,当您想要检测从背景中不明显突出的圆圈时,这可能会很好。
  • 好的。我会尝试玩价值观。当圈数少于 9 个时,您知道如何修复崩溃吗?
  • 发布了答案。让我知道参数调整是否成功。

标签: java android opencv geometry


【解决方案1】:

我认为,如果您只想检测白色圆圈,则需要实现颜色检测。它不仅会大大提高检测质量,而且会去除大量的误报和误报。使用颜色检测非常简单,因为它已经存在于 OpenCV 中。为此使用Core.inRange 函数。你可以找到更多关于它的信息here。但可能对您来说最好的事情是遵循this 教程。它是用 Python 编写的,但它是可以理解的,您只需更改几行即可使其适用于 android。希望这会有所帮助:)

【讨论】:

  • 您好,感谢您的详细解答!如果您查看 cmets,您会发现我对这个问题提出了相同的解决方案。唉,要是你早几天回复就好了……
  • 这是否意味着我不会得到奖励? T-T
  • 不,我想你还是应得的。再次感谢。
  • 你能发布适用于android的可行代码吗@Olelsandr Firsov。
  • 不。该代码存档在我的 PC 上的某个地方,查找它很痛苦。我确实记得这个问题。检测不佳是由于您设置了非常特定的颜色来检测。 inRange 不仅可以包含准确的颜色,还可以包含阴影,从而改进检测。只需检查链接以获取更多信息。第一个不起作用,但从它的外观来看,它是文档。转到 openCV 站点并搜索该函数。
【解决方案2】:

一般来说,让 param1 和 param2 变小会放宽识别圆圈的阈值,因此会出现更多的误报[检测到没有圆圈的圆圈],而更少的假阴性[没有检测到有圆圈的圆圈]。

Param2 设置圆检测阈值。如果数字较小,一般会检测到更多的圆圈。

Param1 设置 Canny 边缘检测器的灵敏度阈值。如果数字较小,则比较大的数字更有可能检测到较暗的圆圈。

与计算机视觉或机器学习中的任何事情一样,如果它不能可靠地工作并且您不知道原因,请尝试更改一些参数。 :-D

少于九个圆圈时的崩溃来自于将圆圈数硬编码为九个。当圆数少于九个时,程序会尝试访问 Mat 数组的边界之外。

目前我没有系统来测试一些 OpenCV,但我可以编写一些代码。我唯一需要注意的是,您可能需要circles.rows 而不是circles.cols。编辑:另外,如果 circles 有 0 个条目,则为 null。

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);
    ...

【讨论】:

  • 这段代码有帮助。部分地。现在,如果我有 1 到 x 个圆圈,应用程序不会崩溃。如果数字为 0 - 崩溃。
  • 好的。我已经修复了添加此 if(circleCoordinates == null){ break; 的崩溃错误}
  • 尝试调整 minRadius 和 maxRadius 参数。如果您的目标只是找到门上的圆圈或更小,那么您可以向圆圈检测器提供该信息。
  • 好的,我想我解决了我的问题 - 我正在实施颜色检测,这将消除大部分(如果不是全部)误报。不过还是谢谢
【解决方案3】:

试试这个。

  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();

【讨论】:

  • 感谢您的回答,但我想我明白了 - 我实现了颜色检测。
  • @OleksandrFirsov 那么问题是什么?
猜你喜欢
  • 2015-02-19
  • 1970-01-01
  • 2010-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-16
  • 1970-01-01
  • 2012-08-02
相关资源
最近更新 更多