问题描述
我正在尝试编写一个代码,其中我有一个向量列表,我必须找到每个向量与其余向量之间的角度。(我正在研究 mediapipe 的手部地标)。 到目前为止,我的代码是这样的:
vectors = [thumb_cmc_vec,thumb_mcp_vec,thumb_ip_vec,thumb_tip_vec,index_mcp_vec,index_pip_vec,index_dip_vec,index_tip_vec,middle_mcp_vec,middle_pip_vec,middle_dip_vec,middle_tip_vec,ring_mcp_vec,ring_pip_vec,ring_dip_vec,ring_tip_vec,pinky_mcp_vec,pinky_pip_vec,pinky_dip_vec,pinky_tip_vec]
for vector in vectors:
next_vector = vector + 1
print(vector)
for next_vector in vectors:
print(next_vector)
M = (np.linalg.norm(vector) * np.linalg.norm(next_vector))
ES = np.dot(vector,next_vector)
th = math.acos(ES / M)
list.append(th)
print(list)
其中 M = 当前向量集的范数的乘积,ES =
向量的标量积和 th = 向量的角度。
我的问题是变量 next_vector
总是从列表的第一个向量开始 for 循环,即使我希望它从前一个循环的下一个向量开始,以免有重复的结果。此外,当两个循环都在第三个向量 (thumb_ip_vec) 上时,我收到此错误
th = math.acos(ES / M)
ValueError: 数学域错误。有没有办法解决这个问题?谢谢!
解决方法
我认为您可以遍历列表索引(使用 for i in range(len(vectors) - 1):
# Iterate from 0 to len(vectors) -1
vector = vectors[i]
for j in range(i + 1,len(vectors)):
# Iterate from index i + 1 to len(vectors)
next_vector = vectors[j]
M = (np.linalg.norm(vector) * np.linalg.norm(next_vector))
ES = np.dot(vector,next_vector)
th = math.acos(ES / M)
list.append(th)
print(list)
)并通过它们的索引访问元素,而不是遍历每个元素
{{1}},
这里的有效解决方案是 vectors
的 iterate over combinations
:
from itertools import combinations # At top of file
for vector,next_vector in itertools.combinations(vectors,2):
M = (np.linalg.norm(vector) * np.linalg.norm(next_vector))
ES = np.dot(vector,next_vector)
th = math.acos(ES / M)
list.append(th)
它比循环索引和索引要快得多,降低了循环嵌套的级别,并使您更清楚地了解您要执行的操作(处理输入的每个唯一配对)。
,我不确定我是否理解您的问题,但请考虑改用范围。 范围允许您迭代,但不只调用确切的值,而是通过调用它的地址。 这意味着您可以操纵该索引来访问相邻值。
for i in range(len(iterables)-1):
ii = i+1
initial_value = iterables[i]
next_value = iterables[ii]
for ii in range(len(iterables)):
# do_rest_of_code
有点像邮递员,你可以在不知道邻居地址的情况下联系到某人的邻居。
上述结构通常有效,但您需要对其进行调整以满足您的需求。