Python 将x、y点集与另一个缩放、旋转、平移且缺少元素的集相匹配

Python 将x、y点集与另一个缩放、旋转、平移且缺少元素的集相匹配,python,performance,geometry,affinetransform,astronomy,Python,Performance,Geometry,Affinetransform,Astronomy,(我为什么要这样做?请参见下面的说明) 考虑两组点,A和B,如下所示 它可能看起来不像,但setA在setB中是“隐藏”的。由于B中的点相对于A在(x,y)中缩放、旋转和平移,因此不容易看到。更糟糕的是,A中存在的一些点在B中缺失,B中包含许多不在A中的点 我需要找到必须应用于B集合的适当缩放、旋转和平移,以便将其与集合A匹配。在上述情况下,正确的值为: scale = 0.14, rot_angle = 0.0, x_transl = 35.0, y_transl = 2.0 哪个产生了(

(我为什么要这样做?请参见下面的说明)

考虑两组点,
A
B
,如下所示

它可能看起来不像,但set
A
在set
B
中是“隐藏”的。由于
B
中的点相对于
A
(x,y)
中缩放、旋转和平移,因此不容易看到。更糟糕的是,
A
中存在的一些点在
B
中缺失,
B
中包含许多不在
A
中的点

我需要找到必须应用于
B
集合的适当缩放、旋转和平移,以便将其与集合
A
匹配。在上述情况下,正确的值为:

scale = 0.14, rot_angle = 0.0, x_transl = 35.0, y_transl = 2.0
哪个产生了(足够好的)匹配

(红色,仅显示匹配的
B
点;这些点位于扇区
10001)我将通过标记所有点并从每组中找到3个点的所有可能组合来解决此问题

# normalize B data to same format as A
set_Bx, set_By = (set_B)
set_B = []
for i in range(len(set_Bx)):
    set_B.append([set_Bx[i],set_By[i]])
'''
set_B = [[2689.28, 2061.19], [3507.04, 3700.27], [2895.67, 2131.2], 
[1051.3, 1837.3], [1929.49, 2017.52], [1035.97, 80.96], [752.44, 
3524.61], [130.62, 3821.22], [620.06, 3711.53], [2769.06, 1812.12], 
[1580.77, 1868.33], [281.76, 3865.77], [224.54, 3273.77], [3848.3, 
2100.71]]
'''

list(itertools.combinations(range(len(set_A)), 3))
list(itertools.combinations(range(len(set_B)), 3))

2) 对于每个3点编组,计算相应三角形的边;对A组和B组重复此过程

dist = sqrt( (x2 - x1)**2 + (y2 - y1)**2 )

3) 然后减小每个三角形的边比,使每个三角形的最小边等于1;其他方面的比例也相应降低

在两个相似的三角形中:

这两个三角形的周长与三角形的周长之比相同 边。相应的侧面、中间带和高度都将处于 这个比例是相同的

4) 最后,对于a组中的每个三角形,使用元素减法与B组中的每个三角形进行比较。然后对结果元素求和,从A和B中找出总和最小的三角形

list(numpy.array(list1)-numpy.array(list2))

5) 给定匹配三角形;就CPU/RAM而言,找到适当的缩放、平移和旋转应该相对简单。

ETA1:草稿脚本

ETA2:注释中讨论的修补错误:使用sum(abs())而不是abs(sum())。现在它工作了,速度也很快

'''
known correct solution

A = [[1894.41, 1957.065],[1967.31, 1960.865],[2015.81, 1981.665]]
B = [[1051.3, 1837.3],[1580.77, 1868.33],[1929.49, 2017.52]]

'''
import numpy as np
import itertools
import math
import operator

set_A = [[2015.81, 1981.665], [1967.31, 1960.865], [1962.91, 1951.365],
        [1964.91, 1994.565], [1894.41, 1957.065]]
set_B = [[2689.28, 3507.04, 2895.67, 1051.3, 1929.49, 1035.97, 752.44, 130.62,
        620.06, 2769.06, 1580.77, 281.76, 224.54, 3848.3],
        [2061.19, 3700.27, 2131.2, 1837.3, 2017.52, 80.96, 3524.61, 3821.22,
        3711.53, 1812.12, 1868.33, 3865.77, 3273.77, 2100.71]]

# normalize set B data to set A format
set_Bx, set_By = (set_B)
set_B = []
for i in range(len(set_Bx)):
    set_B.append([set_Bx[i],set_By[i]])

'''
set_B = [[2689.28, 2061.19], [3507.04, 3700.27], [2895.67, 2131.2], 
[1051.3, 1837.3], [1929.49, 2017.52], [1035.97, 80.96], [752.44, 3524.61], 
[130.62, 3821.22], [620.06, 3711.53], [2769.06, 1812.12], [1580.77, 1868.33], 
[281.76, 3865.77], [224.54, 3273.77], [3848.3, 2100.71]]
'''

print set_A
print set_B
print len(set_A)
print len(set_B)

set_A_tri = list(itertools.combinations(range(len(set_A)), 3))
set_B_tri = list(itertools.combinations(range(len(set_B)), 3))

print set_A_tri
print set_B_tri
print len(set_A_tri)
print len(set_B_tri)

'''
set_A = [[2015.81, 1981.665], [1967.31, 1960.865], [1962.91, 1951.365], 
[1964.91, 1994.565], [1894.41, 1957.065]]

set_A_tri = [(0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 3), (0, 2, 4), (0, 3, 4), 
(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
'''

def distance(x1,y1,x2,y2):
    return math.sqrt((x2 - x1)**2 + (y2 - y1)**2 )

def tri_sides(set_x, set_x_tri):

    triangles = []
    for i in range(len(set_x_tri)):

        point1 = set_x_tri[i][0]
        point2 = set_x_tri[i][1]
        point3 = set_x_tri[i][2]

        point1x, point1y = set_x[point1][0], set_x[point1][1]
        point2x, point2y = set_x[point2][0], set_x[point2][1]
        point3x, point3y = set_x[point3][0], set_x[point3][1] 

        len1 = distance(point1x,point1y,point2x,point2y)
        len2 = distance(point1x,point1y,point3x,point3y)
        len3 = distance(point2x,point2y,point3x,point3y)

        min_side = min(len1,len2,len3)
        len1/=min_side
        len2/=min_side
        len3/=min_side
        t=[len1,len2,len3]
        t.sort()
        triangles.append(t)

    return triangles

A_triangles = tri_sides(set_A, set_A_tri)
B_triangles = tri_sides(set_B, set_B_tri)

print A_triangles
'''
[[1.0, 5.0405616860744304, 5.822935502560814], 
[1.0, 1.5542012854321234, 1.5619803879976761], 
[1.0, 1.3832883678507584, 2.347214708755337], 
[1.0, 1.2141910838179129, 1.4096730529373076], 
[1.0, 1.1275138587537166, 2.0318412465223665], 
[1.0, 1.5207417600732074, 2.3589630093994876], 
[1.0, 3.2270326342163584, 4.13069930678442], 
[1.0, 6.565440477766354, 6.972550347780966], 
[1.0, 2.1606693015281997, 2.3635387983160885], 
[1.0, 1.589425903498476, 1.846471085870448]]
'''
print B_triangles

def list_subtract(list1,list2):

    return np.absolute(np.array(list1)-np.array(list2))

sums = []
threshold = 1
for i in range(len(A_triangles)):
    for j in range(len(B_triangles)):
        k = sum(list_subtract(A_triangles[i], B_triangles[j]))
        if k < threshold:
            sums.append([i,j,k])
# sort by smallest sum
sums = sorted(sums, key=operator.itemgetter(2))

print sums
print 'winner %s' % sums[0]
print sums[0][0]
print sums[0][1]
match_A = set_A_tri[sums[0][0]]
match_B = set_B_tri[sums[0][1]]
print 'triangle A %s matches triangle B %s' % (match_A, match_B)

match_A_pts = []
match_B_pts = []
for i in range(3):
    match_A_pts.append(set_A[match_A[i]])
    match_B_pts.append(set_B[match_B[i]])

print 'triangle A has points %s' % match_A_pts
print 'triangle B has points %s' % match_B_pts

'''
winner [2, 204, 0.031415474959738399]
2
204
triangle A (0, 1, 4) matches triangle B (3, 4, 10)
triangle A has points [[2015.81, 1981.665], [1967.31, 1960.865], [1894.41, 1957.065]]
triangle B has points [[1051.3, 1837.3], [1929.49, 2017.52], [1580.77, 1868.33]]
'''
“”
已知正确解
A=[[1894.411957.065]、[1967.311960.865]、[2015.811981.665]]
B=[[1051.31837.3]、[1580.771868.33]、[1929.492017.52]]
'''
将numpy作为np导入
进口itertools
输入数学
进口经营者
set_A=[2015.811981.665]、[1967.311960.865]、[1962.911951.365],
[1964.91, 1994.565], [1894.41, 1957.065]]
集合B=[[2689.283507.042895.671051.31929.491035.97752.44130.62,
620.06, 2769.06, 1580.77, 281.76, 224.54, 3848.3],
[2061.19, 3700.27, 2131.2, 1837.3, 2017.52, 80.96, 3524.61, 3821.22,
3711.53, 1812.12, 1868.33, 3865.77, 3273.77, 2100.71]]
#规范化SETB数据以设置格式
set_Bx,set_By=(set_B)
set_B=[]
对于范围内的i(len(set_Bx)):
set_B.append([set_Bx[i],set_By[i]]))
'''
集合B=[2689.282061.19]、[3507.043700.27]、[2895.672131.2],
[1051.3, 1837.3], [1929.49, 2017.52], [1035.97, 80.96], [752.44, 3524.61], 
[130.62, 3821.22], [620.06, 3711.53], [2769.06, 1812.12], [1580.77, 1868.33], 
[281.76, 3865.77], [224.54, 3273.77], [3848.3, 2100.71]]
'''
打印集
打印集
打印透镜(设置A)
打印透镜(套)
set_A_tri=列表(itertools.组合(范围(len(set_A)),3))
set_B_tri=列表(itertools.组合(范围(len(set_B)),3))
打印集
打印集
打印透镜(设置为三个)
打印透镜(设置为三个)
'''
set_A=[2015.811981.665]、[1967.311960.865]、[1962.911951.365],
[1964.91, 1994.565], [1894.41, 1957.065]]
集合A_tri=[(0,1,2),(0,1,3),(0,1,4),(0,2,3),(0,2,4),(0,3,4),
(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
'''
def距离(x1、y1、x2、y2):
返回数学sqrt((x2-x1)**2+(y2-y1)**2)
def tri_侧面(设置_x,设置_x_tri):
三角形=[]
对于范围内的i(len(set_x_tri)):
第1点=集合[i][0]
第2点=集合[i][1]
第3点=集合[i][2]
点1X,点1Y=set_x[point1][0],set_x[point1][1]
点2x,点2y=set_x[point2][0],set_x[point2][1]
点3x,点3y=set_x[point3][0],set_x[point3][1]
len1=距离(点1X、点1Y、点2X、点2Y)
len2=距离(点1X、点1Y、点3X、点3Y)
len3=距离(点2x、点2y、点3x、点3y)
最小侧=最小(透镜1、透镜2、透镜3)
len1/=最小侧
len2/=最小侧
len3/=最小侧
t=[len1,len2,len3]
t、 排序()
三角形。附加(t)
返回三角形
A_三角形=三边(集合A,集合A_三边)
B_三角形=三边(集合B,集合B_tri)
打印A_三角形
'''
[[1.0, 5.0405616860744304, 5.822935502560814], 
[1.0, 1.5542012854321234, 1.5619803879976761], 
[1.0, 1.3832883678507584, 2.347214708755337], 
[1.0, 1.2141910838179129, 1.4096730529373076], 
[1.0, 1.1275138587537166, 2.0318412465223665], 
[1.0, 1.5207417600732074, 2.3589630093994876], 
[1.0, 3.2270326342163584, 4.13069930678442], 
[1.0, 6.565440477766354, 6.972550347780966], 
[1.0, 2.1606693015281997, 2.3635387983160885], 
[1.0, 1.589425903498476, 1.846471085870448]]
'''
打印B_三角形
def list_减法(列表1、列表2):
返回np.absolute(np.array(list1)-np.array(list2))
总和=[]
阈值=1
对于范围内的i(len(A_三角形)):
对于范围内的j(len(B_三角形)):
k=和(列表减去(A_三角形[i],B_三角形[j]))
如果k<阈值:
sums.append([i,j,k])
#按最小和排序
sums=排序(sums,key=operator.itemgetter(2))
打印金额
打印“赢家%s”%s[0]
打印总和[0][0]
打印金额[0][1]
match_A=set_A_tri[总和[0][0]]
match_B=set_B_tri[总和[0][1]]
打印“三角形A%s匹配三角形B%s%”(匹配A,匹配B)
匹配A_pts=[]
匹配_B_pts=[]
对于范围(3)中的i:
match_A_pts.append(set_A[match_A[i]])
match_B_pts.append(set_B[match_B[i]])
打印“三角形A有点%s”%match\u A\u pts
打印“三角形B有点%s”%match\u B\u pts
'''
获胜者[2204,
dist = sqrt( (x2 - x1)**2 + (y2 - y1)**2 )
list(numpy.array(list1)-numpy.array(list2))
'''
known correct solution

A = [[1894.41, 1957.065],[1967.31, 1960.865],[2015.81, 1981.665]]
B = [[1051.3, 1837.3],[1580.77, 1868.33],[1929.49, 2017.52]]

'''
import numpy as np
import itertools
import math
import operator

set_A = [[2015.81, 1981.665], [1967.31, 1960.865], [1962.91, 1951.365],
        [1964.91, 1994.565], [1894.41, 1957.065]]
set_B = [[2689.28, 3507.04, 2895.67, 1051.3, 1929.49, 1035.97, 752.44, 130.62,
        620.06, 2769.06, 1580.77, 281.76, 224.54, 3848.3],
        [2061.19, 3700.27, 2131.2, 1837.3, 2017.52, 80.96, 3524.61, 3821.22,
        3711.53, 1812.12, 1868.33, 3865.77, 3273.77, 2100.71]]

# normalize set B data to set A format
set_Bx, set_By = (set_B)
set_B = []
for i in range(len(set_Bx)):
    set_B.append([set_Bx[i],set_By[i]])

'''
set_B = [[2689.28, 2061.19], [3507.04, 3700.27], [2895.67, 2131.2], 
[1051.3, 1837.3], [1929.49, 2017.52], [1035.97, 80.96], [752.44, 3524.61], 
[130.62, 3821.22], [620.06, 3711.53], [2769.06, 1812.12], [1580.77, 1868.33], 
[281.76, 3865.77], [224.54, 3273.77], [3848.3, 2100.71]]
'''

print set_A
print set_B
print len(set_A)
print len(set_B)

set_A_tri = list(itertools.combinations(range(len(set_A)), 3))
set_B_tri = list(itertools.combinations(range(len(set_B)), 3))

print set_A_tri
print set_B_tri
print len(set_A_tri)
print len(set_B_tri)

'''
set_A = [[2015.81, 1981.665], [1967.31, 1960.865], [1962.91, 1951.365], 
[1964.91, 1994.565], [1894.41, 1957.065]]

set_A_tri = [(0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 3), (0, 2, 4), (0, 3, 4), 
(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
'''

def distance(x1,y1,x2,y2):
    return math.sqrt((x2 - x1)**2 + (y2 - y1)**2 )

def tri_sides(set_x, set_x_tri):

    triangles = []
    for i in range(len(set_x_tri)):

        point1 = set_x_tri[i][0]
        point2 = set_x_tri[i][1]
        point3 = set_x_tri[i][2]

        point1x, point1y = set_x[point1][0], set_x[point1][1]
        point2x, point2y = set_x[point2][0], set_x[point2][1]
        point3x, point3y = set_x[point3][0], set_x[point3][1] 

        len1 = distance(point1x,point1y,point2x,point2y)
        len2 = distance(point1x,point1y,point3x,point3y)
        len3 = distance(point2x,point2y,point3x,point3y)

        min_side = min(len1,len2,len3)
        len1/=min_side
        len2/=min_side
        len3/=min_side
        t=[len1,len2,len3]
        t.sort()
        triangles.append(t)

    return triangles

A_triangles = tri_sides(set_A, set_A_tri)
B_triangles = tri_sides(set_B, set_B_tri)

print A_triangles
'''
[[1.0, 5.0405616860744304, 5.822935502560814], 
[1.0, 1.5542012854321234, 1.5619803879976761], 
[1.0, 1.3832883678507584, 2.347214708755337], 
[1.0, 1.2141910838179129, 1.4096730529373076], 
[1.0, 1.1275138587537166, 2.0318412465223665], 
[1.0, 1.5207417600732074, 2.3589630093994876], 
[1.0, 3.2270326342163584, 4.13069930678442], 
[1.0, 6.565440477766354, 6.972550347780966], 
[1.0, 2.1606693015281997, 2.3635387983160885], 
[1.0, 1.589425903498476, 1.846471085870448]]
'''
print B_triangles

def list_subtract(list1,list2):

    return np.absolute(np.array(list1)-np.array(list2))

sums = []
threshold = 1
for i in range(len(A_triangles)):
    for j in range(len(B_triangles)):
        k = sum(list_subtract(A_triangles[i], B_triangles[j]))
        if k < threshold:
            sums.append([i,j,k])
# sort by smallest sum
sums = sorted(sums, key=operator.itemgetter(2))

print sums
print 'winner %s' % sums[0]
print sums[0][0]
print sums[0][1]
match_A = set_A_tri[sums[0][0]]
match_B = set_B_tri[sums[0][1]]
print 'triangle A %s matches triangle B %s' % (match_A, match_B)

match_A_pts = []
match_B_pts = []
for i in range(3):
    match_A_pts.append(set_A[match_A[i]])
    match_B_pts.append(set_B[match_B[i]])

print 'triangle A has points %s' % match_A_pts
print 'triangle B has points %s' % match_B_pts

'''
winner [2, 204, 0.031415474959738399]
2
204
triangle A (0, 1, 4) matches triangle B (3, 4, 10)
triangle A has points [[2015.81, 1981.665], [1967.31, 1960.865], [1894.41, 1957.065]]
triangle B has points [[1051.3, 1837.3], [1929.49, 2017.52], [1580.77, 1868.33]]
'''