ホーム » TensorFlow » TensorFlow Graphics : Tutorials : マテリアルとのライト相互作用 (リフレクション)

TensorFlow Graphics : Tutorials : マテリアルとのライト相互作用 (リフレクション)

TensorFlow Graphics : Intermediate Tutorials : マテリアルとのライト相互作用 (リフレクション) (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 05/30/2019

* 本ページは、TensorFlow Graphics の github レポジトリの次のページを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

 

TensorFlow Graphics : Intermediate Tutorials : マテリアルとのライト相互作用 (リフレクション)

私達の回りの世界は非常に複雑でガラスから木に渡る多様なマテリアル (素材) から構成されます。各マテリアルはそれ自身の内部プロパティを所持していてライトと異なった相互作用をします。例えば、幾つかは拡散して (e.g. 紙や大理石) ライティング条件が与えられたとき、どのようなアングルからでも同じように見えます。他の素材 (e.g. 金属) は大きく異なる外見を持ち鏡面 (= specularities) のような視点依存効果を示します。

ライトがどのように素材と相互作用するかを正確にモデル化することは、サブサーフェイス・スキャタリング (e.g. スキン) と反射率 (e.g. 水) のような効果を伴う複雑な過程です。このチュートリアルでは最も一般的な効果に注目します、それは反射です。反射率をモデル化する際、双方向反射率分布関数 (BRDF, Bidirectional Reflectance Distribution Functions) が選択するメソッドです。入射光の方向が与えられた時、BRDF はサーフェスが観測されている方向に跳ね返るライトの総量を制御します (下の画像で任意の gray ベクトル)。

Lambertian = ランバート反射 ; specular = 鏡面反射

 
このチュートリアルでは、3 つの球上にライトをあてます、それぞれ上の画像で記述されたマテリアルを持ち、そこでは鏡面マテリアルは Phong の鏡面モデルでモデル化されます。

Note: このチュートリアルは進んだトピックをカバーしておりそれ故に step by step に詳細を提供するよりも、BRDF の高位な理解を形成するために制御可能な toy サンプルを提供することに注力しています。

 

セットアップ & Imports

このノートブックに含まれるデモを実行するために必要な総てを import しましょう。

###########
# Imports #
###########
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import math as m
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

from tensorflow_graphics.rendering.reflectance import lambertian
from tensorflow_graphics.rendering.reflectance import phong
from tensorflow_graphics.rendering.camera import orthographic
from tensorflow_graphics.geometry.representation import grid
from tensorflow_graphics.geometry.representation import ray
from tensorflow_graphics.geometry.representation import vector

tf.enable_eager_execution()

 

球体の制御可能なライティング

###########
# Imports #
###########
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import math as m
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

from tensorflow_graphics.rendering.reflectance import lambertian
from tensorflow_graphics.rendering.reflectance import phong
from tensorflow_graphics.rendering.camera import orthographic
from tensorflow_graphics.geometry.representation import grid
from tensorflow_graphics.geometry.representation import ray
from tensorflow_graphics.geometry.representation import vector

tf.enable_eager_execution()
###############
# UI controls #
###############
#@title Controls { vertical-output: false, run: "auto" }
light_x_position = -0.4  #@param { type: "slider", min: -1, max: 1 , step: 0.05 }
albedo_red = 0.7  #@param { type: "slider", min: 0.0, max: 1.0 , step: 0.1 }
albedo_green = 1  #@param { type: "slider", min: 0.0, max: 1.0 , step: 0.1 }
albedo_blue = 1  #@param { type: "slider", min: 0.0, max: 1.0 , step: 0.1 }
light_red = 1  #@param { type: "slider", min: 0.0, max: 1.0 , step: 0.1 }
light_green = 1  #@param { type: "slider", min: 0.0, max: 1.0 , step: 0.1 }
light_blue = 1  #@param { type: "slider", min: 0.0, max: 1.0 , step: 0.1 }
specular_percentage = 0.25  #@param { type: "slider", min: 0, max: 1 , step: 0.01 }
shininess = 4  #@param { type: "slider", min: 0, max: 10, step: 1 }
diffuse_percentage = 1.0 - specular_percentage
dtype = np.float64
albedo = np.array((albedo_red, albedo_green, albedo_blue), dtype=dtype)

def compute_intersection_normal_sphere(image_width, image_height, sphere_radius,
                                       sphere_center, dtype):
  pixel_grid_start = np.array((0.5, 0.5), dtype=dtype)
  pixel_grid_end = np.array((image_width - 0.5, image_height - 0.5), dtype=dtype)
  pixel_nb = np.array((image_width, image_height))
  pixels = grid.generate(pixel_grid_start, pixel_grid_end, pixel_nb)

  pixel_ray = tf.math.l2_normalize(orthographic.ray(pixels), axis=-1)
  zero_depth = np.zeros([image_width, image_height, 1])
  pixels_3d = orthographic.unproject(pixels, zero_depth)

  intersections_points, normals = ray.intersection_ray_sphere(
      sphere_center, sphere_radius, pixel_ray, pixels_3d)
  intersections_points = np.nan_to_num(intersections_points)
  normals = np.nan_to_num(normals)
  return intersections_points[0, :, :, :], normals[0, :, :, :]

#####################################
# Setup the image, sphere and light #
#####################################
# Image dimensions
image_width = 400
image_height = 300

# Sphere center and radius
sphere_radius = np.array((100.0,), dtype=dtype)
sphere_center = np.array((image_width / 2.0, image_height / 2.0, 300.0),
                         dtype=dtype)

# Set the light along the image plane
light_position = np.array((image_width / 2.0 + light_x_position * image_width,
                           image_height / 2.0, 0.0),
                          dtype=dtype)
vector_light_to_sphere_center = light_position - sphere_center
light_intensity_scale = vector.dot(
    vector_light_to_sphere_center, vector_light_to_sphere_center,
    axis=-1) * 4.0 * m.pi
light_intensity = np.array(
    (light_red, light_green, light_blue)) * light_intensity_scale

################################################################################################
# For each pixel in the image, estimate the corresponding surface point and associated normal. #
################################################################################################
intersection_3d, surface_normal = compute_intersection_normal_sphere(
    image_width, image_height, sphere_radius, sphere_center, dtype)

#######################################
# Reflectance and radiance estimation #
#######################################
incoming_light_direction = tf.math.l2_normalize(
    intersection_3d - light_position, axis=-1)
outgoing_ray = np.array((0.0, 0.0, -1.0), dtype=dtype)
albedo = tf.broadcast_to(albedo, tf.shape(surface_normal))

# Lambertian BRDF
brdf_lambertian = diffuse_percentage * lambertian.brdf(incoming_light_direction, outgoing_ray,
                                  surface_normal, albedo)
# Phong BRDF
brdf_phong = specular_percentage * phong.brdf(incoming_light_direction, outgoing_ray, surface_normal,
                        np.array((shininess,), dtype=dtype), albedo)
# Composite BRDF
brdf_composite = brdf_lambertian + brdf_phong
# Irradiance
cosine_term = vector.dot(surface_normal, -incoming_light_direction)
cosine_term = tf.math.maximum(tf.zeros_like(cosine_term), cosine_term)
vector_light_to_surface = intersection_3d - light_position
light_to_surface_distance_squared = vector.dot(
    vector_light_to_surface, vector_light_to_surface, axis=-1)
irradiance = light_intensity / (4 * m.pi *
                                light_to_surface_distance_squared) * cosine_term
# Rendering equation
zeros = tf.zeros(intersection_3d.shape)
radiance = brdf_composite * irradiance
radiance_lambertian = brdf_lambertian * irradiance
radiance_phong = brdf_phong * irradiance

###############################
# Display the rendered sphere #
###############################
# Saturates radiances at 1 for rendering purposes.
radiance = np.minimum(radiance, 1.0)
radiance_lambertian = np.minimum(radiance_lambertian, 1.0)
radiance_phong = np.minimum(radiance_phong, 1.0)
# Gammma correction
radiance = np.power(radiance, 1.0 / 2.2)
radiance_lambertian = np.power(radiance_lambertian, 1.0 / 2.2)
radiance_phong = np.power(radiance_phong, 1.0 / 2.2)

plt.figure(figsize=(20, 20))

# Diffuse
radiance_lambertian = np.transpose(radiance_lambertian, (1, 0, 2))
ax = plt.subplot("131")
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
ax.grid(False)
ax.set_title("Lambertian")
_ = ax.imshow(radiance_lambertian)

# Specular
radiance_phong = np.transpose(radiance_phong, (1, 0, 2))
ax = plt.subplot("132")
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
ax.grid(False)
ax.set_title("Specular - Phong")
_ = ax.imshow(radiance_phong)

# Diffuse + specular
radiance = np.transpose(radiance, (1, 0, 2))
ax = plt.subplot("133")
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
ax.grid(False)
ax.set_title("Combined lambertian and specular")
_ = ax.imshow(radiance)

 

以上






AI導入支援 #2 ウェビナー

スモールスタートを可能としたAI導入支援   Vol.2
[無料 WEB セミナー] [詳細]
「画像認識 AI PoC スターターパック」の紹介
既に AI 技術を実ビジネスで活用し、成果を上げている日本企業も多く存在しており、競争優位なビジネスを展開しております。
しかしながら AI を導入したくとも PoC (概念実証) だけでも高額な費用がかかり取組めていない企業も少なくないようです。A I導入時には欠かせない PoC を手軽にしかも短期間で認知度を確認可能とするサービの紹介と共に、AI 技術の特性と具体的な導入プロセスに加え運用時のポイントについても解説いたします。
日時:2021年10月13日(水)
会場:WEBセミナー
共催:クラスキャット、日本FLOW(株)
後援:働き方改革推進コンソーシアム
参加費: 無料 (事前登録制)
人工知能開発支援
◆ クラスキャットは 人工知能研究開発支援 サービスを提供しています :
  • テクニカルコンサルティングサービス
  • 実証実験 (プロトタイプ構築)
  • アプリケーションへの実装
  • 人工知能研修サービス
◆ お問合せ先 ◆
(株)クラスキャット
セールス・インフォメーション
E-Mail:sales-info@classcat.com