slx0009 Asked:2023-10-17 15:24:09 +0800 CST2023-10-17 15:24:09 +0800 CST 2023-10-17 15:24:09 +0800 CST 如何获得新的圆心坐标,使其不与轮廓相交? 772 我正在学习Python中的Opencv并制作一个小项目。Opencv 窗口创建可以使用手部动作推动的圆圈。大部分代码已经完成 - 读取手部动作并获取其轮廓并创建圆圈(圆圈的数据存储在全局数组中)。但我不知道如何推动杯子。 录制视频时,会处理每一帧。我有手的轮廓以及圆的坐标和半径。也就是说,你需要遍历每个圆并检查它是否与轮廓相交。如果没有,那么一切都很好,如果相交,那么您需要垂直于轮廓移动圆,使其停止相交。然后,使用圆圈中的新数据绘制它们(这也准备好了)。 但我还是不明白到底怎样才能把圆圈移开? python-3.x 1 个回答 Voted Best Answer MBo 2023-10-17T15:37:57+08:002023-10-17T15:37:57+08:00 有必要计算从圆心到轮廓的最小距离 - 在最简单的情况下,通过遍历构成轮廓的线段,并计算从中心到线段的垂直 D 的长度(加上- 以及到角落的距离!)。如果它小于 R,则将中心移动与该垂直线共线的向量,长度为 RD。 这是代码,但它没有考虑到中心投影没有落在线段上,而是有交集的情况,所以还需要检查到线段两端的距离 import math def proj(x1, y1, x2, y2, xp, yp): x12 = x2 - x1 y12 = y2 - y1 dotp = x12 * (xp - x1) + y12 * (yp - y1) dot12 = x12 * x12 + y12 * y12 coeff = dotp / dot12 lx = x1 + x12 * coeff ly = y1 + y12 * coeff return lx, ly, coeff x1,y1,x2,y2,cx,cy,R = 0, 0, 10, 0, 5, 5, 6 lx, ly, cf = proj(x1, y1, x2, y2, cx, cy) if 0<=cf<=1: #проекция находится в пределах отрезка dx, dy = cx - lx, cy - ly dist = math.hypot(dx, dy) if dist < R: #окружность пересекает отрезок xshift = dx * (R-dist) / dist yshift = dy * (R-dist) / dist print(xshift, yshift) >>> 0.0 1.0 如果圆心的投影位于线段之外,但到其中一端的距离小于半径,则圆与该线段相交一次或完全包含该线段。在这种情况下,您需要选择一种从角开始排斥的策略 - 要么我们将其移动相同的找到的向量(这是最简单的),要么我们从两个相邻边的向量中选择最小长度,要么我们沿着外平分线,或其他东西。 如果圆可以延伸超出半径,则必须考虑轮廓的哪一侧是外侧以及线段的方向。此外,对于复杂(非凸)轮廓,移动时可能会出现新的交点;在这种情况下,您必须构建类似外部骨架的东西(外角在交点之前的平分线等)。 然而,对于动态系统,可以预测圆与轮廓之间的接触力矩,并在此时给圆一个沿接触半径的冲量
有必要计算从圆心到轮廓的最小距离 - 在最简单的情况下,通过遍历构成轮廓的线段,并计算从中心到线段的垂直 D 的长度(加上- 以及到角落的距离!)。如果它小于 R,则将中心移动与该垂直线共线的向量,长度为 RD。
这是代码,但它没有考虑到中心投影没有落在线段上,而是有交集的情况,所以还需要检查到线段两端的距离
如果圆心的投影位于线段之外,但到其中一端的距离小于半径,则圆与该线段相交一次或完全包含该线段。在这种情况下,您需要选择一种从角开始排斥的策略 - 要么我们将其移动相同的找到的向量(这是最简单的),要么我们从两个相邻边的向量中选择最小长度,要么我们沿着外平分线,或其他东西。
如果圆可以延伸超出半径,则必须考虑轮廓的哪一侧是外侧以及线段的方向。此外,对于复杂(非凸)轮廓,移动时可能会出现新的交点;在这种情况下,您必须构建类似外部骨架的东西(外角在交点之前的平分线等)。
然而,对于动态系统,可以预测圆与轮廓之间的接触力矩,并在此时给圆一个沿接触半径的冲量