拉直B样条

时间:2017-02-03 02:19:37

标签: python numpy image-processing scikit-image

我插入了一个样条曲线来拟合图像中的像素数据,并使用我想要拉直的曲线。我不确定哪种工具适合解决这个问题。有人可以推荐一种方法吗?

以下是我如何获取样条曲线:

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) )的错误,但我不确定是不是因为我在如何输入数据的问题,或者因为我是滥用变换做我的投射。

1 个答案:

答案 0 :(得分:0)

使用scipy.spatial.ConvexHull时,我遇到了同样的错误。 首先,让我解释一下我的项目:我想要做的是将人们从背景中分割出来(图像消光)。在我的代码中,首先我读取了一个图像和一个trimap,然后根据trimap,我将原始图像分割为前景,bakground和未知像素。这是男女同校的一部分:

img = scipy.misc.imread('sweater_black.png') #color_image

trimap = scipy.misc.imread('sw_trimap.png', flatten='True') #trimap

bg = trimap == 0 #background

fg = trimap == 255 #foreground

unknown = True ^ np.logical_or(fg,bg) #unknown pixels

fg_px = img[fg] #here i got the rgb value of the foreground pixels,then send them to the ConvexHull

fg_hull = scipy.spatial.ConvexHull(fg_px)

但是我在这里得到了一个错误。所以我检查了fg_px的数组然后我发现这个数组是n * 4。这意味着我发送给ConvexHull的每个标量都有四个值。然而,ConvexHUll的输入应该是3维。 我找到了我的错误并发现输入彩色图像是32位(rgb通道和alpha通道),这意味着它有一个alpha通道。将图像传输到24位(这意味着只有rgb通道)后,代码可以工作。

在一句话中,ConvexHull的输入应为b * 4,因此请检查输入数据!希望这对你有用〜