Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-有没有办法识别角度的方向性?_Python_Numpy_Scikit Image_Angle - Fatal编程技术网

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

Python-有没有办法识别角度的方向性?,python,numpy,scikit-image,angle,Python,Numpy,Scikit Image,Angle,下图显示了一种所谓的泪滴状DNA分子。对我来说,这个DNA弯曲角度的分布是非常有趣的。在红色中,显示了由skimage.形态学.skeletonize生成的痕迹。 在我的程序中,跟踪被表示为一个numpy数组:numpy数组中的每个条目都是一个float64元组,对应于图像中跟踪点的x和y坐标。因此,如果我应用np.diff(trace,axis=0),我将得到我想要在向量中分析的片段 问题:现在,我想知道如何计算两个后续段之间的角度。但是,我现在不知道角度是顺时针还是逆时针。例如,在某一点上,

下图显示了一种所谓的泪滴状DNA分子。对我来说,这个DNA弯曲角度的分布是非常有趣的。在红色中,显示了由
skimage.形态学.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


符号变化现在表示曲线的方向变化。

为什么要计算
np.arcin
而不是
np.arccos
?我使用| axb |=| a | b | sin(θ),其中θ是a和b之间的围角,但是我想结果向量的方向对你的问题来说很重要。如果你跨过两个向量走一步,符号就会起作用(想象一个向量相加的三角形:你沿着两条边到达结果向量)。加法是可交换的,但向左或向右的“利手”可以通过叉积来识别,它会切换符号(如上例所示:绝对角度值相同,但符号是反向的)。也许可以看看啊是的:只要你右转,seg(i-1)和seg(i)的叉积总是有相同的符号。如果它切换标志,则表示最后一段向左拐。角度的问题在于,它们不是基2*pi,而是,正如你正确评论的那样,定向的。是的。我认为它是大多数trig函数的默认值。祝你好运,你会成功的,这是一个有趣的问题。如果你被卡住了,把问题中的一些数据贴出来。