C++从点识别形状
C++ recognize shape from points
我正试图找到一种识别点阵列中圆的算法。
比方说,我有一个可以或不能存储圆的点数组(这也意味着数组不必只存储圆的值,在圆的数据之前或之后可能会有一些"额外"的点)。
我已经尝试了一些算法,但没有一个能正确处理这些"额外"点。你对如何处理这个问题有什么想法吗?
编辑//我以前没提过。我想把这个算法用于圆圈手势识别。我想我会有数组中的数据(最后几秒),通过分析每个跟踪帧中的数据,我可以判断是否有圆圈手势。
首先,我计算每个X和Y分量的几何平均值(而不是算术平均值)。我选择几何平均值是因为一个特点是数值很小(关于算术平均值)比大价值更有影响力。
这将我引向所有观点的理论中心:circ_center
然后我计算每个点到中心的距离的标准偏差:stddev。这给了我量化变化量的"指标"。圆的一个性质是,所有圆周点与圆心的距离相同。使用标准dev,我试图测试您的点是否(具有最大方差阈值:max_dispersion)距离相等。
最后,我计算了最大距离阈值内的点与中心的平均距离,这给了我圆的半径:avg_dest。
参数:max_dispersion表示"cicle精度"。更小意味着更精确。min_points_needed是被视为周长的有效点的最小数量。
这只是一次尝试,我没有尝试过。让我知道。
我将尝试这个(伪语言)
points_size = 100; //number_of_user_points
all_poins[points_size]; //coordinates of points
//thresholds to be defined by user
max_dispersion = 20; //value of max stddev accepted, expressed in geometric units
min_points_needed = 5; //minimum number of points near the circumference
stddev = 0; //standard deviation of points from center
circ_center; //estimated circumference center, using Geometric mean
num_ok_points = 0; //points with distance under standard eviation
avg_dist = 0; //distance from center of "ok points"
all_x = 1; all_y = 1;
for(i = 0 ; i < points_size ; i++)
{
all_x = all_x * all_poins[i].x;
all_y = all_y * all_poins[i].y;
}
//pow(x, 1/y) = nth root
all_x = pow(all_x, 1 / points_size); //Geometric mean
all_y = pow(all_y, 1 / points_size); //Geometric mean
circ_center = make_point(all_x, all_y);
for(i = 0 ; i < points_size ; i++)
{
dist = distance(all_poins[i], circ_center);
stddev = stddev + (dist * dist);
}
stddev = square_root(stddev / points_size);
for(i = 0 ; i < points_size ; i++)
{
if( distance(all_poins[i], circ_center) < max_dispersion )
{
num_ok_points++;
avg_dist = avg_dist + distance(all_poins[i], circ_center);
}
}
avg_dist = avg_dist / num_ok_points;
if(stddev <= max_dispersion && num_ok_points >= min_points_needed)
{
circle recognized; it's center is circ_center; it's radius is avg_dist;
}
我们能假设点的阵列大多在圆的圆周上或附近吗?
圆有圆心和半径。如果可以通过两个弦的垂线的交点来确定圆的中心坐标,那么所有true圆点都应该与中心点等距(r)。
假点可以通过与中心点不等距(+-)公差来消除。
这种方法的弱点是你能在多大程度上确定中心和半径?您可能想要尝试最小二乘法来计算中心坐标。
要回答最初提出的问题,我的方法是迭代这些点,并从每一组连续的三点中导出圆心。然后,取创建圆心位于某个绝对范围内的圆的最长连续点子集。然后确定这些点是否始终围绕圆的平均值旋转。您总是可以对任何丢弃的数据执行一些基本的试探法,以确定一个圆是否真的是用户想要制作的。
既然你说你想进行手势识别,我建议你考虑一种完全不同的方法。就我个人而言,我会首先创建一种可以用来描述手势的基本语言。它应该非常简单;我唯一会考虑的词是:
- 开始-表示笔划的开始
- 角度-笔划的起始角度。这应该是八个主要方向之一(N、NW、W、SW、S、SE、E、NE)或Any表示未对齐手势。您也可以添加组合机制,或者"轴对齐"或其他类似的东西
- 结束-表示笔划的结束
- 行程-表示笔划中的直线路径
- 距离-此特定操作将使用的路径总长度的百分比
- 转弯-表示笔划中的转弯
- 方向-转向的方向。可以选择"左"、"右"、"任意"、"上一个"或"相反"
- 角度-转弯的角度。我建议你只使用三个方向(90度、180度、270度)
- 公差-偏离指定角度的最大公差。这两个方向的默认角度都应该在45度左右,这样才有可能匹配签名中的角度
- 类型-硬或径向。径向角度将是沿着半径的笔划。硬角度将是围绕一个点的转弯
- 半径-如果转弯是径向的,这就是转弯的半径(单位是总路径长度的百分比,当然还有适当的转换)
显然,你可以使角度更精细,但范围越粗,对输入误差的容忍度就越高。不过,过于宽容可能会导致误解。
如果你应用一些模糊逻辑,就不难把任何手势分解成这样的语言。然后,您可以创建一组手势"签名",描述可以执行的各种手势。例如:
//Circle
Start Angle=Any
Turn Type=Radial Direction=Any Angle=180deg Radius=50%
Turn Type=Radial Direction=Previous Angle=180deg Radius=50%
End
//Box
Start Angle=AxisAligned
Travel Distance=25%
Turn Type=Hard Direction=Any Angle=90deg Tolerance=10deg
Travel Distance=25%
Turn Type=Hard Direction=Previous Angle=90deg Tolerance=10deg
Travel Distance=25%
Turn Type=Hard Direction=Previous Angle=90deg Tolerance=10deg
Travel Distance=25%
End
如果你愿意,我可以研究一种算法,它可以取一个点云,并将其退化为一系列这样的命令,这样你就可以将它们与预先生成的签名进行比较。
- 提升 ASIO 无法识别计时器对象
- 从udp接收帧对于人脸识别来说太慢
- 模板类无法识别友元运算符
- std::visit无法识别类型
- 无法识别模板功能
- 我有两个类需要在同一 cpp 文件中相互引用,但第一个类无法识别第二个类类型的对象
- 如何在LLVM中dyn_cast以识别StoreInst?
- 从不同的附加依赖项中识别等同命名的函数
- C++出现控制台错误.我无法识别源代码的问题
- VSCode IntelliSense无法识别SDL框架的SDL_image扩展库
- Qt:"Q3DScatter"即使包含在内也无法识别
- 使用指针的类识别
- 如何静态识别动态堆分配?
- 为什么C++无法识别我的对象实例化?
- C++ 无法识别创建进程'telnet'
- 识别 2D 矢量C++中的位置
- 如何识别项目是 QT 中的文件还是文件夹
- ESP32 无法识别任何设备已连接到其接入点
- 无法识别 Mac c++ 文件系统库
- 识别数组中的重复元素?