2

我正在尝试编写一个代码,其中我有一个向量列表,我必须找到每个向量与其余向量之间的角度。(我正在研究 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: math domain error。有没有办法解决这个问题?谢谢!

4

3 回答 3

2

这里的有效解决方案是迭代combinationsvectors

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)

它比在索引和索引上循环要快得多,降低了循环嵌套的级别,并且更清楚您要做什么(处理输入的每个唯一配对)。

于 2021-05-02T16:31:15.123 回答
2

我认为您可以遍历列表索引(使用range(len(vectors) - 1))并通过索引访问元素,而不是遍历每个元素

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)
于 2021-05-02T15:55:07.757 回答
1

我不确定我是否理解您的问题,但请考虑改用范围。范围允许您进行迭代,但不只调用确切的值,而是调用它的地址。这意味着您可以操纵该索引来访问相邻值。

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
                               

有点像邮递员,你可以在不知道邻居地址的情况下联系到某人的邻居。
上面的结构通常可以工作,但您需要对其进行调整以满足您的需求。

于 2021-05-02T16:14:25.150 回答