需求:求两条直线的距离
方法:通过两条直线上的两个点分别向另一条直线做垂线,两个垂点的中心点连接作为距离。
如下图:黑线表示待求的两条直线间的距离,红线表示右侧直线向左侧直线的垂线,蓝线表示左侧直线向右侧直线的垂线,紫线表示两条直线上垂点中点的连线(代表距离)。
实现代码:
import math
import cv2
def intersectionLines(a1, a2, b1, b2):
return (
((a1[0] * a2[1] - a1[1] * a2[0]) * (b1[0] - b2[0]) -
(b1[0] * b2[1] - b1[1] * b2[0]) * (a1[0] - a2[0])) /
((a1[0] - a2[0]) * (b1[1] - b2[1]) -
(a1[1] - a2[1]) * (b1[0] - b2[0])),
((a1[0] * a2[1] - a1[1] * a2[0]) * (b1[1] - b2[1]) -
(b1[0] * b2[1] - b1[1] * b2[0]) * (a1[1] - a2[1])) /
((a1[0] - a2[0]) * (b1[1] - b2[1]) -
(a1[1] - a2[1]) * (b1[0] - b2[0]))
)
def p_to_l(point,l_p1,l_p2):
if l_p1[0]-l_p2[0]==0:
crop=(l_p1[0],point[1])
# print("crop",crop)
elif l_p1[1]-l_p2[1]==0:
crop=(point[0],l_p1[1])
else:
k_l=(l_p1[1]-l_p2[1])/(l_p1[0]-l_p2[0])
# print(k_l)
k=-1/k_l
# print(k)
b=point[1]-k*point[0]
# print(b)
x=l_p1[0]
# print(x)
y=k*x+b
point2=(x,y)
# print(point)
# print(point2)
# print(l_p1,l_p2)
crop=intersectionLines(point, point2, l_p1, l_p2)
return crop
def p_to_distance(p1,p2):
return math.sqrt((p1[0]-p2[0])**2+(p1[1]-p2[1])**2)
def to_overlap_pts(a1, a2, b1,b2):
if a1[1]>a2[1]:
l1_hight=a1
l1_low=a2
else:
l1_hight=a2
l1_low=a1
if b1[1]>b2[1]:
l2_hight=b1
l2_low=b2
else:
l2_hight=b2
l2_low=b1
l1_p1, l1_p2, l2_p1, l2_p2 = (0., 0.), (0., 0.), (0., 0.), (0., 0.)
point1_state=0
point2_state=0
#直线没有重合部分l1
l1_l=p_to_l(l1_low,l2_low,l2_hight)
l1_h=p_to_l(l1_hight,l2_low,l2_hight)
# print("l1",l1_h)
# print("l2_low",l2_low)
# print("l2_hight",l2_hight)
list=[l2_low[0],l2_hight[0]]
l=min(list)
r=max(list)
if l<=l1_h[0]<=r:
point1_state=1
if l<=l1_l[0]<=r:
point2_state=1
print("state",point1_state,point2_state)
if point1_state==0 and point2_state==0:
print("框选错误,请重新框选")
else:
l1_b=0
l1_t=0
l2_b=0
l2_t=0
#左边直线
if l2_low[0]<l2_hight[0]:
l=l2_low[0]
r=l2_hight[0]
else:
r = l2_low[0]
l = l2_hight[0]
cro_p1 = p_to_l(l1_low, l2_low, l2_hight)
if l<=cro_p1[0]<=r:
p1=l1_low
p2=cro_p1
cro_p1 = (cro_p1[0], cro_p1[1])
l1_b=1
else:
pass
cro_p2 = p_to_l(l1_hight, l2_low, l2_hight)
if l<=cro_p2[0]<=r:
p1=l1_hight
p2=cro_p2
cro_p2 = (cro_p2[0], cro_p2[1])
l1_t=1
else:
pass
#右边直线
if l1_low[0]<l1_hight[0]:
l=l1_low[0]
r=l1_hight[0]
else:
r= l1_low[0]
l = l1_hight[0]
cro_p3 = p_to_l(l2_low, l1_low, l1_hight)
if l<=cro_p3[0]<=r:
p1=l2_low
p2=cro_p3
cro_p3 = (cro_p3[0], cro_p3[1])
l2_b=1
else:
pass
cro_p4 = p_to_l(l2_hight, l1_low, l1_hight)
if l<=cro_p4[0]<=r:
p1=l2_hight
p2=cro_p4
cro_p4 = (cro_p4[0], cro_p4[1])
l2_t=1
else:
pass
#右直线投影到左直线
if l1_b+l1_t==0 and l2_b+l2_t==2:
l1_p1=cro_p3
l1_p2=cro_p4
l2_p1=l2_low
l2_p2=l2_hight
#左直线投影到右直线
elif l1_b+l1_t==2 and l2_b+l2_t==0:
l1_p1=l1_low
l1_p2=l1_hight
l2_p1=cro_p1
l2_p2=cro_p2
#右直线投影到作直线,左直线一个点投影到右直线
elif l1_b + l1_t == 1 and l2_b + l2_t == 2:
#左直线上点
if l1_t == 1:
l2_p1 = l2_low
l2_p2 = cro_p2
#左直线下
else:
l2_p1 = cro_p1
l2_p2 = l2_hight
l1_p1 = cro_p3
l1_p2 = cro_p4
#左直线投影到右直线,右直线一个点投影到左直线
elif l1_b + l1_t == 2 and l2_b + l2_t == 1:
#右直线上点
if l1_t == 1:
l1_p1 = l1_low
l1_p2 = cro_p4
#右直线下点
else:
l1_p1 = cro_p3
l1_p2 = l1_hight
l2_p1 = cro_p1
l2_p2 = cro_p2
elif l1_b == 1 and l2_t == 1:
l1_p1 = l1_low
l1_p2 = cro_p4
l2_p1 = cro_p1
l2_p2 = l2_hight
elif l1_t == 1 and l2_b == 1:
l1_p1 = cro_p3
l1_p2 = l1_hight
l2_p1 = l2_low
l2_p2 = cro_p2
return l1_p1, l1_p2, l2_p1, l2_p2
def coincidence_part(a1, a2, b1,b2):
# img=cv2.imread("1030_1_undistorted.png")
if a1[1]>a2[1]:
l1_hight=a1
l1_low=a2
else:
l1_hight=a2
l1_low=a1
if b1[1]>b2[1]:
l2_hight=b1
l2_low=b2
else:
l2_hight=b2
l2_low=b1
#直线没有重合部分l1
if l1_hight[1]<=l2_low[1] or l1_low[1]>=l2_hight[1]:
print("框选错误,请重新框选")
else:
l1_b=0
l1_t=0
l2_b=0
l2_t=0
#左边直线
if l2_low[0]<l2_hight[0]:
l=l2_low[0]
r=l2_hight[0]
else:
r = l2_low[0]
l = l2_hight[0]
cro_p1 = p_to_l(l1_low, l2_low, l2_hight)
if l<=cro_p1[0]<=r:
p1=l1_low
p2=cro_p1
cro_p1 = (cro_p1[0], cro_p1[1])
l1_b=1
else:
pass
cro_p2 = p_to_l(l1_hight, l2_low, l2_hight)
if l<=cro_p2[0]<=r:
p1=l1_hight
p2=cro_p2
cro_p2 = (cro_p2[0], cro_p2[1])
l1_t=1
else:
pass
#右边直线
if l1_low[0]<l1_hight[0]:
l=l1_low[0]
r=l1_hight[0]
else:
r= l1_low[0]
l = l1_hight[0]
cro_p3 = p_to_l(l2_low, l1_low, l1_hight)
if l<=cro_p3[0]<=r:
p1=l2_low
p2=cro_p3
cro_p3 = (cro_p3[0], cro_p3[1])
l2_b=1
else:
pass
cro_p4 = p_to_l(l2_hight, l1_low, l1_hight)
if l<=cro_p4[0]<=r:
p1=l2_hight
p2=cro_p4
cro_p4 = (cro_p4[0], cro_p4[1])
l2_t=1
else:
pass
#右直线投影到左直线
if l1_b+l1_t==0 and l2_b+l2_t==2:
l1_p1=cro_p3
l1_p2=cro_p4
l2_p1=l2_low
l2_p2=l2_hight
#左直线投影到右直线
elif l1_b+l1_t==2 and l2_b+l2_t==0:
l1_p1=l1_low
l1_p2=l1_hight
l2_p1=cro_p1
l2_p2=cro_p2
#右直线投影到作直线,左直线一个点投影到右直线
elif l1_b + l1_t == 1 and l2_b + l2_t == 2:
#左直线上点
if l1_t == 1:
l2_p1 = l2_low
l2_p2 = cro_p2
#左直线下
else:
l2_p1 = cro_p1
l2_p2 = l2_hight
l1_p1 = cro_p3
l1_p2 = cro_p4
#左直线投影到右直线,右直线一个点投影到左直线
elif l1_b + l1_t == 2 and l2_b + l2_t == 1:
#右直线上点
if l1_t == 1:
l1_p1 = l1_low
l1_p2 = cro_p4
#右直线下点
else:
l1_p1 = cro_p3
l1_p2 = l1_hight
l2_p1 = cro_p1
l2_p2 = cro_p2
elif l1_b == 1 and l2_t == 1:
l1_p1 = l1_low
l1_p2 = cro_p4
l2_p1 = cro_p1
l2_p2 = l2_hight
elif l1_t == 1 and l2_b == 1:
l1_p1 = cro_p3
l1_p2 = l1_hight
l2_p1 = l2_low
l2_p2 = cro_p2
# print(l1_b, l1_t, l2_b, l2_t)
# print(l1_p1,l1_p2,l2_p1,l2_p2)
l1_c = ((l1_p1[0] + l1_p2[0])/ 2, (l1_p1[1] + l1_p2[1]) / 2)
l1_to_l2=p_to_l(l1_c,l2_p1,l2_p2)
l1_to_l2=(l1_to_l2[0],l1_to_l2[1])
l2_c = ((l2_p1[0] + l2_p2[0]) / 2, (l2_p1[1] + l2_p2[1]) / 2)
# print(l2_c,l1_p1,l1_p2)
l2_to_l1=p_to_l(l2_c,l1_p1,l1_p2)
l2_to_l1 = (int(l2_to_l1[0]), int(l2_to_l1[1]))
l1=p_to_distance(l1_c,l1_to_l2)
l2=p_to_distance(l2_c,l2_to_l1)
# print(l1,l2)
distance=(l1+l2)/2
# print(distance)
return distance
# coincidence_part((200,100),(200,600),(800,100),(800,621))
# coincidence_part((100,100),(600,100),(200,400),(500,400))