Algorithm 网格点拟合算法
我有一个2D空间中形成(不完美)网格的点列表: 将这些点拟合到刚性网格的最佳方法是什么(即创建一个二维数组并计算出每个点在该数组中的位置) 网格上没有洞,但我事先不知道它的尺寸是多少Algorithm 网格点拟合算法,algorithm,Algorithm,我有一个2D空间中形成(不完美)网格的点列表: 将这些点拟合到刚性网格的最佳方法是什么(即创建一个二维数组并计算出每个点在该数组中的位置) 网格上没有洞,但我事先不知道它的尺寸是多少 编辑:网格不一定是规则的(甚至不是行/列之间的间距)我能想到的最好的解决方案是一个蛮力解决方案,它计算网格尺寸,使点与其最近的网格交点之间的欧几里德距离的平方误差最小化 这假设点的数量p正好等于列的数量乘以行的数量,并且每个网格交点上正好有一个点。它还假设任意点的最小x/y值为零。如果最小值大于零,只需从每个点的x
编辑:网格不一定是规则的(甚至不是行/列之间的间距)我能想到的最好的解决方案是一个蛮力解决方案,它计算网格尺寸,使点与其最近的网格交点之间的欧几里德距离的平方误差最小化 这假设点的数量p正好等于列的数量乘以行的数量,并且每个网格交点上正好有一个点。它还假设任意点的最小x/y值为零。如果最小值大于零,只需从每个点的x坐标减去最小x值,从每个点的y坐标减去最小y值 其思想是在给定点数的情况下创建所有可能的栅格尺寸。在上面的16点示例中,我们将制作尺寸为1x16、2x8、4x4、8x2和16x1的网格。对于每个网格,我们通过将点的最大宽度除以列数减1,将点的最大高度除以行数减1来计算网格交点的位置。然后,我们将每个点拟合到其最近的网格交点,并找到该点和交点之间的误差(距离的平方)。(请注意,仅当每个点比任何其他交点更接近其预期栅格交点时,此选项才有效。) 将每个网格配置的错误分别相加后(例如,获得1x16配置的一个错误值,2x8配置的另一个错误值等等),我们选择错误最低的配置 初始化:
P is the set of points such that P[i][0] is the x-coordinate and
P[i][1] is the y-coordinate
Let p = |P| or the number of points in P
Let max_x = the maximum x-coordinate in P
Let max_y = the maximum y-coordinate in P
(minimum values are assumed to be zero)
Initialize min_error_dist = +infinity
Initialize min_error_cols = -1
算法:
for (col_count = 1; col_count <= n; col_count++) {
// only compute for integer # of rows and cols
if ((p % col_count) == 0) {
row_count = n/col_count;
// Compute the width of the columns and height of the rows
// If the number of columns is 1, let the column width be max_x
// (and similarly for rows)
if (col_count > 1) col_width = max_x/(col_count-1);
else col_width=max_x;
if (row_count > 1) row_height = max_y/(row_count-1);
else row_height=max_y;
// reset the error for the new configuration
error_dist = 0.0;
for (i = 0; i < n; i++) {
// For the current point, normalize the x- and y-coordinates
// so that it's in the range 0..(col_count-1)
// and 0..(row_count-1)
normalized_x = P[i][0]/col_width;
normalized_y = P[i][1]/row_height;
// Error is the sum of the squares of the distances between
// the current point and the nearest grid point
// (in both the x and y direction)
error_dist += (normalized_x - round(normalized_x))^2 +
(normalized_y - round(normalized_y))^2;
}
if (error_dist < min_error_dist) {
min_error_dist = error_dist;
min_error_cols = col_count;
}
}
}
return min_error_cols;
for(col_count=1;col_count 1)col_width=max_x/(col_count-1);
else col_width=最大值x;
如果(行计数>1)行高度=最大y/(行计数-1);
else行高度=最大值;
//重置新配置的错误
误差_dist=0.0;
对于(i=0;i
得到列数(从而得到行数)后,可以重新计算每个点的标准化值,并对其进行四舍五入,以获得它们所属的网格交点。最后,我使用了这个算法,灵感来自比克的:
- 按x值对点进行排序
- 将点分组为列:前r个点构成第一列,其中r是行数
- 在每列中,按y值对点进行排序,以确定它们所在的行
- 对于每行/每列,计算y值/x值的范围
- 对齐中的差异是找到的最大范围
一点图像处理方法: 如果你认为你有一个二进制图像,其中X是1,其余的是0,你可以将行和列相加,并使用峰值查找算法来识别对应于网格X和y线的峰值: 您的点作为二进制图像: 行/列之和 现在对信号应用一些平滑技术(例如lowess): 我相信你会明白的:-)
祝你好运我写了这个算法,它可以解释丢失的坐标以及有错误的坐标 Python代码 代码输出
我也在寻找另一个使用线性代数的解决方案。查看我的问题。为什么不舍入每个坐标?您需要每个行/列的大小,或者只需要行/列计数?看起来像是某种傅里叶变换的工作。@n.m.您的意思是如果您事先不知道虚拟网格是什么?如果是的话…@dystroy-我不能对坐标进行舍入,因为同一行/列中的点可能不止一个单位。谢谢!这几乎就是我想要的,只是我忘了指定网格不一定是规则的(参见其他答案)谢谢!最后,我针对一个稍微不同的问题采用了这种方法,我不能假设没有空白(但不能太稀疏):分别考虑
x
和y
坐标,我尝试增加插槽的数量(即col或rows),当发现超过百分之几的插槽为空时停止,然后返回具有最小平方误差和的解决方案。
for (col_count = 1; col_count <= n; col_count++) {
// only compute for integer # of rows and cols
if ((p % col_count) == 0) {
row_count = n/col_count;
// Compute the width of the columns and height of the rows
// If the number of columns is 1, let the column width be max_x
// (and similarly for rows)
if (col_count > 1) col_width = max_x/(col_count-1);
else col_width=max_x;
if (row_count > 1) row_height = max_y/(row_count-1);
else row_height=max_y;
// reset the error for the new configuration
error_dist = 0.0;
for (i = 0; i < n; i++) {
// For the current point, normalize the x- and y-coordinates
// so that it's in the range 0..(col_count-1)
// and 0..(row_count-1)
normalized_x = P[i][0]/col_width;
normalized_y = P[i][1]/row_height;
// Error is the sum of the squares of the distances between
// the current point and the nearest grid point
// (in both the x and y direction)
error_dist += (normalized_x - round(normalized_x))^2 +
(normalized_y - round(normalized_y))^2;
}
if (error_dist < min_error_dist) {
min_error_dist = error_dist;
min_error_cols = col_count;
}
}
}
return min_error_cols;
# Input [x, y] coordinates of a 'sparse' grid with errors
xys = [[103,101],
[198,103],
[300, 99],
[ 97,205],
[304,202],
[102,295],
[200,303],
[104,405],
[205,394],
[298,401]]
def row_col_avgs(num_list, ratio):
# Finds the average of each row and column. Coordinates are
# assigned to a row and column by specifying an error ratio.
last_num = 0
sum_nums = 0
count_nums = 0
avgs = []
num_list.sort()
for num in num_list:
if num > (1 + ratio) * last_num and count_nums != 0:
avgs.append(int(round(sum_nums/count_nums,0)))
sum_nums = num
count_nums = 1
else:
sum_nums = sum_nums + num
count_nums = count_nums + 1
last_num = num
avgs.append(int(round(sum_nums/count_nums,0)))
return avgs
# Split coordinates into two lists of x's and y's
xs, ys = map(list, zip(*xys))
# Find averages of each row and column within a specified error.
x_avgs = row_col_avgs(xs, 0.1)
y_avgs = row_col_avgs(ys, 0.1)
# Return Completed Averaged Grid
avg_grid = []
for y_avg in y_avgs:
avg_row = []
for x_avg in x_avgs:
avg_row.append([int(x_avg), int(y_avg)])
avg_grid.append(avg_row)
print(avg_grid)
[[[102, 101], [201, 101], [301, 101]],
[[102, 204], [201, 204], [301, 204]],
[[102, 299], [201, 299], [301, 299]],
[[102, 400], [201, 400], [301, 400]]]