Я интерполировал сплайн, чтобы подогнать данные о пикселях из изображения с кривой, которую я хотел бы выпрямить. Я не уверен, какие инструменты подходят для решения этой проблемы. Может ли кто-нибудь порекомендовать подход?
Вот как я получаю свой сплайн:
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()
Мой более широкий проект состоит в том, чтобы следовать подходу, изложенному в новом методе выпрямления изогнутых строки текста в стилистических документах. Эта статья достаточно подробно описывает поиск линии, описывающей искривленный текст, но гораздо меньше, когда речь идет о выпрямлении кривой. Мне трудно представить, что единственная ссылка на выпрямление, которую я вижу, находится в аннотации:
найдите угол между нормалью в точке на кривой и вертикальной линией и, наконец, посетите каждую точку в тексте и поверните их на соответствующие углы.
Я также нашел геометрическую деформацию изображения в python, что кажется многообещающим. Если бы я мог исправить сплайн, я думаю, это позволило бы мне установить диапазон целевых точек для сопоставления с аффинным преобразованием. К сожалению, я не нашел способа исправить свой сплайн и протестировать его.
Наконец, эта программа реализует алгоритм выпрямления сплайнов, но статья о алгоритм находится за платной стеной, и я не могу понять 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)
), но я не уверен, связано ли это с тем, как я подаю данные, или потому, что я злоупотребляю преобразованием для своей проекции .