我正在做一些基于计算机视觉的手势识别东西。在这里,我想检测一下我手上的圆圈(圆周运动)。我的初始阶段工作正常,我能够从我正在绘制的每个帧中获得一个质心。这基本上是我的数据集。 2D坐标点的集合。现在我想检测一个圆形运动,然后生成一个调用“Circle Detected”的函数。圆形检测器将给出YES / NO布尔输出。 以下是我在40帧
中生成的数据集示例使用MATLAB将x,y值绘制成位图图像。 我的初始手部动作很慢,后来我加快了速度,在规定的时间内完成了圆圈(40帧)。关于帧数的事情没有硬性和快速的规则但是现在我使用40帧滑动窗口进行圆检测(0-39)然后(1-40)然后(2-41)等。 我还使用以下方法计算连续点之间的反正切:
angle = atan2(prev_y - y, prev_x - x) * 180 / pi;
现在我应采取什么方法来检测圆圈(此样本图像应该为YES)。我注意到的角度并没有从0增加到360.它确实会增加但是会随着跳跃而增加。
答案 0 :(得分:1)
如果您只对完整或接近完整的圈子感兴趣:
我认为标准参数估算方法:Hough / RANSAC在这种情况下效果不佳。
由于你有帧顺序,因此有连续斑点中心之间的距离,你可以创建一个几乎统一的数据子样本(比方说,选择20个间隔〜均匀的点),计算中心并测量所有点的距离那个中心。
如果它几乎是一个圆,则所有点都与中心的距离相近。
如果你想做一些稍微强健的事情,你可以:
max(D) - min(D)
,其中D
是blob中心和估计的圆心之间距离的向量(但你可以使用健壮的统计数据而不是max& min)答案 1 :(得分:0)
一种可能的方法是:
获取具有倾斜角90 - angle
的线,并传递点[(x + prev_x)/2 (y + prev_y)/2]
。此线与点[x y]
和[prev_x prev_y]
之间的直线垂直。你可以获得40条这样的线。
您还可以在两个连续行之间获得intersection point。检查所有40个交叉点是否位于可接受范围内。返回一个布尔值。
答案 2 :(得分:0)
我会使用最小二乘估计。在数字上你可以使用Nelder-Mead方法。您可以得到最接近您的点的圆,并根据剩余误差值决定是否将圆视为有效。
点是点的数组,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你可以谷歌或在这里问我。