こんにちは西川です。これはMaya Advent Calender 2020の5日目の記事です!
Mayaでscikit-learnを使ってクラスタ分析してみます。Maya2020で動作を確認しています。
完成品
Gifを見てください。位置情報をもとにクラスタリングして、グループ分けしています。
近くにあるオブジェクトが良い感じにグループになってますね。これをPythonを使って実装しようと思います。そのためにはNumpyとscikit-learnが必要になります。
クラスタ分析 (K-means 法)とは?
k-means法とは何かについて知りたい方は下記の記事をご覧ください。簡単に言えば分類わけです。
k-means法は機械学習によく使われる、データを良い感じに分類分けするアルゴリズムです。 このアルゴリズムを使ってオブジェクトの位置をもとに分類わけしてみます。
背景のオブジェクトを近い位置にあるオブジェクトごとに、グループ分けしたいなぁーと思ったときに使い所あるかも?
実装方法
MayaでNumpyとscikit-learnを使えるようにする
MayaのPythonでクラスタ分析に必要なライブラリ「Numpy」と「scikit-learn」を使えるようにする必要があります。ビルドするのは面倒なので、すでにビルド済みのものをダウンロードします。公開してくださって感謝です。Maya2020で動作しました。
以下のURLの「Feel free to grab the wheels here」のリンクから「numpy-1.13.1+mkl-cp27-none-win_amd64.whl」をダウンロードします。
以下のURLの下の方にある「ビルド済みバイナリ」の「sklearn-0.18.1」をダウンロードします。下記のリンクのNumpyは私の環境では動きませんでした。
ダウンロードした2つのファイルを7zipなどで解凍して、PYTHONPATHが通ったところにおきます。私は以下のディレクトリを作成して中に入れました。
「C:\Users\user\Documents\maya\scripts\pythonPackage」
「C:\Users\user\Documents\maya\2020」にMaya.envファイルを作成して以下のコード記述しました。PYTHONPATHを追加します。
PYTHONPATH=C:\Users\user\Documents\maya\scripts\pythonPackage
これでMayaでNumpyとscikit-learnを使えるようなりました!
オブジェクトの位置をもとにクラスタ分析 (K-means 法)する
まずコードを示します。簡単です。
from sklearn.cluster import KMeans
import numpy as np
import maya.cmds as cmds
objects = cmds.ls(sl=True)
# ndarrayを作る。2次元配列で要素数が一致していないとエラーが出るので、000を入れておく
list_locations = np.array([[0,0,0]])
objects_name_list = []
for object in objects:
pos = cmds.xform(object,q=1,ws=1,rp=1)
location = np.array([pos])
# オブジェクトの位置情報をndarrayに追加する
list_locations = np.append(list_locations, location, axis=0)
# あとでオブジェクトをMaya上でグループ分けするために名前を保存しておく
objects_name_list.append(object)
# 最初のダミーを消す
list_locations = np.delete(list_locations,0,axis=0)
# クラスタの分類の数
num_clustering = 3
# K-means方を適用
pred = KMeans(n_clusters=num_clustering).fit_predict(list_locations)
for num in range(num_clustering):
grp = cmds.group( em=True, name='cluster_grp'+str(num) )
for index,object_name in enumerate(objects_name_list):
if pred[index] == num:
# クラスタが同じなら親子つけ
cmds.parent(object_name,grp)
コメントを読んでもらえればだいたい分かると思います。
オブジェクトの位置情報を2次元配列のndarrayにして、KMeansに渡しています。配列の要素数を事前にそろえないとエラーになるので[0,0,0]を入れて、ループをぬけた後に[0, 0, 0]をnp.deleteで消しています。
n_clusters=num_clustering
のところで分類分けする数を指定。
KMeansの結果はクラスタの番号が配列ででます。5個の分類なら[2,4,3,0,0,2,3,4]みたいな感じです。
最後に分類の数だけforループで回して、オブジェクトの名前のリストのインデックスから、KMeansの結果を取得して、番号が同じならグループに親子づけしています。
num_clusteringを指定することで好きな数に分類できます。色々試してみてください。
おわり
最もベーシックなクラスタリングアルゴリズムのk-means法をMayaで使ってみました。
機械学習で使われるアルゴリズムを3DCGで使ってみたらもっと面白いことができそうですね!
Maya Advent Calender 2020の6日目はlieさんの記事です!!