Python - 有没有办法识别角度的方向性?

Python - is there a way to identify the directionality of angles?

在下图中,显示了一种所谓的泪滴状 DNA 分子。对我来说,这个 DNA 弯曲角度的分布非常有趣。在红色中,显示了 skimage.morphology.skeletonize 产生的轨迹。 在我的程序中,轨迹被表示为一个 numpy 数组:numpy 数组中的每个条目都是一个 float64 元组,对应于图像中轨迹点的 x 和 y 坐标。因此,如果我应用 np.diff(trace, axis=0),我会从向量中获取要分析的片段。

问题:现在,我现在如何计算两个后续线段之间的角度。但是,我现在不知道角度是顺时针还是逆时针。例如,在某一时刻,DNA 向左弯曲,因此那里的角度与 DNA 向右弯曲时测得的角度不同,而通常情况下是这样。有什么方法可以解决这个问题?

目前我的想法: 我想对每个线段进行插值,然后检查下一段是否位于插值线的下方或上方,指示顺时针与逆时针角度。但这似乎很难实施,而且由于我是初学者,任何意见都将不胜感激!

我认为叉积 np.cross 会对您有所帮助。对于一个简单的三角形,首先逆时针旋转,然后顺时针旋转,这可能看起来像这样(可以优化,为了清晰起见,让它更长)。角度输出是矢量与遵循右手法则的方向之间的夹角:编辑:添加了方向变化的曲线,添加了图表(逆时针方向的注释):

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path

def drangl(vsgi, vsgi1):
    '''sin(theta)=|axb|/(|a||b|)'''
    return np.arcsin(np.cross(vsgi, vsgi1)/np.linalg.norm(vsgi)/np.linalg.norm(vsgi1))

print('going around the traingle counter-clockwise and clockwise:\n')

trace = np.array([(0.,0.), (10.,-1.), (5.,10.), (0.,0.)])
vsegs = np.diff(trace, axis=0)

for iv in [0,1,-1]: # counter-clockwise
    print(f'ctr-cl: {iv:d} {drangl(vsegs[iv], vsegs[iv+1]):2.2f}')
for iv in [-1,1,0]: # clockwise
    print(f'cw: {iv:d} {drangl(vsegs[iv], vsegs[iv+1]):2.2f}')
    
print('\nnow with direction change in the path:\n')

trace = np.array([(0.,0.), (10.,-1.), (9., 5.), (12., 5.), (5.,10.), (0.,0.)])
vsegs = np.diff(trace, axis=0)
    
for iv in [0,1,2,3,-1]: # counter-clockwise
    print(f'ctr-cl: {iv:d} {drangl(vsegs[iv], vsegs[iv+1]):2.2f}')
for iv in [-1,3,2,1,0]: # clockwise
    print(f'cw: {iv:d} {drangl(vsegs[iv], vsegs[iv+1]):2.2f}')
    
codes = [
    Path.MOVETO,
    Path.LINETO,
    Path.LINETO,
    Path.LINETO,
    Path.LINETO,
    Path.CLOSEPOLY,
]

path = Path(trace, codes)
fig, ax = plt.subplots()
patch = patches.PathPatch(path, facecolor='white', lw=2)
ax.add_patch(patch)
ax.set_xlim(-1, 13)
ax.set_ylim(-2, 11)
ax.annotate('turns right', xy=(9, 5), xytext=(5, 5),
            arrowprops=dict(facecolor='black', shrink=0.05),
            )
ax.annotate('turns left', xy=(12, 5), xytext=(10, 10),
            arrowprops=dict(facecolor='black', shrink=0.05),
            )
plt.show()

产生

逆时针和顺时针绕小三角:

ctr-cl: 0 1.04
ctr-cl: 1 0.89
ctr-cl: -1 1.21
cw: -1 1.21
cw: 1 0.89
cw: 0 1.04

now with direction change in the path:

ctr-cl: 0 1.31
ctr-cl: 1 -1.41
ctr-cl: 2 0.62
ctr-cl: 3 1.41
ctr-cl: -1 1.21
cw: -1 1.21
cw: 3 1.41
cw: 2 0.62
cw: 1 -1.41
cw: 0 1.31

符号变化现在指示曲线改变方向的位置。