【问题标题】:Circle estimation from 2D data set二维数据集的圆估计
【发布时间】:2014-01-08 20:28:17
【问题描述】:

我正在做一些基于计算机视觉的手势识别工作。在这里,我想检测我的手做的一个圆圈(圆周运动)。我的初始阶段工作正常,我能够从我正在绘制的每一帧中获得一个质心的 blob。这本质上是我的数据集。二维坐标点的集合。现在我想检测一个圆形运动,并说生成一个对“检测到圆形”的函数的调用。圆形检测器将给出 YES / NO 布尔输出。 这是我在 40 帧中生成的数据集的示例

x、y 值只是使用 MATLAB 绘制到位图图像上。 我最初的手部动作很慢,后来我加快了速度,在规定的时间内(40 帧)完成了圆圈。关于帧数没有硬性规定,但现在我使用 40 帧滑动窗口进行圆形检测 (0-39) 然后 (1-40) 然后 (2-41) 等等。 我还使用以下方法计算连续点之间的反正切:

angle = atan2(prev_y - y, prev_x - x) * 180 / pi;

现在我应该采取什么方法来检测一个圆圈(这个示例图像应该会导致“是”)。我注意到的角度并没有从 0 到 360 稳定地增加。它确实增加了,但到处都有跳跃。

【问题讨论】:

    标签: image-processing gesture gesture-recognition gestures


    【解决方案1】:

    如果您只对完整或接近完整的圆圈感兴趣:

    我认为标准参数估计方法:Hough/RANSAC 在这种情况下效果不佳。

    由于您具有帧顺序以及连续斑点中心之间的距离,因此您可以创建一个几乎均匀的数据子样本(比如说,选择 20 个间隔均匀的点),计算中心并测量所有点的距离那个中心。

    如果它几乎是一个圆,所有点到中心的距离都差不多。

    如果你想做一些更健壮的事情,你可以:

    • 计算所有点的中心(平均值)。
    • 执行梯度下降以更新中心:应该相当容易,并且您不会有局部最小值。我可能会使用的错误术语是max(D) - min(D),其中D 是斑点中心和估计圆心之间的距离向量(但您可以使用稳健的统计数据而不是最大值和最小值)
    • 评估圆圈

    【讨论】:

    • 是的,我已经尝试过霍夫变换,但它不起作用。我现在将首先尝试您的第一种方法。谢谢..
    • 没问题,我很确定只要您拥有大部分圆圈并且您设法或多或少均匀地对斑点中心进行采样,简单的方法就会起作用。
    • 好的,我尝试了第一种方法。我的手部运动的速度必须或多或少一致,否则质心会移向缓慢绘制的点(更密集的区域)。我在想也许在点之间画一条线,然后估计中心。但这在计算上会很昂贵。
    • 我不认为速度真的必须是均匀的,你可以对斑点中心进行二次采样。例如,如果两个中心之间的最大距离是 X 像素,则只取相距 ~X 像素的样本,我认为它应该不是很准确,因为你只是试图估计圆的中心,它应该是相当的健壮
    • 通过一些微调和子采样,我得到了很好的结果。谢谢 :) 稍后有时间我会尝试梯度下降。
    【解决方案2】:

    我会使用最小二乘估计。在数值上,您可以使用 Nelder-Mead 方法。您得到最接近您的点的圆,并根据残差值决定是否认为该圆有效。

    作为 points 的数组,xc,yc 是中心的坐标,r 是半径,这可能是一个要最小化的错误示例:

    class Circle
    {
        private PointF[] _points;
        public Circle(PointF[] points)
        {
            _points = points;
        }
        public double MinimizeFunction(double xc, double yc, double r)
        {
            double d, d2, dx, dy, sum;
    
            sum = 0;
            foreach(PointF p in _points)
            {
                dx = p.X - xc;
                dy = p.Y - yc;
                d2 = dx * dx + dy * dy;
                // sum += d2 - r * r;
                d = Math.Sqrt(d2) - r;
                sum += d * d;
            }
            return sum;
        }
        public double ResidualError(double xc, double yc, double r)
        {
            return Math.Sqrt(MinimizeFunctional(xc, yc, r)) / (_points.Length - 3);
        }
    
    }
    

    注释的函数和未注释的函数之间存在细微差别,但出于实际原因,这种差别是没有意义的。相反,从理论的角度来看,差异很重要。

    由于您需要提供一个初始值集 (xc, yc, r),因此您可以计算给定三个点的圆,选择相距较远的三个点。

    如果您需要有关“给定三分的圆”或 Nelder-Mead 的更多详细信息,您可以在此处搜索或询问我。

    【讨论】:

      猜你喜欢
      • 2013-07-23
      • 2011-08-11
      • 1970-01-01
      • 2015-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-10
      • 2015-07-20
      相关资源
      最近更新 更多