2014-12-24 3 views
4

부드럽게 처리해야하는 모호한 직사각형의 숫자가 여러 개 있습니다. 단순화 된 예 :2 차원 그림 매끄럽게하기

fig, ax1 = plt.subplots(1,1, figsize=(3,3)) 
xs1 = [-0.25, -0.625, -0.125, -1.25, -1.125, -1.25, 0.875, 1.0, 1.0, 0.5, 1.0, 0.625, -0.25] 
ys1 = [1.25, 1.375, 1.5, 1.625, 1.75, 1.875, 1.875, 1.75, 1.625, 1.5, 1.375, 1.25, 1.25] 

ax1.plot(xs1, ys1) 
ax1.set_ylim(0.5,2.5) 
ax1.set_xlim(-2,2) ; 

enter image description hereenter image description here

나는 scipy.interpolate.RectBivariateSpline을 시도하지만 분명히 모든 지점에서 데이터 (예 : 히트 맵), 및 scipy.interpolate.interp1d하지만 원하는 충분히 합리적으로 1 차원 평활화 된 버전을 생성하려고합니다.

이것을 부드럽게하는 적절한 방법은 무엇입니까?

을 편집하여 나의 목표를 조금 더 자세히 설명하십시오. 나는 모든 점들을 통과하는 선들을 필요로하지 않는다. 사실 나는 모든 포인트를 거치지 않는 편이 좋을 것입니다. 왜냐하면 이웃이나 다른 유사한 접근 방식으로 평균화되어야하는 명확한 아웃 라이어 포인트가 있기 때문입니다. 나는 위에서 염두에 두었던 시작의 원유 매뉴얼 스케치를 포함시켰다.

답변

9

Chaikin의 코너 절단 알고리즘이 이상적인 방법 일 수 있습니다. 꼭짓점이 P0, P1, ... P (N-1) 인 주어진 다각형의 경우, 코너 절단 알고리즘은 P (i)와 P (i + 1)로 정의 된 각 선분에 대해 두 개의 새 꼭지점을 생성합니다.

(i) = (1/4) P (i) + (3/4) P (i) = (3/4) P (i + 1)

P (i + 1)

따라서 새 폴리곤의 정점은 2N입니다. 그런 다음 원하는 다각형에 도달 할 때까지 새로운 다각형을 다시 반복하여 적용 할 수 있습니다. 결과는 많은 정점이있는 다각형이되지만 표시 될 때 부드럽게 보입니다. 이 코너 절단 방법으로 생성 된 결과 곡선이 2 차 B- 스플라인 곡선으로 수렴된다는 것이 증명 될 수 있습니다. 이 방법의 장점은 결과 곡선이 절대 오버 슈트되지 않는다는 것입니다. 다음 그림은 당신에게 코너 절단 한 번 더 적용하면
Apply corner cutting once

절단

원래 다각형
Original Polygon

코너 적용을 (사진 this link에서 촬영)이 알고리즘에 대한 더 나은 아이디어를 줄 것이다
enter image description here

보기Chaikin의 코너 절단 알고리즘에 대한 자세한 내용은을 참조하십시오.

+0

다음은이 알고리즘에 대한 Python 2.7.X 구현입니다. https://stackoverflow.com/questions/47068504/ find-python-chaikins-corner-cutting-algorithm의 어디에서 찾을 것인가? –

3

이 질문에 대한 대답이 많지만,이 다각형을 베 지어 곡선으로 정의 할 수는 있습니다. 코드는 간단하며이 곡선이 어떻게 작동하는지 잘 알고있을 것입니다. 이 경우이 곡선은 제어 다각형이됩니다. 하지만 완벽하지는 않습니다. 첫째로,이 폴리곤의 "매끄러운 버전"이 아니라 커브와 다른 것입니다. 커브의 정도가 높을수록 제어 다각형처럼 보이지 않습니다. 제가 말하고자하는 것은 어쩌면 프로그래밍 문제로 다각형을 부드럽게하는 대신 매끄럽게하려는 대신 수학 도구로이 문제를 해결해야한다는 것입니다.

6

실제로이 경우 scipy.interpolate.inter1d을 사용할 수 있습니다. 다각형의 x 및 y 구성 요소를 별도의 시리즈로 처리해야합니다. 사각형과 빠른 예를 들어

: 당신이 볼 수

import numpy as np 
import matplotlib.pyplot as plt 
from scipy.interpolate import interp1d 

x = [0, 1, 1, 0, 0] 
y = [0, 0, 1, 1, 0] 

t = np.arange(len(x)) 
ti = np.linspace(0, t.max(), 10 * t.size) 

xi = interp1d(t, x, kind='cubic')(ti) 
yi = interp1d(t, y, kind='cubic')(ti) 

fig, ax = plt.subplots() 
ax.plot(xi, yi) 
ax.plot(x, y) 
ax.margins(0.05) 
plt.show() 

enter image description here

그러나, 이것은 0,0에서 몇 가지 문제가 발생합니다.

스플라인 세그먼트가 두 개 이상의 점에 의존하기 때문에 이러한 현상이 발생합니다. 첫 번째와 마지막 점은 보간 된 방식으로 "연결"되지 않습니다. 끝점의 스플라인에 대한 "랩 어라운드 (wrap-around)"경계 조건이 있도록 x 및 y 시퀀스를 두 번째 및 마지막 점과 두 번째 점으로 "패딩"하여이 문제를 해결할 수 있습니다.

import numpy as np 
import matplotlib.pyplot as plt 
from scipy.interpolate import interp1d 

x = [0, 1, 1, 0, 0] 
y = [0, 0, 1, 1, 0] 

# Pad the x and y series so it "wraps around". 
# Note that if x and y are numpy arrays, you'll need to 
# use np.r_ or np.concatenate instead of addition! 
orig_len = len(x) 
x = x[-3:-1] + x + x[1:3] 
y = y[-3:-1] + y + y[1:3] 

t = np.arange(len(x)) 
ti = np.linspace(2, orig_len + 1, 10 * orig_len) 

xi = interp1d(t, x, kind='cubic')(ti) 
yi = interp1d(t, y, kind='cubic')(ti) 

fig, ax = plt.subplots() 
ax.plot(xi, yi) 
ax.plot(x, y) 
ax.margins(0.05) 
plt.show() 
enter image description here

그리고 그냥 데이터와 모양을 보여주기 :

import numpy as np 
import matplotlib.pyplot as plt 
from scipy.interpolate import interp1d 

x = [-0.25, -0.625, -0.125, -1.25, -1.125, -1.25, 
    0.875, 1.0, 1.0, 0.5, 1.0, 0.625, -0.25] 
y = [1.25, 1.375, 1.5, 1.625, 1.75, 1.875, 1.875, 
    1.75, 1.625, 1.5, 1.375, 1.25, 1.25] 

# Pad the x and y series so it "wraps around". 
# Note that if x and y are numpy arrays, you'll need to 
# use np.r_ or np.concatenate instead of addition! 
orig_len = len(x) 
x = x[-3:-1] + x + x[1:3] 
y = y[-3:-1] + y + y[1:3] 

t = np.arange(len(x)) 
ti = np.linspace(2, orig_len + 1, 10 * orig_len) 

xi = interp1d(t, x, kind='cubic')(ti) 
yi = interp1d(t, y, kind='cubic')(ti) 

fig, ax = plt.subplots() 
ax.plot(xi, yi) 
ax.plot(x, y) 
ax.margins(0.05) 
plt.show() 

enter image description here

참고이 방법으로 "오버 슈트"꽤 얻을 . 이는 3 차 스플라인 보간 때문입니다. @ pythonstarter의 제안은 그것을 처리하는 또 다른 좋은 방법이지만, 베 지어 곡선은 동일한 문제 (기본적으로는 수학적으로 동일합니다. 제어점이 정의되는 방식의 문제 일뿐입니다)로 인해 어려움을 겪을 것입니다. 폴리곤을 다듬는 데 특화된 방법 (예 : 다항식 근사 식 지수 커널 (PAEK))을 비롯하여 다듬기를 처리 할 수있는 여러 가지 방법이 있습니다. 필자는 PAEK를 구현하려 한 적이 없으므로 어떻게 참여했는지 확신 할 수 없습니다. 보다 견고하게 수행해야하는 경우 PAEK 또는 다른 유사한 방법을 조사해보십시오.

+0

이 기능은 원래 설명대로 작동합니다. 내가 실제로 찾고자했던 것이 약간 다르다는 것을 알게되었고, Chaikin의 코너 절단 알고리즘에 대한 @ fang의 제안은 내가 원했던 것과 더 가깝다. – iayork

+0

이것은 베지에 곡선 문제를 해결했습니다! 주기적인 경계 조건을 사용하지 않고 작동하는 방법을 알아 내려고 노력했습니다. –

관련 문제