【发布时间】:2017-06-20 07:40:42
【问题描述】:
我已经插入了一条样条曲线,以将图像中的像素数据与我想要拉直的曲线相匹配。我不确定什么工具适合解决这个问题。有人可以推荐一种方法吗?
这是我得到样条的方式:
import numpy as np
from skimage import io
from scipy import interpolate
import matplotlib.pyplot as plt
from sklearn.neighbors import NearestNeighbors
import networkx as nx
# Read a skeletonized image, return an array of points on the skeleton, and divide them into x and y coordinates
skeleton = io.imread('skeleton.png')
curvepoints = np.where(skeleton==False)
xpoints = curvepoints[1]
ypoints = -curvepoints[0]
# reformats x and y coordinates into a 2-dimensional array
inputarray = np.c_[xpoints, ypoints]
# runs a nearest neighbors algorithm on the coordinate array
clf = NearestNeighbors(2).fit(inputarray)
G = clf.kneighbors_graph()
T = nx.from_scipy_sparse_matrix(G)
# sorts coordinates according to their nearest neighbors order
order = list(nx.dfs_preorder_nodes(T, 0))
xx = xpoints[order]
yy = ypoints[order]
# Loops over all points in the coordinate array as origin, determining which results in the shortest path
paths = [list(nx.dfs_preorder_nodes(T, i)) for i in range(len(inputarray))]
mindist = np.inf
minidx = 0
for i in range(len(inputarray)):
p = paths[i] # order of nodes
ordered = inputarray[p] # ordered nodes
# find cost of that order by the sum of euclidean distances between points (i) and (i+1)
cost = (((ordered[:-1] - ordered[1:])**2).sum(1)).sum()
if cost < mindist:
mindist = cost
minidx = i
opt_order = paths[minidx]
xxx = xpoints[opt_order]
yyy = ypoints[opt_order]
# fits a spline to the ordered coordinates
tckp, u = interpolate.splprep([xxx, yyy], s=3, k=2, nest=-1)
xpointsnew, ypointsnew = interpolate.splev(np.linspace(0,1,270), tckp)
# prints spline variables
print(tckp)
# plots the spline
plt.plot(xpointsnew, ypointsnew, 'r-')
plt.show()
我更广泛的项目是遵循A novel method for straightening curved text-lines in stylistic documents 中概述的方法。那篇文章在找到描述弯曲文本的行方面相当详细,但在涉及拉直曲线的地方却少得多。我无法想象在摘要中看到的对拉直的唯一参考:
求曲线上某点的法线与垂直线的夹角,最后访问文本上的每个点,并旋转对应的角度。
我还找到了Geometric warp of image in python,这似乎很有希望。如果我可以纠正样条曲线,我认为这将允许我为仿射变换设置一系列目标点以映射到。不幸的是,我还没有找到一种方法来纠正我的样条曲线并对其进行测试。
最后,this 程序实现了一个算法来拉直样条曲线,但是关于算法的论文是在付费墙后面,我无法理解 javascript。
基本上,我迷路了,需要指点。
更新
仿射变换是我知道如何开始探索的唯一方法,所以自从我发布以来我一直在努力。我根据我的 b 样条曲线上的点之间的欧几里德距离对曲线进行了近似校正,从而生成了一组目标坐标。
从最后一个代码块停止的地方开始:
# calculate euclidian distances between adjacent points on the curve
newcoordinates = np.c_[xpointsnew, ypointsnew]
l = len(newcoordinates) - 1
pointsteps = []
for index, obj in enumerate(newcoordinates):
if index < l:
ord1 = np.c_[newcoordinates[index][0], newcoordinates[index][1]]
ord2 = np.c_[newcoordinates[index + 1][0], newcoordinates[index + 1][1]]
length = spatial.distance.cdist(ord1, ord2)
pointsteps.append(length)
# calculate euclidian distance between first point and each consecutive point
xpositions = np.asarray(pointsteps).cumsum()
# compose target coordinates for the line after the transform
targetcoordinates = [(0,0),]
for element in xpositions:
targetcoordinates.append((element, 0))
# perform affine transformation with newcoordinates as control points and targetcoordinates as target coordinates
tform = PiecewiseAffineTransform()
tform.estimate(newcoordinates, targetcoordinates)
我目前因仿射变换 (scipy.spatial.qhull.QhullError: QH6154 Qhull precision error: Initial simplex is flat (facet 1 is coplanar with the interior point)
) 的错误而挂断,但我不确定这是因为我输入数据的方式有问题,还是因为我滥用了变换来做我的投影。
【问题讨论】:
-
您是在寻找将样条线投影到给定直线上的变换,还是试图从给定变换中确定直线?希望这是有道理的。
-
如果我正确理解你的问题,我想找到将我的样条投影到直线上的转换。
-
你有那条线的方程式吗?
-
我想是的。任何一条线都和另一条线一样好,只要它是直的。比如说,f(x)=0。
-
如果您想将样条线投影到 x 轴上,那么您需要做的就是获取所有 x 坐标并将它们与 y=0 配对。这会给你在 x 轴上的“a”投影。我不确定这是否是你所追求的。
标签: python numpy image-processing scikit-image