Как сгладить обводку, учитывая некоторые координаты (x, y) обводки по порядку? - PullRequest
0 голосов
/ 22 февраля 2019

В настоящее время я работаю над проектом, в котором мне нужно создать изображение сглаженного штриха с учетом некоторых упорядоченных координат штриха.Предположим, у меня есть несколько точек

import numpy as np
X = np.array([1, 3, 6, 8, 5])
Y = np.array([1, 8, 4, 4, 1])
plt.plot(X, Y)

figure-1

Но я хочу создать сглаженную коллекцию точек, которая будет изображать это (это всего лишь рука).нарисованная картинка, я думаю, вы поняли):

hand drawing

Я видел этот вопрос, который работает только для функций (одинх будет выводить только один у).Но мне нужен сплайн для отношения (не функция).Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 22 февраля 2019

Вы можете использовать B-spline (splprep и splev) из scipy.interpolate:

import numpy as np
from scipy.interpolate import splprep, splev
import matplotlib.pyplot as plt

X = np.array([1, 3, 6, 8, 5])
Y = np.array([1, 8, 4, 4, 1])
pts = np.vstack((X, Y))
# Find the B-spline representation of an N-dimensional curve
tck, u = splprep(pts, s=0.0)
u_new = np.linspace(u.min(), u.max(), 1000)
# Evaluate a B-spline
x_new, y_new = splev(u_new, tck)

plt.plot(x_new, y_new, 'b--')
plt.show()

Это даст вам нечто похожее на то, что вы просили:

enter image description here

Вы можете поиграть с параметрами splprep, чтобы изменить результат.Вы можете найти более подробную информацию в этом StackOverflow post .

0 голосов
/ 22 февраля 2019

Вышеприведенные ответы очень элегантны, но вот попытка «хакерского» решения, это гораздо менее гладко

X_new = []
Y_new = []
for i in range(4):
    line1 = [X[i],Y[i]] + np.expand_dims(np.linspace(0,1,10),-1)*np.array([X[i+1] - X[i], Y[i+1] - Y[i]])

    line_normal = [- Y[i+1] + Y[i], X[i+1] - X[i]]
    line_normal = line_normal/np.sqrt(np.dot(line_normal, line_normal))

    line1_noisy = line1 + line_normal * 0.2*(np.random.rand(10,1) - 0.5)
    X_new.append(line1_noisy[:,0])
    Y_new.append(line1_noisy[:,1])
X_new = np.stack(X_new).reshape(-1)
Y_new = np.stack(Y_new).reshape(-1)
plt.plot(X_new, Y_new)

enter image description here

0 голосов
/ 22 февраля 2019

См. алгоритм Чайкина .

Алгоритм Чайкина - это геометрические алгоритмы, которые работают непосредственно с полигоном управления.Схема генерации кривой основана на «разрезании углов», когда алгоритм генерирует новый многоугольник управления, обрезая углы от исходного.
Рисунок ниже иллюстрирует эту идею, когда исходный многоугольник управления был преобразован во второй многоугольник(немного смещено) путем обрезания углов первой последовательности.

enter image description here

Вот пример реализации.

"""
polygoninterpolation.py
Chaikin's Algorith for curves
http://graphics.cs.ucdavis.edu/~joy/GeometricModelingLectures/Unit-7-Notes/Chaikins-Algorithm.pdf
"""
import math
import random
from graphics import *


class MultiLine:

    def __init__(self, points=None, rgb_color=(255, 255, 255), width=1):
        self.lines = []
        if points is None:
            self.points = []
        else:
            self.points = points
            self._build_lines()
        self.rgb_color = rgb_color
        self.width = width

    def add_point(self):
        self.points.append(point)

    def _build_lines(self):
        for idx, point in enumerate(self.points[:-1]):
            self.lines.append(Line(self.points[idx], self.points[idx + 1]))

    def draw(self, win):
        for line in self.lines:
            line.setOutline(color_rgb(*self.rgb_color))
            line.setWidth(self.width)
            line.draw(win)


def get_chaikin(points, factor=4):
    new_points = []   # [points[0]]
    for idx in range(len(points) - 1):
        p1, p2 = points[idx], points[idx+1]
        p_one_qtr, p_three_qtr = get_quarter_points(p1, p2, factor)
        new_points.append(p_one_qtr)
        new_points.append(p_three_qtr)
    return new_points   # + [points[-1]]  # for a closed polygon


def get_quarter_points(p1, p2, factor=4):
    n = factor
    qtr_x = (p2.x - p1.x) / n
    qtr_y = (p2.y - p1.y) / n
    return Point(p1.x + qtr_x, p1.y + qtr_y), \
           Point(p1.x + (n-1) * qtr_x, p1.y + (n-1) * qtr_y)


win = GraphWin("My Window", 500, 500)
win.setBackground(color_rgb(0, 0, 0))


# points0 = [Point(250, 20),
#            Point(20, 400),
#            Point(480, 400)]

# points0 = [Point(20, 400),
#            Point(35, 200),
#            Point(250, 100),
#            Point(400, 150),
#            Point(450, 350),
#            Point(380, 450)]

# points0 = [Point(20, 400),
#            Point(35, 200),
#            Point(250, 100),
#            Point(400, 150),
#            Point(220, 170),
#            Point(310, 190),
#            Point(180, 270),
#            Point(450, 230),
#            Point(440, 440),
#            Point(380, 450)]

points0 = [Point(random.randrange(500), random.randrange(500)) for _ in range(random.randrange(3, 80))]

x_line0 = MultiLine(points0)
# x_line0.draw(win)

points1 = get_chaikin(points0)
x_line1 = MultiLine(points1, rgb_color=(200, 200, 200), width=1)
# x_line1.draw(win)

points2 = get_chaikin(points1)
x_line2 = MultiLine(points2, rgb_color=(200, 200, 200), width=1)
# x_line2.draw(win)

points3 = get_chaikin(points2)
x_line3 = MultiLine(points3, rgb_color=(200, 200, 200), width=1)
# x_line3.draw(win)

points4 = get_chaikin(points3)
x_line4 = MultiLine(points4, rgb_color=(200, 200, 200), width=1)
# x_line4.draw(win)

points5 = get_chaikin(points4)
x_line5 = MultiLine(points5, rgb_color=(200, 200, 200), width=1)
x_line5.draw(win)


# poly0 = Polygon(points0)
# poly0.setOutline(color_rgb(0, 255, 0))
# poly0.setWidth(1)
# poly0.draw(win)
#
# points1 = get_chaikin(points0 + [points0[0]])
# poly1 = Polygon(points1)
# poly1.setOutline(color_rgb(0, 255, 0))
# poly1.setWidth(1)
# poly1.draw(win)
#
# points2 = get_chaikin(points1 + [points1[0]])
# poly2 = Polygon(points2)
# poly2.setOutline(color_rgb(0, 255, 0))
# poly2.setWidth(1)
# poly2.draw(win)
#
# points3 = get_chaikin(points2 + [points2[0]])
# poly3 = Polygon(points3)
# poly3.setOutline(color_rgb(0, 255, 0))
# poly3.setWidth(1)
# poly3.draw(win)
#
# points4 = get_chaikin(points3 + [points3[0]])
# poly4 = Polygon(points4)
# poly4.setOutline(color_rgb(0, 255, 0))
# poly4.setWidth(1)
# poly4.draw(win)
#
# points5 = get_chaikin(points4 + [points4[0]])
# poly5 = Polygon(points5)
# poly5.setOutline(color_rgb(0, 255, 0))
# poly5.setWidth(2)
# poly5.draw(win)


print("done")


print(win.getMouse())
win.close()
...