TensorFlow Graphics : Intermediate Tutorials : B-スプラインと Slerp 補間 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 05/28/2019
* 本ページは、TensorFlow Graphics の github レポジトリの次のページを翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
TensorFlow Graphics : Intermediate Tutorials : B-スプラインと slerp 補間
限定的な数の事前定義されたポイントと関連する値が与えられたとき、補間は新しいデータポイントを事前定義されたポイントの範囲内で予測することを可能にします。
下の例で、左のプロットは青いドットで表わされるサンプルを示します。これらのサンプルが滑らかな関数に由来すると仮定すると、これらのドット間のもっともらしい (= plausible) 値を見つけるために利用可能な多くの選択肢があります。最初の選択肢は中央のプロットで観察できるように、隣り合う点の任意のペアを線で結びつける区分線形関数を構築することです。もう一つの広く使用される選択肢はこれらのサンプルに多項式を fit させることです。右のプロットはサンプルに fit された三次多項式を示します。
このノートブックは B-スプラインと球面線形補間を TensorFlow Graphicsを使用してどのように遂行するかを示します。
セットアップ & Imports
このノートブックに含まれるデモを実行するために必要な総てを import しましょう。
import matplotlib.pyplot as plt import tensorflow as tf from tensorflow_graphics.math.interpolation import bspline from tensorflow_graphics.math.interpolation import slerp tf.enable_eager_execution()
Slerp 補間
Lerp はポイント間を線形に補間することを可能にする広く使用される補間テクニックです。冒頭で記述された区間線形補間は線形補間のピースから効果的に構成されます。しかしデータが円上または球面に在る場合はどうでしょう?その場合、Lerp は補間するための良い方法を提供しませんが、幸い、Slear は提供するでしょう!Slerp は球面線形補間を表しクォータニオンを補間するコンテキストで導入されました、これは回転の形式化です。
次のデモは 2 つのベクトルを定義することを可能にします。それぞれ円の中心か始まり円上で終わります。これらは間を補間することを望むベクトルを定義し、そしてスライダー「パーセント」は各ベクトルが補間されたベクトルに影響を与える程度を制御します。結果のベクトルはまた円上で終わることに注意してください。
#@title Slerp - Vectors will be normalized first { vertical-output: true, run: "auto"} vector_1_x = -0.56 #@param { type: "slider", min: -1.0, max: 1.0, step: 0.01} vector_1_y = -0.39 #@param { type: "slider", min: -1.0, max: 1.0, step: 0.01} vector_2_x = 0.47 #@param { type: "slider", min: -1.0, max: 1.0, step: 0.01} vector_2_y = 0.74 #@param { type: "slider", min: -1.0, max: 1.0, step: 0.01} percent = 0.7 #@param { type: "slider", min: 0.0, max: 1.0, step: 0.01} vector_1 = tf.constant((vector_1_x, vector_1_y), dtype=tf.float32) vector_2 = tf.constant((vector_2_x, vector_2_y), dtype=tf.float32) vector_1 = tf.nn.l2_normalize(vector_1) vector_2 = tf.nn.l2_normalize(vector_2) vector_3 = slerp.interpolate( vector_1, vector_2, percent, method=slerp.InterpolationType.VECTOR) v1 = vector_1.numpy() v2 = vector_2.numpy() v3 = vector_3.numpy() plt.figure(figsize=(10, 10)) circle = plt.Circle((0, 0), 1.0, color='g', fill=False) ax = plt.gca() ax.add_artist(circle) plt.arrow( 0.0, 0.0, v1[0], v1[1], width=0.001, color='k', length_includes_head=True) plt.arrow( 0.0, 0.0, v2[0], v2[1], width=0.001, color='b', length_includes_head=True) plt.arrow( 0.0, 0.0, v3[0], v3[1], width=0.001, color='r', length_includes_head=True) plt.axis((-1.1, 1.1, -1.1, 1.1)) plt.show()
B-スプライン補間
グローバルサポートを持つ他の補間テクニック (e.g. ベジェ曲線、グローバル多項式補間) とは対照的に、B-スプラインはローカルコントロールを持つ区間多項式関数です。コントールは「ノット」と呼ばれるポイントの位置に由来します。
#@title B-Spline Interpolation { vertical-output: true, run: "auto"} num_knots = 5 cyclical = True #@param { type: "boolean" } degree = 3 #@param { type: "slider", min: 1, max: 4, step: 1} knot_1_x = -2.5 #@param { type: "slider", min: -3.0, max: 3.0, step: 0.5} knot_1_y = -1 #@param { type: "slider", min: -3.0, max: 3.0, step: 0.5} knot_2_x = -1.5 #@param { type: "slider", min: -3.0, max: 3.0, step: 0.5} knot_2_y = 2 #@param { type: "slider", min: -3.0, max: 3.0, step: 0.5} knot_3_x = 0 #@param { type: "slider", min: -3.0, max: 3.0, step: 0.5} knot_3_y = -3 #@param { type: "slider", min: -3.0, max: 3.0, step: 0.5} knot_4_x = 1.5 #@param { type: "slider", min: -3.0, max: 3.0, step: 0.5} knot_4_y = 3 #@param { type: "slider", min: -3.0, max: 3.0, step: 0.5} knot_5_x = 3 #@param { type: "slider", min: -3.0, max: 3.0, step: 0.5} knot_5_y = 0 #@param { type: "slider", min: -3.0, max: 3.0, step: 0.5} max_pos = num_knots if cyclical else num_knots - degree knots = tf.constant(((knot_1_x, knot_2_x, knot_3_x, knot_4_x, knot_5_x), (knot_1_y, knot_2_y, knot_3_y, knot_4_y, knot_5_y))) positions = tf.expand_dims( tf.range(start=0.0, limit=max_pos, delta=0.01, dtype=knots.dtype), axis=-1) spline = bspline.interpolate(knots, positions, degree, cyclical) spline = tf.squeeze(spline, axis=1) plt.figure(figsize=(10, 10)) plt.plot(spline[:, 0], spline[:, 1], 'r') plt.plot(knots[0, :], knots[1, :], 'b.') plt.axis((-3.5, 3.5, -3.5, 3.5)) plt.show()
以上