我有以下问题。成像您有一组以某种规律组织的坐标,如下图所示。
我想做的是自动提取坐标,以便它们从左到右,从上到下排序。另外,坐标的总数应尽可能大,但仅包括坐标,以使提取的坐标位于近似矩形的网格上(即使坐标具有不同的对称性,例如六边形)。我一直想提取遵循矩形晶胞结构的坐标。
对于上面显示的示例,包含此类正交排列集的最大数字将是8 x 8坐标(以下称此尺寸:m x n),如红色矩形所示。
问题在于给定坐标嘈杂且失真。 我的方法是生成一个人造晶格,并考虑到晶格的某些旋转,移动和简单变形,将给定坐标的差异最小化。然而,事实证明,定义一个涵盖问题复杂性的成本函数是棘手的,即最小化给定坐标和拟合晶格之间的差异,同时最大化网格分量m x n。
如果有人有一个聪明的主意如何解决这个问题,也许还有机器学习算法,我将非常感激。
这是我到目前为止使用的代码: 生成具有m x n坐标的人造晶格的函数,这些坐标在“ n”和“ m”方向上被a和b隔开。角度θ允许晶格旋转。
def lattice(m, n, a, b, theta):
coords = []
for j in range(m):
for i in range(n):
coords.append([np.sin(theta)*a*i + np.cos(theta)*b*j, np.cos(theta)*a*i - np.sin(theta)*b*j])
return np.array(coords)
我使用以下函数来测量点之间的平均最小距离,这是拟合的良好起点:
def mean_min_distance(coords):
from scipy.spatial import distance
cd = distance.cdist(coords, coords)
cd_1 = np.where(cd == 0, np.nan, cd)
return np.mean(np.nanmin(cd_1, axis=1))
以下函数提供了理论上适合坐标长度的m x n的所有可能组合,假定其排列方式未知。已经包含将其限制为最小值和最大值的功能:
def get_all_mxn(l, min_m=2, min_n=2, max_m=None, max_n=None):
poss = []
if max_m is None:
max_m = l + 1
if max_n is None:
max_n = l +1
for i in range(min_m, max_m):
for j in range(min_n, max_n):
if i * j <= l:
poss.append([i, j])
return np.array(poss)
我使用的成本函数的定义(对于一组特定的m x n)。因此,我首先想对某种m x n的布置非常合适。
def cost(x0):
a, b, theta, shift_a, shift_b, dd1 = x0
# generate lattice
l = lattice(m, n, a, b, theta)
# distort lattice by affine transformation
distortion_matr = np.array([[1, dd1], [0, 1]])
l = np.dot(distortion_matr, l.T).T
# shift lattice
l = l + np.array((shift_b, shift_a))
# Some padding to make the lists the same length
len_diff = coords.shape[0] - l.shape[0]
l = np.append(l, (1e3, 1e3)*len_diff).reshape((l.shape[0] + len_diff, 2))
# calculate all distances between all points
cd = distance.cdist(coords, l)
minimum distance between each artificial lattice point and all coords
cd_min = np.min(cd[:, :coords.shape[0] - len_diff], axis=0)
# returns root mean square difference of all minimal distances
return np.sqrt(np.sum(np.abs(cd_min) ** 2) )
然后运行最小化:
md = mean_min_distance(coords)
# initial guess
x0 = np.array((md, md, np.deg2rad(-3.), 3, 1, 0.12))
res = minimize(cost, x0)
但是,结果非常依赖于初始参数x0,我什至没有包含m和n的拟合。