问题
我有一个要形成网格的坐标列表。每个坐标都有一个随机误差分量,并且缺少一些坐标。Grid could be rotated (update).
我想用一个正交网格来拟合数据点,并返回网格顶点的列表。例如:
应用程序
其目的是在扫描图像中找到一个网格。数据点来自OpenCV中轮廓或边缘检测的结果。一个例子是带有照片网格的图像。
目标
我写了一些Python代码,但我想找到一个使用SciPy、statmodels或其他模块的线性代数算法,它会更健壮,并处理网格的小旋转(小于10°)。
仅使用列表的Python代码
# Noisy [x, y] coordinates (origin is upper-left corner)
pts = [[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, sum_nums, count_nums, avgs = 0, 0, 0, []
num_list.sort()
for num in num_list:
# Calculate average for last row or column and begin new row or column
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
# Or continue with current row or column
else:
sum_nums += num
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(*pts))
# Find averages of each row and column of the grid
x_avgs = row_col_avgs(xs, 0.1)
y_avgs = row_col_avgs(ys, 0.1)
# Return vertices of 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]]]
3条答案
按热度按时间wqsoz72f1#
下面是代码的一个简单实现。由于AvgGrid的大小是已知的,我预先分配了所需的内存(而不是追加)。这应该有速度优势,特别是当输出顶点的数量很大的时候。
eeq64g8w2#
如果将所有点投影到垂直轴或水平轴上,问题就变成了一个等间距聚类的问题。
要执行这些聚类,可以考虑连续(排序)点之间的距离。它们将形成两个聚类:短距离对应于噪声,而长距离对应于网格大小。您可以使用大津方法解决双向聚类问题。
eqfvzcg83#
平行斜率普通最小二乘(OLS)模型:
y = mx + grp + B,其中m=斜率,b= y轴截距,& grp=分类变量。
这是一种可以处理旋转栅格的替代算法。
OLS模型包括原始方向上的数据点和相同数据点的90°旋转。这是必要的,以便所有网格线平行并具有相同的斜率。
1.通过在第一行或最后一行中选择斜率最接近零的两个相邻点,找到一条参考网格线,与其余点进行比较。
1.计算此参考线与其余点之间的距离。
1.根据计算出的距离将点分段成组(每条网格线一组)。
1.对旋转90度的网格重复步骤1到3,并合并结果。
1.建立平行坡度OLS模型以确定格缐的缐性方程式。
1.将旋转后的网格线旋转回其原始方向。
1.计算交点。
示例:
用于创建示例的Python代码
适合网格线的Python代码