HOMEWORKS2020に参加しました。

もう2ヶ月近く前の話ですが、、、
1月23日24日と大阪のPINE BLOOKLYNというイベントスペースで、
HOMEWORKSという展示のイベントに参加させていただきました。

その中で私は drawingBlobscapes という作品を展示させていただきました。

drawingBlobscapes

20210124_1324.gif

画像まとめ(flickr)
20200123-24_HOMEWORKS

コロナ禍ということもあり、中には東京からリモートで展示される作家さんもいらっしゃいましたが、私は帰省も兼ねて厳重にコロナ対策を行った上で現地にて参加させていただきました。

ちなみに大阪移動で新幹線のグリーン車に初めて乗ったのですが、普段乗っているものと結構違って少し衝撃でした。広くてすげー快適、人もわりかし少なかった。

経緯

HOMEWORKSについて以前から名前は知っていて、参加してみたいなあと思っていた展示でした。たまたま会社の同僚から紹介いただいて、いい機会だったので、ぜひにと参加させていただきました。

当初はVRゴーグルに使われるような高密解像度モニタを使って、
一見写真や絵画に見える展示物の中で一部映像が表示されているという作品を作ろうと考えていたのですが、
VRモニタとPCの相性が割と限られていたようで、予定していたPCではモニタに映像が正しく表示されないという自体が発覚し、展示内容を再検討しました。VRモニタはPC選んで別の機会に使ってみたい。

なにか使えそうなアイデアないかなと過去のプロジェクトなど見ていると、ちょうど1年前にopenFrameworksで作成していた実験プロジェクトを発掘し、自分としては改めて好きな表現だなーと思ったので、こちらを作品として仕上げてみることにしました。

作品について、

概要的な話をすると、
openFrameworksを始めてからkyndさんというアーティストを知り、プログラミングで作るアナログな表現に魅力を感じていました。

作っていく過程で、
抽象的に変換された自分の像を見ることで、自分にしかそれは自分だとわからない表現が面白いなと思ったり、
自分は写真に映るのが少し苦手なので、こういう曖昧な像の残り方は好都合だと思いました。

ちょっと余談ですが、記憶を探るには小石程度のきっかけで良いとパクノダが言ってました。
実際には、記憶は形を留めないけれど。美化され風化されるものだけれど。
個人的に思い出すということに関しては、別に正確でなくても十分に意味は果たしている、
むしろ正確に思い出すことはそこまで重要でなく、美化され風化され、
都合よく形を変えた方が思い出すということは豊かな気がします。

手書きのようなイラストチックな表現を目指した結果、いままでなんとなく好きだった表現に少し理由が見えてきた気がしました。

同じ絵でも、他人にはわからないけど、自分にとってはなんとなく理解できるものは、愛着を持ちやすいと思います。自分にだけの度合いが強ければなおさら。
また一見なんの手がかりにもならない写真や映像が、ある人にとっては、何かを思い出すきっかけになればいいなと思っていました。エモ。

イラストチックにするだけであれば、映像をアニメ調に変換するとか、鉛筆画風に変換するとか、シェーダーや機械学習を使った手法がたくさんあります。

それも悪かあないのですが、別の手法をとった場合、何かしらの制限によって別の手法が必要になった場合、自ずと差別化された新しい表現が生まれるものかもしれないです。
まあ今回の話では時間や自分の能力などの制限が仕方なく発生している部分もありますが。
だからこそ、このプロトタイプとしてゆるく展示できる場所には大きな意味があるとも感じました。


技術的な話をすると、
主な技術としてはopenCVのfindContours , k-meansというものが使われています。

撮影した映像の1フレームを対象にk-meansの処理を掛けることで、その1枚で使われている主な色を抜き出します。

K-meansとは、ものすごくざっくりと説明すると、複数ある値を指定したK個のクラスに分類する手法です。普通、平均を出すと、複数の値から1つの平均値を取り出しますが、それが複数個取り出せるみたいな。(今回は10個とか)
以下の図でいうと、XYにたくさんプロットされている点を3つのクラスタに分類すると、各点はどの分類に当てはまるか、またその主となるXYは(薄い大きな+OX)どんな値か。みたいな。
そして、取り出した色をもとにfindContoursという処理をあてます。

kmeans

findContoursについてもざっくり説明すると、1枚の画像から輪郭を検出するような処理です。
ピクセルごとに周りのピクセルと比較して明るさに大きなギャップがあるピクセルを輪郭のエッジとするみたいな。
で今回は、色を指定してこのfindContoursをかけ、指定した色の輪郭を検出するということをしています。

こうして検出された輪郭はいくつかの点の情報を持っています。この点をつないで輪郭線を書くわけなんですが、このときこの点の数を間引いていくことで抽象的な表現にしています。要は多角形を三角形に近づけていくみたいな話。
図形に近づけることで少しおしゃれな見え方になったりしてたのしい。gifでみると変化が見られたりしてたのしい。

でまた、この輪郭のことをContourとかBlobと呼ぶことをよく見かけます。
この輪郭・塊の集合で表された像を描いていく作品だったので、タイトルをdrawingBlobscapesとしました。

ちなみに本作はopenFrameworksを使用して制作したのですが、
K-meansは内部的にはピクセルに対して行われる処理ではあるので割と重たい処理です。なので、この処理は別スレッドで処理するようにしています。
来場者の中にopenCVに詳しい方、openFrameworksを触っていた方もいらしていて、まさにスレッドなど自分としては少し頑張った部分について質問していただいた方がいて嬉しかったです。

その他、今回はほぼshaderを使っていないので、今後のブラッシュアップもいろいろできるかなと思ったり。ただ、使わなかったからこその表現であった気もします。

おおまかな作り自体は1年前の元プロジェクトの時点でできていたものの、
展示用に最適化であったり、パラメータの調整的なところであったり、
簡易でマッピングの機能もいるわと思って、ofxWarpMeshで対応したり。

あとWebカメラの映像をそのままこの変換に掛けるのでなく、彩度やコントラストの調整は事前にWebCamSettingというアプリを使って処理しました。
その調整くらいならプロジェクトに仕込んでもよかったけど、ギリギリまで別の所を詰めるべきだと思ったので、そこは既存のアプリをありがたく使おうと割り切りました。こういう展示なら十分。

感想

思っていたよりもお客さんが来てくれていて、だけど会場が広くて込み過ぎもせず、とてもいいイベントに参加させていただきました。
めちゃくちゃ良いスペースだったのですが、もう営業終了してしまうということで非常に残念。

リアルな展示ではお客さんから直接感想やフィードバックを貰えるので、やった実感があって楽しかったです。

展示しながら人がいないタイミングでパラメータいじってみたり、gifでも出力しておきたいなと思って、急遽1分毎くらいに3秒分くらいを連番で書き出す機能を実装してみたり。個人的にはライブ感のある展示で退屈しなかったです。これもゆるめの展示だからこそ。

プロジェクターを割と大きなスペースにドンと投影するのは久しぶりだったので、やっぱりそれだけで少し嬉しかったです。
コロナが落ち着いてきているので、また少しずつこういうイベントが増えて参加できるといいなあ。

ご来場いただいたお客さん、企画運営などしてくださった方々、参加作家のみなさま、お疲れさまでした&ありがとうございました!!

20210124_1422.gif
20210124_1326.gif

[fav work] 100 Special Moments

[fav work] 100 Special Moments

fav work.
いいなと思った作品を雑に調べた雑な記録です。
this is a dirty memo.

100 Special Moments - Jason Salavon (2004)

100 Special Moments 2004

Digital C-print.
Dimensions variable. Ed. 7 + 2 APs.

From a broader series begun in 1997, each of these works utilizes 100 unique commemorative photographs culled from the internet. The final compositions are arrived at using both the mean and the median, splitting the difference between a specific norm and an ideal one.

1997年に始まったより広いシリーズから、これらの作品のそれぞれは、インターネットから切り取られた100枚のユニークな記念写真を利用しています。最終的な構成は、特定の標準と理想的なものとの間の差を分割し、平均と中央値の両方を使用して到着します。

こちらが第一弾の作品だそうだ。
Jason Salavon | Figure 1. (Every Playboy Centerfold, 1988-1997)

10年間のPlayboy誌の袋とじ的な写真の集合らしい。

この集合する手法を amalgamations というふうに表していた。

こういったamalgamationsシリーズを知るきっかけになったのが、FORM+CODEに掲載されていた100 Special Momentsでした。

Jason Salavon | 100 Special Moments

似たような画像を重ねて平均を取って一枚とする、みたいな手法は今となっては真新しくもなんともないけれど、個人的にはやっぱり好きな手法・仕組みだ。誰でもちょっと見ればなんとなく意図がわかるし、表現としても淡くいい感じになりやすいし、観賞者が理解しやすい気がする。

対象物の選択がおもしろい。ポルノ関連のものであったり、結婚式やサンタさんなど、定番っちゃ定番でありふれたアプローチかもしれないけど、やっぱり、なんかいいなあと思える。


JASON SALAVON

  • Jason Salavon | Biography

    Jason Salavonは、独自のデザインによるソフトウェア・プロセスを用いて、大量の共同体の素材を生成し、再構成することで、身近なものに新しい視点を提示しています。形式的には多様であるが、彼のプロジェクトは、多様な視覚的集団の中に配置された個々の要素の役割を操作することが多い。その結果、部分と全体、個人と集団の関係性が探求され、予期せぬパターンが発見されることも少なくありません。彼の作品は、大衆文化や日常に自然に惹かれていることを反映しており、共通の参照文献やソース素材の使用を定期的に取り入れています。最終的な作品は、写真プリントやビデオインスタレーションなどのオブジェとして展示されていますが、リアルタイムのソフトウェアの文脈の中に存在するものもあります。

    1970年にインディアナ州で生まれ、テキサス州で育ち、シカゴを拠点に活動するサラヴォンは、シカゴ美術学院で美術修士号を取得し、テキサス大学オースティン校で学士号を取得しました。彼の作品は世界中の美術館やギャラリーで展示されています。彼の展覧会のレビューは、Artforum、Art in America、The New York Times、WIREDなどの出版物に掲載されています。彼の作品の例は、メトロポリタン美術館、ホイットニー美術館、シカゴ美術館などの著名な公共および個人のコレクションに収蔵されています。

近年ではGANを使った作品を発表しているよう。こちらも大量の画像をもとに新たな表現を生み出すという軸に沿ったもので、とてもいい。

Homage in Between (annotated) from Jason Salavon Studio on Vimeo.

reference

CABINET / Artist Project / 100 Special Moments

As Susan Sontag has observed, “Photography reinforces a nominalist view of social reality as consisting of small units of an apparently infinite number—as the number of photographs that could be taken of anything is unlimited. Through photographs, the world becomes a series of unrelated, free-standing particles; and history, past and present, a set of anecdotes, and fait divers. The camera makes reality atomic, manageable, and opaque. It is a view of the world which denies interconnectedness, continuity, but which confers on each moment the character of a mystery.” While Jason Salavon’s work clearly recognizes the decompositional tendency of photography cited by Sontag, it does not simply accede to it, instead finding a way to use it against itself.

Dismembering the pictorial record of the American experience into the smallest possible unit, the pixel, Salavon’s work then remembers it in one composite output combining all the distinct source images—often commemorative photos culled from the Internet. This gesture in turn produces a second ambiguity; do the composite portraits—of newly married couples, of a child on Santa’s lap—in fact offer a sympathetic image of a shared experience that unites us despite our increasingly dislocated existences? Or are they an indictment of the homogenization of both experience and representation within contemporary society?

This project presents two pairs of composite portraits based on 100 images of familiar social rituals. The two apparently similar composites are produced using related but distinct computing processes developed by Salavon and applied to 100 source images culled from the Internet. For each output pixel of the “mean” portraits (which Salavon describes as “airy”), the numerical values of the 100 source pixels in the corresponding coordinate are added together and then divided by 100 to create a new “average” pixel; this process is then repeated for each of the millions of pixels that make up a given photograph. The “median” portraits (which Salavon describes as “crunchy”) are created using a related but crucially different process. Rather than averaging the 100 pixels at any given position, Salavon selects the actual pixel whose numerical value is in the middle of the series of 100. This one real pixel is then used to represent the entire set.

These twin procedures result in two visually similar but conceptually divergent images: one is a visualization of an “ideal norm” (mean) in that the image is a mathematical fabrication—none of those pixels ever existed. The other is a “specific norm” (median)—which is to say an aggregate of actual pixels selected from the source images. Like any photograph, Salavon’s images straddle the divide between the real and the idealized, just like the notion of ‘an average American life” hovers between lived reality and its idealized phantasm.

スーザン・ソンタグが観察しているように、「写真は、社会の現実を、何でも撮影できる写真の数が無限であるように、一見無限の数の小さな単位で構成されているという名目主義的な見方を強めている。写真を通して、世界は無関係な独立した粒子の集合体となり、歴史、過去、現在、逸話の集合体となり、多様性のあるものとなる。カメラは現実を原子的、管理可能、不透明にする。それは、相互接続性や連続性を否定する世界観であるが、それぞれの瞬間に謎の性質を与えるものである。ジェイソン・サラヴォンの作品は、ソンタグが引用した写真の分解的傾向を明確に認識しているが、単にそれに従うのではなく、自分自身に対してそれを利用する方法を見つけている。

アメリカの経験の絵画的な記録を可能な限り小さな単位であるピクセルに分解し、サラヴォンの作品はそれを記憶しており、インターネットから抜粋した記念写真など、すべての異なるソース画像を組み合わせた1つの合成画像として出力している。新婚のカップルやサンタの膝の上の子供など、合成されたポートレートは実際には、ますます疎遠になっていく私たちの存在にもかかわらず、私たちを結びつける共有の経験の共感的なイメージを提供しているのだろうか?それとも、現代社会における経験と表象の均質化への非難なのでしょうか?

このプロジェクトでは、身近な社会的儀式の100のイメージに基づいた2組の合成肖像画を提示します。一見似ているように見える2つの合成画像は、サラボンが開発した、関連性はあるが異なるコンピューティング・プロセスを用いて制作され、インターネットから抜粋した100枚の画像に適用されている。平均的な」ポートレート(サラヴォンは「空気感のある」と表現しています)の各出力ピクセルについて、対応する座標にある100のソースピクセルの数値を足し合わせ、100で割って新たな「平均的な」ピクセルを作成し、このプロセスを写真を構成する数百万のピクセルごとに繰り返します。このプロセスは、与えられた写真を構成する数百万のピクセルごとに繰り返されます。「中央値」のポートレート(サラボン氏は「カリカリ」と表現しています)は、関連していますが決定的に異なるプロセスを使って作成されます。任意の位置にある100個のピクセルを平均化するのではなく、サラヴォンは100個のピクセルの中から数値が中央にある実際のピクセルを選択します。そして、この1つの実際のピクセルが全体を表すために使用されます。

1つは「理想的な規範」(平均値)を可視化したもので、画像は数学的に作られたものであり、これらの画素は存在しません。もう一つは「特定の規範」(中央値)であり、元の画像から選ばれた実際のピクセルの集合体である。他の写真と同様に、サラヴォンのイメージは、「平均的なアメリカ人の生活」という概念が、生きている現実と理想化された空想の間をさまようようようように、現実と理想化の間をまたいでいる。

[fav work] Self Portrait

[fav work] Self Portrait

fav work.
僕の好きな作品を紹介します。

Self Portrait - RANDOM INTERNATIONAL (2010)

https://www.random-international.com/self-portrait-2010


すごく好きな作品のひとつ。
実物を見たことはないけれど。

大学院時代、UVライトについてちょっと調べていたときに知った。

アウトプットがアナログであるというところが好きなポイントだ。
ディスプレイではないもので像を再現することはロマンだと思う。フィルムだったり、レコードだったり。

4K、8Kと更に一層高解像度化が進むことで、限りなくアナログに近いデジタル表現は可能だろうけど、潜在的なところで大きな違いが存在するんだろうな。

瞬く間に消えていくという、素材の特徴を作品にうまく活かしていて最高。

Self Portrait invites viewers to become active agents in the making of their own depiction. The work creates a large-scale, impermanent representation of the person standing before it, printing their image with light onto a light-sensitive surface.
The portrait begins to fade away almost as soon as it emerges; the work erases every mark it makes. Each captured moment is immediately lost and can only be experienced as process. Self Portrait follows an aesthetic of presence and erasure that Random International has developed over the years in a variety of Temporary Printing Machine installations.

「セルフ・ポートレート」は、鑑賞者が自分自身の描写を作るための能動的なエージェントになることを誘います。この作品は、目の前に立っている人物のイメージを感光性の表面に光で印刷し、大規模で無常的な表現を作成します。
肖像画は、それが現れたとたんに消え始め、作品はその痕跡をすべて消し去ります。捉えられた一瞬一瞬はすぐに失われ、プロセスとしてしか体験することができません。セルフポートレート」は、ランダム・インターナショナルが長年にわたり、様々な一時的な印刷機のインスタレーションで培ってきた存在感と消去の美学を踏襲しています。

アイデアとしてはやはりlight reactive screen print がポイント。

動画はちょっと違うが。

蓄光という現象からいろんなアイデアを連想するのもおもしろいなあ。

最初に見たのはこっちの作品でした。

実験動画みたいなのもあった。(10年前で止まってるけど、rAndomInternatinalのYoutube channnelもおもしろい)


2つ目なんか、木の板に蓄光塗料が塗られているのがよくわかる。

Plywood canvas, light reactive paint, Aluminium, PCB, rapid prototyped parts, motor, stainless steel rails, computer. This object is a machine that temporarily paints any pixel-based images or text with light. It uses a special, light reactive material as a canvas which allows the image to remain visible for about 45 seconds to 1 minute. The painting then fades away, creating space for a new one immediately.

合板キャンバス、光反応性塗料、アルミニウム、PCB、ラピッドプロトタイピングパーツ、モーター、ステンレススチールレール、コンピューター。

このオブジェクトは、任意のピクセルベースの画像やテキストを一時的に光でペイントする機械です。特殊な光反応性材料をキャンバスとして使用し、約45秒から1分間、画像が見える状態を保ちます。その後、ペイントはフェードアウトし、すぐに新しいもののためのスペースが作られます。

記事

  • https://www.designboom.com/art/random-international-self-portrait-temporary-printing-machine/

単純明快で、儚くて、なんとも言えないけど、なんだかすごくいい作品です。


fin

oF_ofxARKitでPeopleOcclusion

openFrameworksでPeopleOcclusionを実装する際の手順を記載します。

こちらにソースコードおいてます。以下はその解説などになります。
https://github.com/shiyuugohirao/oF_PeopleOcclusion_example

はじめに

PeopleOcclusionというのはAppleが開発したARKitに備わっている機能です。
2次元の画像から人と認識される部分を取得できます。

ちゃんと着手するまで勘違いしていましたが、
PeopleOcclusionはあくまで2次元の処理であり、深度を取得したり推定したりする機能ではありません。

逆に言えば人間部分の推定に深度情報を必要としないので、
ディスプレイ・モニタに写った人や平面ポスターに印刷された人なんかでも認識は可能です。
(実際の人間に比べると精度は劣るような印象ですが。)

ちなみにPeopleOcclusionと呼んだり、PersonSegmentationと呼んだり、ほぼ同義のワードが飛び交うようです。

またちなみに、Unityでは、Unityが公式で開発しているらしいARFoundationというARKitをまとめたSDK(?)があって、そこから比較的容易に取得できます。
以前、北千住デザインさんのQiitaの記事を参考にしたら、いとも簡単に動かせたので驚きでした。

で、Unityでは調べりゃたくさん記事が出てくるのですが、openFrameworksではたぶんほぼ参考文献がありませんでした。
ZachLibermanさんのInstagramなどでは、ちらほらPeopleOcclusionらしき作例がアップされていたので、あきらめずに試行錯誤できました。

環境

手順

まずは、ofxARKitのサンプルを動かしてみます。
他のアドオンと違いちょいと設定が必要なので、ofxARKitを触ったことない方は、慣れるためにも、適当なサンプルをいくつか実機で実行してみることをおすすめします。
(たとえばexample-basicとかexample-face-trackingとか)

ProjectGeneratorを使ってプロジェクトファイルを作る際には、2bbbさんの記事もとても参考になります。

ofxARKitを使う際の設定項目は大きく4つ。

  • Targetの設定 ()
  • Signing&Capabilitiesの設定
  • ofxiOS-Info.plist でカメラ許可の設定
  • Shaders.metal の設定

以下その詳細な手順

  1. ProjectGenerator > import で適当なサンプルフォルダを選択し、 Updateでプロジェクトファイル(.xcodeproj)を生成します。

  2. 生成したxcodeprojを開きます。

  3. 左のProjectNavigatorからプロジェクト名を選択して、[General]タブからDeploymentInfo > TargetをiOS13以上にします。
    ※PeopleOcclusionなどiOS13以上でないと使えない機能を使う場合、Targetの設定もiOS13以上を設定しておかないとたしか警告が出てうぜえです。


  4. 続いて[Signing&Capabilities]タブでAppleDevelopperLicenseの設定を行います。
    ※ここについての詳細はいろいろとややこしいので、別の記事を参考にしてください。

  5. ProjectNavigatorから ofxiOS-Info.plistを開き、右クリック>AddRow>Privacy - Camera Usage Description を追加します。
    ※Valueをサボって空欄にしているとアプリ起動時にコンソールに以下のようなエラーが出てました。

    [access] This app has crashed because it attempted to access privacy-sensitive data without a usage description.  The app's Info.plist must contain an NSCameraUsageDescription key with a string value explaining to the user how the app uses this data.
    




  6. ProjectNavigatorから addons > ofxARKit > src > lib > Shaders.metal を開き、右側Inspectorsから Typeを MetalShaderSource、TargetMembershipにチェックを入れます。




その他注意点として、ProjectGeneratorで新規プロジェクトを作ったら、以下フォルダのsrcファイルも必要になります。

  • delegates
    • MyAppDelegate.h
    • MyAppDelegate.mm
  • viewcontrollers
    • MyAppViewController.h
    • MyAppViewController.mm
    • OFAppViewController.h
    • OFAppViewController.mm

基本はexampleのsrcフォルダにある各フォルダをコピペでいいと思います。僕は特に弄ったことはなかったと思います。

上記の手順を踏めば、実機でサンプルは問題なく動くはずです。
ビルド成功しても、起動直後に落ちる場合は、カメラの設定など怪しいです。
コンソールのエラーを見ると割とちゃんとエラー内容が書いてあるので、参考にしてみてください。

上記手順はProjectGeneratorでプロジェクトをUpdateするたびに必要になります。
なんてこともofxARKitのREADMEに書いてありました。丁寧だぜ。

PeopleOcclusionの実装

本題です。

要点は、

  • ARKitからSegmentationBufferを取得する。
  • 取得したSegmentationBufferを頑張って使いやす型に変換する。
    →今回はcv::Matに変換する方法を見つけたのでcv::Matを採用しました。

ARKitでは人物か否かをSegmentBufferというバッファに格納するようです。
ここまでできれば、openFrameworksで如何様に処理が可能です。

注意点として、取得できるSegmentationBufferは 256x192pxしかありません。
iPhoneXSの場合、取得したカメラ画像の解像度は 1125x2436pxなので、SegmentationBufferをマスクとしてカメラ画像を切り取るには調整が必要です。
cv::Matでは座標の向きも普段と異なったり。。

また、SegmentationBufferをスケールだけ合わせてマスクとして利用すると、もとが低解像度のためエッジがかくかくしてしまいます。
このためof_PeopleOcclusion_exampleではブラーをかけてエッジをなめらかにしてみたり、
ofxCv::ContourFinderで輪郭(Blob)を取得してみたり、工夫が必要になります。

ARKitからSegmentationBufferを取得する

oF_PeopleOcclusion_example をもとに説明していきます。

サンプルアプリの動作を説明をしておくと、

  • 取得したカメラ画像の描画
  • SegmentationBufferをもとに取得した輪郭線の描画
  • SegmentationBufferをもとに取得したステンシルバッファ(白黒マスク画像)の描画
  • ステンシルバッファでマスクしたカメラ画像(セグメンテーションされた画像)の描画

の4つをそれぞれ、画面左上、右上、左下、右下のタップでオンオフ切り替えるものです。



sessionの開始

ARKitを利用するためexample-basicなどと同様、まずofAppのコンストラクタでARKitのセッションを開始します。

このsession開始時に合わせて、どんなsessionを開始するのかを記述したconfigurationを設定します。
※これはexample-face-trackingのサンプルを参考にしました。

ofApp :: ofApp (ARSession * session){
    ARWorldTrackingConfiguration *configuration = [ARWorldTrackingConfiguration new];
    auto mode = ARFrameSemanticPersonSegmentationWithDepth;
    bool b = [ARWorldTrackingConfiguration supportsFrameSemantics:mode];
    if(b) configuration.frameSemantics = mode;
    else ofLogWarning()<<"Not support for "<<mode;
    [session runWithConfiguration:configuration];
    this->session = session;
}

ARWorldTrackingConfigurationの他にもARBodyTrackingConfigurationなど面白そうな設定もあるのですが、
今回のPeopleOcclusionについては、ARWorldTrackingConfigurationなど一部のタイプでしか利用できなかったはず(Apple公式リファレンスにそんな記述があったようななかったような)

用意したconfigurationに対してframeSemanticsというものを追加で設定してやります。
これもPeopleOcclusionをする際は、ARFrameSemanticPersonSegmentationARFrameSemanticPersonSegmentationWithDepthなどを指定する必要があります。(Apple公式リファレンス)

以上で、ofApp起動後にセッションが開始され、setup()のなかから、このセッションを引数としてprocessorを生成します。

    processor = ARProcessor::create(session);
    processor->setup();

で、このprocessorをupdate()することで情報を更新し、sessionから様々な情報を取得することができるようになります。

cvtSegmentationToPix()

update()から呼んでいるもので、ここで、要点となるsegmentationBufferの取得と変換を行っています。

auto buf = session.currentFrame.segmentationBuffer;

ここがポイントです。
ちなみにサンプルでは推論型を使っていますが、CVPixelBufferRefとなります。(公式リファレンス)

さらにちなみにここでsegmentationBufferではなく、estimatedDepthDataを取得すればおそらく2次元画像からデプス推定したバッファを取得できるはず、、!

取得した CVPixelBufferRef をcv::Matに変換します。
参考 : https://stackoverflow.com/questions/19358686/how-do-i-convert-from-a-cvpixelbufferref-to-an-opencv-cvmat/43465531

cv::Mat ofApp::getMatFromImageBuffer(CVImageBufferRef buffer) {
    cv::Mat mat ;
    CVPixelBufferLockBaseAddress(buffer, 0);
    void *address = CVPixelBufferGetBaseAddress(buffer);
    int width = (int) CVPixelBufferGetWidth(buffer);
    int height = (int) CVPixelBufferGetHeight(buffer);
    mat = cv::Mat(height, width, CV_8UC4, address, 0);
    //ofxCv::convertColor(mat, mat, CV_BGRA2BGR);
    //cv::cvtColor(mat, mat, CV_BGRA2RGBA);
    CVPixelBufferUnlockBaseAddress(buffer, 0);
    return mat;
}

ここまでで、openFrameworksでPeopleOcclusion(SegmentationBuffer)を取得することができました。

ここから先は、取得したデータをどう処理するかという話になります。
cv::Matの描画やマスクなどの処理については後日また改めて、書きたいと思います。

study:

[TouchDesigner] DATまわりの話

はじめに

# TouchDesigner Advent Calendar 2019

この記事はQiitaに投稿した記事の動画補足つきVerです。

また先日とある大学で行われた制作展のサポートをさせていただき、学生さんにTouchDesignerなどを教える機会がありました。
今後もそういった機会が増えるため、入門者初心者にもなるたけすげーわかりやすく書けるよう努力します、、!!

ここはこういうやり方あるよ、このほうがいいよ、など引っかかることがあれば気軽に教えていただければ幸いです、、!🙏


DATにまつわる話

CSVの読み込み

FileInDATでcsvファイルなどの読み込みができます。(いくらか前は対応してなかったぽいです。)
FileInDATのRefreshトグルをオンにしておくと、読み込み元のファイルの変更を保存ごとに随時反映してくれます。

ちなみにcsvファイルをドラッグアンドドロップすると自動でTableDATに変換して読み込みができます。が、Tableとして読み込まれるためcsvファイルの変更は反映されません。

※FileInでcsvを読み込む際、csvファイルの最終行が読み込まれない場合があるので注意です。
とりあえずcsvファイルを用意する場合は、最終行に空行を追加するなどするのがよいかもです。

5行目の空行がないと @hello, he, helloの行を読み込んでくれません。(動画1:51)

日本語ファイルの読み込み

日本語を含むcsvファイル(ツイートデータ、歌詞データなど)をTouchDesingerに取り込むときにぶつかる問題です。
TouchDesignerではTextに直接日本語を入力したりはできますが、csvなどファイルから読み込んだときにはエンコードの関係で文字化けしてしまいます。
正しく取り込むためにはPythoのスクリプトを書いてutf8として指定して読み込む必要があります。
以下はそんなスクリプトの一例です。

# loadJapaneseFile - Example

import csv
table = op('loadedCSV')
table.clear()

path = project.folder +'/'+ me.parent().par.Csvfile

with open(path, encoding='utf8') as f:
    data = csv.reader(f)
    cn = len(next(data))
    rn = len(list(data))+1
    table.setSize(rn,cn)

with open(path, encoding='utf8') as f:
    data = csv.reader(f)
    r=0
    for row in data:
        c=0
        for col in row:
            print( col )
            table[r,c] = col.strip()
            c+=1
        r+=1

上記のスクリプトでは、一度テーブルをリセットして、csvの数だけセル(空白)を作った後、再度読み込んだcsvの値をセットしています。
なんかいろいろ試した際に思うように行かず、取り急ぎ実装した一例なので、あまり効率的でないかも。。いやゼッタイへん。
よりよい実装わかりしだい更新しますね。

指定フォルダ内の動画を再生する

Palleteの中にmoviePlaylistなんてものもありますが。。もっとシンプルでいいんだって時。
FolderDATで、フォルダ内のファイルリストを取得できます。
この際、拡張子の指定や、サブフォルダ(子フォルダ)の中身も参照するかどうかなど、簡単にプロパティから指定できます。


日付順にソート

最新の動画を取得したいなどの要望を叶えるため、
FolderDATで取得したリストを日付順だったり更新順に並べ替えたいという場合があります。
並べ替えたい時はSortDATというものがあるのですが、基本的には数値順かアルファベット順のみです。Dateを表示させると「Fri Dec 6~」みたいな表示でうまく並べ替えできない場合があります。このためDateをEpochというフォーマットに置き換えソートを掛けます。

上記の動画で操作しているように、ポイントはFolderのDateFormatをEpochにするところ。
これによって正しくSortをかけることができます。
またSortDATにはランダムに並べ替える機能もあり、Seedの値を変更することでランダムな並びを変更できます。
いわゆる配列のシャッフルのように使えるので便利です。(動画2:05)

ついでにSort後、再度日付に変換するtoxを作っていたのですが、、ファイル行方不明のため後ほどアップしておきます。。

TextDAT

Pythonのスクリプトを書き込んで実行することができます。
その他、メモ書きのように利用することもできます。プログラミング言語で言うコメントの役割ですね。

スクリプトを書く

オペレータをアクティブ状態にするとスクリプトを書くことができます。
書き込んだスクリプトはTextDATを右クリック>Run、またはCtrl (Cmd)+Rで実行できます。(アクティブ状態で選択しているとき、つまりオペレータに直接入力可能な状態の場合はスクリプトの実行ができません!)

その他、他のスクリプト内から、op('text1').run()のようにオペレータを指定してrun()とすることでスクリプトを実行することができます。

そんでから、実行結果はTextportというウィンドウで確認することができます。
ツールバー>Dialogs>Textport and DATs、またはAlt (option)+Tでウィンドウを開くことができます。

関数ごとにTextを作る

Execute系のオペレータから実行するとき、直接その中に書くと、デバッグしづらいことがあります。
たとえばChopの0,1(OFF,ON)をフラグとして関数を実行する場合、「Chopの値をもとにDATのTextで書いたスクリプトを実行したい」ので、ChopExcuteを使用することになるかと思います。
このとき直接ChopExecuteの中に処理のスクリプトを書いてもいいのですが、ChopExecuteを選択してCtrl+RとしてもonOffToOn()というイベント関数になっているので実行されません。
作業中は任意のタイミングで処理を実行させたい場合が往々にしてあると思います。そんなときのために処理のスクリプトは別のTextDATにわけて書くと後々融通がききやすいです。

後々知りましたが、このことは、かの先生も自身のサイトで述べられていたので、真理なんだと思います。

また関数をひとつのTextDATに書いた際、

print(me) #とか 
print('---'+me.name+'---') #とか

などを追加しておけばスクリプトの実行順が追いやすいのでデバッグしやすいかもです。

その他ちょっとしたスクリプトTips

  • オペレータのpulseパラメータをスクリプトから叩く
    たとえばMovieFileInのCuepulsewを叩く時
op('moviefilein1').par.cuepulse.pulse()
  • ButtonCOMPをスクリプトからクリックする。
op('button1')click()
  • EvaluateDATのExpressionでスクリプトの簡易チェック
    td_evaluate.png
    単純に値をとってくるときなどに意外と便利かもです。

  • TD高速化Tips
    op('lfo1')['chan1'] よりも op('lfo1')[0] のほうが処理速度は早い(らしい) 


おまけ

オペレータに色を付ける。

自作のtoxなどのオペレータに色を付けたい。調べてもパッと出てこなかったけど、何かのチュートリアル動画を見ていたときにしれっと色をつけているのを見てやり方を知りました。

  1. Cキーを押してカラーパレットを表示
  2. 色を付けたいオペレーターを選択してカラーパレットから色を選択

td_opColor.png

自作toxのロードについて

いい感じのオペレータ群ができたら、オペレータ群をまるっと選択>右クリック>CollapseSelected でひとつのコンテナにまとめる。
このコンテナをtoxとして利用するため、Save Component .toxでtoxファイルに書き出すのですが、このときのもとの自作コンテナは自動ではtoxファイルを参照していることにはなりません。
CommonでExternal.toxを指定でき、これを指定することで初めて、toxファイルを参照して利用することができます。
Reload .tox on Startで起動時にtoxファイルを読み込んできますが、作業中にtoxを編集して再度読み直す場合は、Common>Re-Initが便利です。

また初期値として、ReloadCustomParametersがONになっています。このため、toxを使いまわしそれぞれパラメータを調整しても、ここがONのままだと次回起動時に元になっているtoxファイルの値が入ってしまい、調整が水の泡になってしまいます。適宜OFFにするなど注意してください!

td_base_common.png

ちなみに、Built-inのパラメータはOP.par.cuepulseのようにパラメータ名がオール小文字ですが、カスタムパラメータはOP.par.CustomparameterとParameter名の1文字目のみが必ず大文字になります。
標準パラメータとカスタマイズの干渉を防ぐためだったりすると思うのですが、
そんな些細なことになんとなく気がついていたおかげで僕は何度か幸せになることがありました。

おわりに

DATまわりの知見というか基礎的なところから些細なTipsを書かせていただきました。
なにかひとつでも役に立つものがあれば幸いです。

TouchDesignerはリアルタイム映像ジェネレータとしてとても優秀なソフトでVJ方面での利用が目立つ印象ですが、その一方で、データの管理など裏方処理がバチボコ楽、シリアル通信がバチボコ楽など、
プログラミングしたことないけど何か作りたい学生 にも"うってつけ"だと制作展のサポートで思いました。
(のちのちはプログラミングなどにも興味持ってもらいたいですけど)

ちなみに、今回動画の撮影はFonePawというソフト(無料版は3分間の書き出し制限)を使いました。
入力キーの表示はKeyCastrOWを使いました。KeyCastrOWはGithubから自分でビルドする必要がありますが、ビルド済みのものを配布している方がいらっしゃったのでそちらから拝借。

今後もちょろりちょろり書いていきたいです。

  • ドングルまわりの話(みんなどうしてるんですか?)
  • Instantiateの話
  • MovieFileInの話