2017-02-03 3 views
2

Ich habe einen Spline interpoliert, um Pixeldaten aus einem Bild mit einer Kurve anzupassen, die ich gerade begradigen möchte. Ich bin mir nicht sicher, welche Tools zur Lösung dieses Problems geeignet sind. Kann jemand einen Ansatz empfehlen?Begradigen B-Spline

Hier ist, wie ich meine Spline bekommen:

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() 

Mein breiter angelegtes Projekt ist das Konzept in A novel method for straightening curved text-lines in stylistic documents skizziert zu folgen. Dieser Artikel ist ziemlich detailliert darin, die Linie zu finden, die gekrümmten Text beschreibt, aber viel weniger, wenn es darum geht, die Kurve zu glätten. Ich habe Mühe, die einzige Referenz zu visualisieren zu Begradigung, dass ich sehe, in der Zusammenfassung ist:

den Winkel zwischen der Normalen an einem Punkt auf der Kurve finden und die vertikalen Linie und schließlich jeden Punkt auf dem Text besuchen und drehen durch ihre entsprechenden Winkel.

Ich fand auch Geometric warp of image in python, die vielversprechend scheint. Wenn ich den Spline korrigieren könnte, würde ich damit eine Reihe von Zielpunkten für die affine Transformation festlegen. Leider habe ich keinen Ansatz gefunden, um meinen Spline zu korrigieren und zu testen.

Schließlich this Programm implementiert einen Algorithmus, um Splines zu begradigen, aber das Papier auf dem Algorithmus ist hinter einer Pay-Wand und ich kann den Javascript nicht verstehen.

Grundsätzlich bin ich verloren und brauche Zeiger.

aktualisieren

Die affine Transformation war der einzige Ansatz, den ich eine Idee hatte, wie die Erkundung zu beginnen, also habe ich auf, dass gearbeitet, seit ich geschrieben. Ich habe eine Reihe von Zielkoordinaten erstellt, indem ich eine ungefähre Entzerrung der Kurve basierend auf dem euklidischen Abstand zwischen Punkten auf meinem B-Spline durchgeführt habe.

Von dort, wo der letzten Codeblock aus links:

# 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) 

ich derzeit bin auf Fehler bei den affinen Transformation aufgehängt (scipy.spatial.qhull.QhullError: QH6154 Qhull precision error: Initial simplex is flat (facet 1 is coplanar with the interior point) ), aber ich bin mir nicht sicher, ob es wegen eines Problems ist, mit wie Ich füttere die Daten oder weil ich die Transformation missbrauche, um meine Projektion zu machen.

+1

Suchen Sie nach einer Transformation, die Ihren Spline auf eine bestimmte gerade Linie projizieren oder versuchen Sie eine gerade Linie aus einer gegebenen Transformation zu bestimmen? Hoffnung, die Sinn macht. – DrBwts

+0

Wenn ich Ihre Frage richtig verstehe, möchte ich die Transformation finden, die meinen Spline auf eine gerade Linie projiziert. – Tric

+0

Und Sie haben die Gleichung dieser Linie? – DrBwts

Antwort

0

Ich habe den gleichen Fehler mit Ihnen bei der Verwendung von scipy.spatial.ConvexHull. Zunächst möchte ich mein Projekt erklären: Was ich tun wollte, ist die Leute aus dem Hintergrund zu segmentieren (Image Matting). In meinem Code lese ich zuerst ein Bild und ein Trimap, dann segmentiere ich gemäß dem Trimap das Originalbild in Vordergrund, Hintergrund und unbekannte Pixel.Hier ist ein Teil des Coed:

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)

Aber ich habe einen Fehler here.So prüfe ich die Array von fg_px und dann fand ich dieses Array n * 4. was bedeutet, dass jeder Skalar, den ich an ConvexHull sende, vier Werte hat. Allerdings sollte die Eingabe von ConvexHUll 3-dimensional sein. Ich Quelle mein Fehler und festgestellt, dass das Eingabefarbbild 32bits (RGB-Kanal und Alpha-Kanal) ist, was bedeutet, dass es einen Alpha-Kanal hat. Nachdem das Bild auf 24 Bit übertragen wurde (was nur RGB-Kanäle bedeutet), funktioniert der Code.

In einem Satz sollte der Eingang von ConvexHull b * 4 sein, also überprüfen Sie Ihre Eingabedaten! Hoffe, das funktioniert für Sie ~