簡體   English   中英

尋找直線和輪廓的交點

[英]Finding intersection between straight line and contour

我試圖找到一條直線(紅色虛線)與以紅色突出顯示的輪廓線的交點(見圖)。 我在第二個圖中使用 .get_paths 將所述等高線與其他(第二個圖)隔離。

我看過一個輪廓相交問題, 如何以有效的方式找到兩個輪廓集之間的所有交點,並試圖將其用作基礎,但未能重現任何有用的東西。

http://postimg.org/image/hz01fouvn/

http://postimg.org/image/m6utofwb7/

有沒有人有任何想法?

重新創建繪圖的相關功能,

#for contour 
def p_0(num,t) :
    esc_p = np.sum((((-1)**n)*(np.exp(t)**n)*((math.factorial(n)*((n+1)**0.5))**-1)) for n in range(1,num,1))
    return esc_p+1

tau = np.arange(-2,3,0.1)
r=[]

p1 = p_0(51,tau)
p2 = p_0(51,tau)

for i in p1:
    temp_r=i/p2
    r.append(temp_r)

x,y= np.meshgrid(tau,tau)
cs = plt.contour(x, y, np.log(r),50,colors='k')
whichContour =20
pa = CS.collections[whichContour].get_paths()[0]
v = pa.vertices
xx = v[:, 0]
yy = v[:, 1]
plt.plot(xx, yy, 'r-', label='Crossing contour')

#straight line 
p=0.75
logp = (np.log(p*np.exp(tau)))
plt.plot(tau,logp)

目前的嘗試,

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import math

def intercepting_line() :
matplotlib.rcParams['xtick.direction'] = 'out'
matplotlib.rcParams['ytick.direction'] = 'out'

#fake data

delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = 10.0 * (Z2 - Z1)

#plot
cs = plt.contour(X,Y,Z)
whichContour = 2 # change this to find the right contour lines

#get the vertices to calculate an intercept with a line
p = cs.collections[whichContour].get_paths()[0]
#see: http://matplotlib.org/api/path_api.html#module-matplotlib.path
v = p.vertices
xx = v[:, 0]
yy = v[:, 1]

#this shows the innermost ring now
plt.plot(xx, yy, 'r--', label='inner ring')

#fake line
x = np.arange(-2, 3.0, 0.1)
y=lambda x,m:(m*x)
y=y(x,0.9)
lineMesh = np.meshgrid(x,y)
plt.plot(x,y,'r' ,label='line')

#get the intercepts, two in this case 
x, y = find_intersections(v, lineMesh[1])
print x
print y
#plot the intercepting points
plt.plot(x[0], y[0], 'bo', label='first intercept')
#plt.plot(x[1], y[1], 'rs', label='second intercept')
plt.legend(shadow=True, fancybox=True, numpoints=1, loc='best')
plt.show()

#now we need to calculate the intercept of the vertices and whatever line
#this is pseudo code but works in case of two intercepting contour vertices

def find_intersections(A, B):
# min, max and all for arrays
amin = lambda x1, x2: np.where(x1<x2, x1, x2)
amax = lambda x1, x2: np.where(x1>x2, x1, x2)
aall = lambda abools: np.dstack(abools).all(axis=2)
slope = lambda line: (lambda d: d[:,1]/d[:,0])(np.diff(line, axis=0))

x11, x21 = np.meshgrid(A[:-1, 0], B[:-1, 0])
x12, x22 = np.meshgrid(A[1:, 0], B[1:, 0])
y11, y21 = np.meshgrid(A[:-1, 1], B[:-1, 1])
y12, y22 = np.meshgrid(A[1:, 1], B[1:, 1])
m1, m2 = np.meshgrid(slope(A), slope(B))
m1inv, m2inv = 1/m1, 1/m2

yi = (m1*(x21-x11-m2inv*y21) + y11)/(1 - m1*m2inv)
xi = (yi - y21)*m2inv + x21

xconds = (amin(x11, x12) < xi, xi <= amax(x11, x12),
          amin(x21, x22) < xi, xi <= amax(x21, x22) )
yconds = (amin(y11, y12) < yi, yi <= amax(y11, y12),
          amin(y21, y22) < yi, yi <= amax(y21, y22) )

return xi[aall(xconds)], yi[aall(yconds)]

目前它找到了相交點,但只在線條一致的地方,我在這里找不到解決方案的主要原因是我不明白原作者在這里的思路,

yi = (m1*(x21-x11-m2inv*y21) + y11)/(1 - m1*m2inv)
xi = (yi - y21)*m2inv + x21     

使用shapely可以找到交點,而不是使用該點作為fsolve()的初始猜測值來找到真正的解決方案:

#for contour 
def p_0(num,t) :
    esc_p = np.sum((((-1)**n)*(np.exp(t)**n)*((math.factorial(n)*((n+1)**0.5))**-1)) for n in range(1,num,1))
    return esc_p+1

tau = np.arange(-2,3,0.1)

x,y= np.meshgrid(tau,tau)
cs = plt.contour(x, y, np.log(p_0(51, y)/p_0(51, x)),[0.2],colors='k')

p=0.75
logp = (np.log(p*np.exp(tau)))
plt.plot(tau,logp)

from shapely.geometry import LineString
v1 = cs.collections[0].get_paths()[0].vertices

ls1 = LineString(v1)
ls2 = LineString(np.c_[tau, logp])
points = ls1.intersection(ls2)
x, y = points.x, points.y

from scipy import optimize

def f(p):
    x, y = p
    e1 = np.log(0.75*np.exp(x)) - y
    e2 = np.log(p_0(51, y)/p_0(51, x)) - 0.2
    return e1, e2

x2, y2 = optimize.fsolve(f, (x, y))

plt.plot(x, y, "ro")
plt.plot(x2, y2, "gx")

print x, y
print x2, y2

這是輸出:

0.273616328952 -0.0140657435002
0.275317387697 -0.0123646847549

和情節:

在此處輸入圖片說明

將輪廓線視為折線並將頂點坐標插入隱式線方程 (F(P) = aX + bY + c = 0)。 符號的每次變化都是一個交集,通過求解 2x2 線性方程來計算。 您不需要復雜的求解器。

如果需要同時檢測等高線,也不是很復雜:考慮通過該線的垂直平面的地形截面。 您將通過沿交叉的網格圖塊邊緣的線性插值獲得高度。 尋找與網格的交點與 Bresenham 畫線算法密切相關。

那么你得到的是一個配置文件,即單個變量的函數。 定位與水平面(等值)的交點也是通過檢測符號的變化來完成的。

這是我用來解決這個問題的一種方法

def straight_intersection(straight1, straight2):
    p1x = straight1[0][0]
    p1y = straight1[0][1]
    p2x = straight1[1][0]
    p2y = straight1[1][1]
    p3x = straight2[0][0]
    p3y = straight2[0][1]
    p4x = straight2[1][0]
    p4y = straight2[1][1]
    x = p1y * p2x * p3x - p1y * p2x * p4x - p1x * p2y * p4x + p1x * p2y * p3x - p2x * p3x * p4y + p2x * p3y * p4x + p1x * p3x * p4y - p1x * p3y * p4x
    x = x / (p2x * p3y - p2x * p4y - p1x * p3y + p1x * p4y + p4x * p2y - p4x * p1y - p3x * p2y + p3x * p1y)
    y = ((p2y - p1y) * x + p1y * p2x - p1x * p2y) / (p2x - p1x)
    return (x, y)

雖然這個問題現在已經很老了,但我想為子孫后代分享我對這個問題的回答。 實際上,對於這個問題,我發現了另外兩個相對有效的解決方案。

第一個解決方案是在 opencv 中遞歸地使用pointPolygonTest

# Enumerate the line segment points between 2 points
for pt in zip(*line(*p1, *p2)):
    if cv2.pointPolygonTest(conts[0], pt, False) == 0:  # If the point is on the contour
        return pt

第二種解決方案,您可以簡單地繪制輪廓和線條並制作一個np.logical_and()來獲得答案

blank = np.zeros((1000, 1000))
blank_contour = drawContour(blank.copy(), cnt[0], 0, 1, 1)
blank_line = cv2.line(blank.copy(), line[0], line[1], 1, 1)
intersections = np.logical_and(blank_contour, black_line)

points = np.where(intersections == 1)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM