The document discusses geometry processing and sparse matrices. It provides an overview of geometry processing, which uses applied math and computer science concepts to design algorithms for acquiring, reconstructing, analyzing, manipulating, simulating and transmitting complex 3D models. It then discusses representing shapes using triangle meshes and differential coordinates. It introduces discrete and continuous Laplace-Beltrami operators for geometry processing. Finally, it discusses representing the Laplacian matrix of a mesh as a sparse matrix using scipy and different sparse matrix storage formats like CSR and CSC for efficient computations.
7. Geometry Processingとは
Geometry processing, or mesh processing, is a fast-growing
area of research that uses concepts from applied mathematics,
computer science and engineering to design efficient
algorithms for the
¨ acquisition
¨ reconstruction
¨ analysis
¨ manipulation
¨ simulation
¨ transmission
of complex 3D models.
http://en.wikipedia.org/wiki/Geometry_processing
14. Stanford 3D Scan Repository
¨ Stanford Bunny
¤ 頂点数: 35,947
¤ 35,947 x 35,947 =
1.2 G
15. Stanford 3D Scan Repository
¨ Dragon
¤ 頂点数: 566,098
¤ 566,098 x 566,098 =
298G
16. 疎行列 Sparse Matrix
成分のほとんどがゼロである
ことを活用した形式で行列を
記憶・演算
“Sparse matrices are widely
used in scientific computation,
especially in large-scale
optimization, structural and circuit
analysis, computational fluid
dynamics, and, generally, the
numerical solution of partial
differential equations.”
Sparse Matrices in MATLAB: Design and
Implementation
21. From OpenOpt doc...
“Unlike MATLAB, Octave, and a number of other
software, there is not standard Python library for
sparse matrices: someone uses scipy.sparse, someone
PySparse, someone (as CVXOPT) uses its own library
and/or BLAS, someone just uses 3 columns (for the
number indexes and value). SciPy developers refused
to author of scipy.sparse to include it into NumPy, I
think it's a big mistake, probably now it would been a
unified standard. Still I hope in future numpy versions
difference in API for handling sparse and dense
arrays will be removed. “
22. 基本的な流れ
構築に適した形 演算に適した形式
式で行列を作る
に変換し演算を行う
A = lil_matrix((N,N))! A = A.tocsr()!
A[i,j] = a! A = A.dot(D)!
! f = factorized(A)!
x = f.solve(b)!
24. Graph Laplacian in scipy.sparse
from scipy import sparse!
!
N = len(points)!
L = sparse.lil_matrix((N, N))!
for vids in faces:!
L[vids, vids] = 1!
D = sparse.spdiags(L.sum(axis=0), 0, N, N)!
L = L.tocsc()-D!
25. Graph Laplacian in scipy.sparse
from scipy import sparse!
!
N = len(points)!
L = sparse.lil_matrix((N, N))!
for vids in faces:!
L[vids, vids] = 1!
D = sparse.spdiags(L.sum(axis=0), 0, N, N)!
L = L.tocsc()-D!
26. points and faces from Maya
!
import numpy as np!
import pymel.core as pm!
!
mesh = pm.PyNode(‘bunny’)!
points = np.array(mesh.getPoints())!
faces = np.array(mesh.getVertices()!
! ! [1]).reshape(mesh.numFaces(),3)!
27. Graph Laplacian in scipy.sparse
from scipy import sparse!
!
N = len(points)!
L = sparse.lil_matrix((N, N))!
for vids in faces:!
L[vids, vids] = 1!
D = sparse.spdiags(L.sum(axis=0), 0, N, N)!
L = L.tocsc()-D!
32. Sparse Matrix Format Benchmark:
Construction
Benchmark by modified bench_sparse.py in SciPy distribution
33. Sparse Matrix Format Benchmark:
Conversion
Benchmark by modified bench_sparse.py in SciPy distribution
34. Sparse Matrix Format Benchmark:
Matrix Vector Product
Benchmark by modified bench_sparse.py in SciPy distribution
35. Graph Laplacian in scipy.sparse
from scipy import sparse!
!
N = len(points)!
L = sparse.lil_matrix((N, N))!
for vids in faces:!
L[vids, vids] = 1!
D = sparse.spdiags(L.sum(axis=0), 0, N, N)!
L = L.tocsc()-D!
38. Graph Laplacian in scipy.sparse
from scipy import sparse!
!
N = len(points)!
L = sparse.lil_matrix((N, N))!
for vids in faces:!
L[vids, vids] = 1!
D = sparse.spdiags(L.sum(axis=0), 0, N, N)!
L = L.tocsc()-D!
39. 細かい演算の仕様
!
# LがCSC,CSRだとNotImplementedError!
L -= D!
!
# OK!
L = L-D!
40. Laplacian Mesh Fairing
!
! = ! − !L !
A Signal Processing Approach To Fair Surface Design
[Taubin 95]
41. Mesh Fairing in scipy.sparse
from scipy.sparse import linalg as spla!
!
A = sparse.identity(L.shape[0]) - _lambda * L!
solve = spla.factorized(A.tocsc())!
x = solve(points[:,0])!
y = solve(points[:,1])!
z = solve(points[:,2])!
new_points = np.array([x, y, z]).T!
!
# Set result back to Maya mesh!
mesh.setPoints(new_points)!
42. Mesh Fairing in scipy.sparse
from scipy.sparse import linalg as spla!
!
A = sparse.identity(L.shape[0]) - _lambda * L!
solve = spla.factorized(A.tocsc())!
x = solve(points[:,0])!
y = solve(points[:,1])!
z = solve(points[:,2])!
new_points = np.array([x, y, z]).T!
!
# Set result back to Maya mesh!
mesh.setPoints(new_points)!
43. Solving sparse linear system
¨ sparse.linalg.factorized(A)
¤ AのLU分解結果を保持したlinear system solver関数を
返す
¤ AはCSC形式で渡す必要がある
SparseEfficiencyWarning: splu requires CSC matrix
format
44. Mesh Fairing in scipy.sparse
from scipy.sparse import linalg as spla!
!
A = sparse.identity(L.shape[0]) - _lambda * L!
solve = spla.factorized(A.tocsc())!
x = solve(points[:,0])!
y = solve(points[:,1])!
z = solve(points[:,2])!
new_points = np.array([x, y, z]).T!
!
# Set result back to Maya mesh!
mesh.setPoints(new_points)!
45. Solving sparse linear system
# Error! 右辺はベクトルのみ!
new_points = solve(points)!
!
# 仕方がないので一列ずつ!
x = solve(points[:,0])!
y = solve(points[:,1])!
z = solve(points[:,2])!
new_points = np.array([x, y, z]).T!
57. Further Readings
Levy, Bruno and Zhang, Hao.
“Spectral Mesh Processing” ACM SIGGRAPH 2010
http://alice.loria.fr/WIKI/index.php/Graphite/SpectralMeshProcessing
¤ Laplacianの特異値分解を用いてMeshの周波数解析
58. Further Readings
[Alexa 2011] Alexa, Marc and Wardetzky, Max.
“Discrete Laplacians on General Polygonal Meshes”
ACM SIGGRAPH 2011
http://cybertron.cg.tu-berlin.de/polymesh/ (ソースコード有)
¤ Discrete Laplacianを一般的なポリゴンメッシュに対し定義