.hito project つくりました。

2013.04.27-05.03 恵比寿にあるPANOF studioにてunframeというグループ展を行い、
そこで「.hito」(ドットヒト)っていう作品を展示しました。


.hito project from rettuce on Vimeo.

img0

img1

photo

img2

img3

そして生成されたサイト。
website -> .hito

dot_hito_670

簡単な概要としては、2台のKinectを使って人を撮影し、
3D空間上で組み合わせて簡易3Dポリゴンとして復元。
ポリゴンに対して一定時間のキャプチャを繰り返し、
以下のファイルとして保存した後、webサイトにアップロードしてDBに保存って流れ。

・点情報、インデックス情報、面情報などを持った3Dデータの.objファイル
・.objファイルに色情報を加えた.hitoファイル
・一枚絵としての.pngファイル
・12コマアニメーションの.gifファイル
・3Dデータの.stlファイル

これらはその場で生成、アップロードされると、
サイトに反映されてページが出来てダウンロード可能になる仕組みにしました。

まーほんとにひどいコードでよければそのままgithubで。
(当日に急遽音に反応するような仕組み入れ込んだりそれをOSCで制御したりとか現場で組み込んだ部分があるのでぐちゃぐちゃ。。)
あ、github上のソースからはアップロードURLは抜いてます。:-p

ちなみにこのシステムそのまま使ってメンバー撮影して、
unframeのサイト背景映像とかに使ってました。:)
http://unframe.jp

Member of unframe project 001 from rettuce on Vimeo.

んでいきなり言い訳から入ると、
今回の展示は仕事の案件と時期がどん被りで、全く制作時間が取れなかった。。
表現面ではもっと色々なことが出来たと思うし(きゃりーえふぇくとやりたかった。。)、
せっかくこうやって自分のできることを見てもらえるいいチャンスだったので、
正直、今回に関して言えば会社員であることのハンデはまざまざと経験したなーという感じ。

んでもまー、制約や制限の中で何を作るか、何ができるか、どういった表現が生まれるかってのが
いつもやってる広告だとも思うし、そん中で自分が何ができるかって考えた結果が今回の「.hito」だったってだけの話。

制作かてい

以前つくった、Kinect x openFrameworks x Delaunay。表現は特にこれと変わらないのでポリゴンの作り方は割愛。
んで、今回やりたかったことは、OMOTE3D みたいなサービスを見た時に、単純に自分でもつくってみたい!と。
真鍋さんとかもやってたし、まーKinect2台使えばできんだろくらいの軽いノリで作り始める。

んでまずは単純に人をまるっと半身分撮影して、それを空間上でがっちゃんこしてつなげる。
(3Dデータとしてはつながってない)

sample0

なるほど、中心点から動いてズレるとその分、別のカメラからの入力に差分が生まれるのかー。
とか、当たり前のことをここで気付く。

あと、全身撮るには中心からKinectまでの距離1.83mくらい必要で、
合計4mも展示スペースとれねーよ。。てことでバストアップ+前45°からの撮影に急遽変更。

次に3D空間内で回転行列使ってKinectの点情報を自由に操作できるようにtoolパネルを作成。
ピッタリになるようにキャリブレーションして位置情報をxml保存。
(レセプション時はガンガン三脚とか蹴られるし、Kinect触ったりされるし、ズレまくってたな、、orz)

Demonstration of PointCloud using 2 Kinect. from rettuce on Vimeo.

で、ここで2台のKinectから取得できた3Dの位置情報を元に
新規MeshとしてVertex, Index, Face, Color,を定義してやる。
泥臭くtriangleの三点の中央位置に来る色情報をfaceの色として定義する。
頂点情報の被りはデータとしては重くなってしまうし無駄なんだけど
faceに対して1つ1つ個別のColorを定義したかったので目をつむる。。
この辺りはテクスチャにしてしまうとか、やり方を知らないだけでまだまだできると思う。

ここらで簡易ポリゴンはできた。

で、Meshまで持っていけたならそのままobjデータに書き出せるということをblogで知って、
ここでobjデータとかの存在を知る。
中身を見るとなるほど、頂点情報とかをそのまま書き出せばいいのか。なんかできそう。
ということで見よう見まねで自分で.obj書き出しもやってみる。この辺りはfile openとかC++ほんと楽チン。:)

んで、この辺りでちょっと特殊なMeshの作り方してんだからどうせなら色情報も1つのファイルに持たせてしまって、
オレオレ拡張子のデータ作ってまえばいいんじゃね?んでそれそのまま「.hito」でファイル拡張子そのまま作品名にすればいいやってなった。
(余談だけどヒトデータをそのまま書き出すってとこで.DNAってファイル拡張子とちょっと迷った)

んで次に、そんなマニアックなもんが出来上がっても自分以外誰も喜ばねーだろ、と。冷静に気付く。(独自ファイルなんだから当たり前やけども)
もうちょっと分かりやすいアウトプットを用意しましょ。ということでちょっと前にTLでたどころせんせが言ってた
GIFアニ書き出しとかあったなーと思い出す。あ、ofxGifEncoderだ。
あとはアイコン用とかに静止画png書き出しとかしてあげればいいかな?と。

ここらではTwitter, tumblr, とか既存SNSに上げていってって公開方法を想定してた。
twitter -> @dot_hito
facebook -> Dot.hito project
tumblr -> dothito.tumblr.com

でもやっぱり誰も喜ばない.objとか.hitoをダウンロードできるようにしたい。。!
てことでサイト作ることに。

えーと、サイトにアップロードってどうやるんだ。まずDBとか必要なんか?(ココ展示開始1週間まえくらいw)

てことでMySQLさわりはじめてみる。
Wordpressとかでよく初期設定は触るけど自分でSQL文叩いてどうこうは初めて。
でも意外とこれがどうして簡単楽チンで。わー、たのし。:)
てことで以下その時のメモ。

■ phpMyAdmin → DB作成

DB新規作成

.hito_project

テーブル作成

hito
カラム数 5
ID 		int(11)
DATE 	datetime
NAME 	text
HITO 	longtext
OBJ 	longtext

■ SQL確認

SHOW CREATE DATABASE `.hito_project` 

■ User追加

特権 → ログイン情報
ユーザー名 *********
ホスト localhost
パスワード hogehoge

■ テーブルを作成 → 『hito』テーブルに5カラム作成

CREATE TABLE `.hito_project`.`hito` (
`ID` INT NOT NULL ,
`DATE` DATE NOT NULL ,
`DNA` TEXT NOT NULL ,
`URL0` TEXT NOT NULL ,
`URL1` TEXT NOT NULL
) ENGINE = InnoDB;

■ テーブルの基本操作

INSERT データ登録
SELECT データ表示
UPDATE データ更新
DELETE データ削除

■ SQLでデータ追加 INSERT

INSERT INTO hito(ID, DNA) VALUES(0, '123456789');

全部入れる場合は先に要素指定いらない

INSERT INTO hito VALUES(1, '2013-04-27 04:24:26', '123456789', 'hito', 'obj');

■ SQLでデータ更新 UPDATE

全部更新

UPDATE hito SET URL0 = 'aaa';

指定更新

UPDATE hito SET URL0 = 'bbb' WHERE ID = 0;

■ SQLでデータ検索 SELECT

IDデータ全部取得

SELECT ID FROM hito ;

データ全部取得

SELECT * FROM hito ;

ID 0のデータ全部取得

SELECT * FROM hito WHERE ID = 0;

んでこっからphpで操作してみる。

■ MySQLに接続する

PHPでMySQLに接続するには、今はmysqliをつかうのがいいみたい。
てことで以下を変数にいれる。
‘接続先アドレス’, ‘ユーザー名’, ‘パスワード’, ‘データベース名’

$host = "localhost";
$user = "************";
$password = "hogehoge";
$database = ".hito_project";

//DB Connect
$mysqli = new mysqli($host, $user, $password, $database);
if ($mysqli->connect_errno) {
    printf("Connect failed: %s\n", $mysqli->connect_error);
    exit();
}

接続できたら呼び出し。

//SQL Set & Action
$sql = "SELECT * FROM hito LIMIT 100";

if ($result = $mysqli->query( $sql )) {
    // printf("Select returned %d rows.\n", $result->num_rows);

	$tempall = '';

	while($row = $result->fetch_array(MYSQLI_ASSOC))
	{
		$temp = '<article>';
		$temp .= '<a href="detail.php?n='.$row['NAME'].'" target="_self">';
		$temp .= '<img src="common/gif/'.$row['NAME'].'.gif" >';
		$temp .= '</a>';
		$temp .= '</article>';
		$tempall = $temp . $tempall;
	}

	print( $tempall );
}

$result->close();
$mysqli->close();

■ データベースに保存する

こちらも特に問題なくSQL文書いてqueryする。いっしょ。

//SQL Set & Action
$sql = "INSERT INTO hito VALUES(1, '2013-04-27 04:24:26', '123456789', 'hito', 'obj');";
if ($result = $mysqli->query( $sql )) {
	printf("SUCCESS ADD NEW DATA %d rows.\n", $result->num_rows);
}else{
	exit('CANNOT ADD NEW DATA...');
}

■ データベースを閉じる

$mysqli->close();

■ 最新5件を取得する

SELECT NAME FROM `hito` ORDER BY DATE DESC LIMIT 5

ORDER BY DATE DESC → 新しい順にDATEで並び替え
LIMIT 5 → 5件だけ

■ NAMEが****のデータを取得する

DELETE FROM `hito` WHERE `hito`.`NAME` = '****' LIMIT 1;

ということでphpでSQL操作みたいな簡単なことはできるようになったので、
次oFからPOSTしてphpにDB保存させるみたいなこと。
これもofxHttpUtils使ったらサクッといけた。

ofxHttpForm form;
ofxHttpUtils httpUtils;

void DataPost::upload_data(string id, string date, string name, string hito, string obj )
{
    form.action = HOST + WRITE_DB;
    form.method = OFX_HTTP_POST;
    form.addFormField("ID", id );
    form.addFormField("DATE", date );   // 2013-04-19 07:52:56
    form.addFormField("NAME", name );
    form.addFormField("HITO", hito );
    form.addFormField("OBJ",  obj );
    httpUtils.addForm(form);
    requestStr = "data post to server : " + HOST + WRITE_DB;
    ofLog( OF_LOG_NOTICE, requestStr );
}

みたいな感じでPOSTメソッド作っといて
さっきやったphp側でDBに書き込み。

んで次にoFでファイル転送。実はこれちょとハマったんだけど。
結局これもofxHttpUtils使ったら即解決。
そいえばなんかaddFormFieldと一緒に使うとうまくいかんかった。:-p
php側で受け取って、所定の保存場所にどんどこ保存。

// oF
void DataPost::upload_file(string path, string url )
{
    form.action = HOST + url;
    form.method = OFX_HTTP_POST;
    form.addFile("file", path );
    httpUtils.addForm(form);
    requestStr = "file sent to server : " + url;
    ofLog( OF_LOG_NOTICE, requestStr );
}
<?php
if ($_FILES["file"]["error"] > 0)
  {
  echo "Error: " . $_FILES["file"]["error"] . "
"; } else { echo "Upload: " . $_FILES["file"]["name"] . "
"; echo "Type: " . $_FILES["file"]["type"] . "
"; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb
"; echo "Stored in: " . $_FILES["file"]["tmp_name"]. "

"; // 受け取ったファイルを指定ディレクトリに保存 $target_dir = "/***********************/www/"; $target_path = $target_dir . basename($_FILES["file"]["name"]); if(is_uploaded_file($_FILES["file"]["tmp_name"])){ echo "The file ". basename($_FILES["file"]["name"])." has been uploaded 1
"; if(move_uploaded_file($_FILES["file"]["tmp_name"], $target_path)) { echo "The file ". basename($_FILES["file"]["name"])." has been uploaded 2
"; } else{ echo "Error...
"; } }else{ echo "NOT UPLOAD ...
"; } } ?>

参照するファイル名は同タイミングでさっきDBに保存したのでこれでサイトで使える。
ちょっとハマッたのはパーミッション関係で、php側でディレクトリ跨いでファイル操作したりするので
sshでさくらvpsの中に入って、ファイル操作する為の特定ディレクトリだけ所有者とか権限をapacheにあげたりとかとか。
ほいこれでPOSTからサーバー保存もおk。

後はDBに貯まったファイルネームを参照してページとリンクを生成。

さっきやった通り、DBに接続して、

<?php
$host = "localhost";
$user = "*************";
$password = "hogehoge";
$database = ".hito_project";

//DB Connect
$mysqli = new mysqli($host, $user, $password, $database);
if ($mysqli->connect_errno) {
    printf("Connect failed: %s\n", $mysqli->connect_error);
    exit();
}
?>

所定の場所でページとリンクを生成。

<?php
	//SQL Set & Action
	$sql = "SELECT NAME FROM `hito` ORDER BY DATE DESC LIMIT 5";

	if ($result = $mysqli->query( $sql )) {
	    // printf("Select returned %d rows.\n", $result->num_rows);

		while($row = $result->fetch_array(MYSQLI_ASSOC))
		{
			$temp = '<article>';
			$temp .= '<a href="detail.php?n='.$row['NAME'].'" target="_self">';
			$temp .= '<img src="oF/gif/'.$row['NAME'].'.gif" >';
			$temp .= '</a>';
			$temp .= '</article>';
			print( $temp );
		}
	}

    $result->close();
    $mysqli->close();
?>

詳細ページでは各々のファイル参照先をリンクとして繋げてあげれば、
現場で撮影 → データファイル生成 → サーバーにアップロード →
→ DB保存 → ウェブサイト掲載 → ダウンロードページ生成 が全自動でできる。
わー簡単ヾ(*´∀`*)ノキャッキャッ

所感(てか反省)

・展示用 MacBookPro 貧弱すぎた。

これはもうほんとごめんなさいって話で、3年前くらいの何のパワーアップもしてないMBP13incで
Kinect2台でリアルタイムポリゴン表現大分無理あった、、
ちゃんと展示期間中にMBP借りるなりしないとダメだったんだけど、
金ねーよってことでポリゴン数出来るだけ減らしたりキャプチャタイミング調整したんですが、
それでもfps10ちょっととか、3dデータ書き出す瞬間は固まったりとか、散々でした。。
普通の今時のスペックのMBPとかだったら全然60fps出るので、、
これはもうほんとに金なくてごめんなさいって話。orz

・もうちょっとヒトのディテール描画を細かくしてもよかったなー

上のスペックの話にモロ依存する話ではあるのだけれど、そこ無視する話をすると、
人の描画はもうちょっと細かくしてもよかったかなーと。
というのも、今回どこまでヒトを簡略化してデータにできるか、
それをヒトと認識できるかという実験的な意味合いもあって、自分や友人は判断できるし、
あーなんとなく分かるーってなるのだけど、正直不特定多数の人々が楽しむインスタレーションとしては
もっとヒトの判別が容易にできるほうが見ているユーザーが単純に楽しいし、発見もある。

そしてこれは収穫というか意外だったんだけど、みんな自分がサイトにアップされることにそこまで抵抗がない。
(もちろん今のポリゴン数だったら自分って分からないしってジャッジはあると思うんだけど)
それでもみんなwebサイト上に自分が公開されることへの抵抗ってのは、facebookやらInstagramやらの影響なのか
そんなになくなってきてるのかなぁとか思った。
人のディティールが細かくできればサイト自体ももっとバリエーションのある、
文字通り図鑑にできただろうなぁって思った。(ちなみに当初、zukan(図鑑ね)って作品名で考えてた)

んで以下がもちょっとディティール部分のパラメータ上げたバージョン。
(やってることはOpenCVのCannyEdge使ってランダムポイントに輪郭とか特徴点を追加する)

20130504_124100

ということでやっぱり自分で考えて自分で作りたいもんを自由に作れるってのがすげー楽しいし純粋にモチベーション上がる。(ほんとはもっと時間あったら、仕事としてできたら、、とか、たらればはめっちゃあるんだけども:-p )
でもやっぱりこういう割合を自分で増やしていきたいし、今後自分の仕事にしていきたいと思った。:)

見てくれた方、遊びに来てくれた方、どうもありがとうございました!

さて次いこー。:)

you