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

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の話

ASCII to String変換

ASCII to String 変換

C++の話。

oFでは keyPressed(int key)って関数があって、
キーボードの入力をASCIIコードの値としてkeyに格納され受け取ることができます。
たとえば[a]とキーを叩くと、keyにはASCIIコードで'a'を表す 97 という整数が格納されます。
このため、文字を計算式で扱えるなど、いろんな便利なことができるんですが、反面、単純に文字として受け取るときに変換が必要です。

for(int i=0; i<5; i++){
    string s;
    s = ('A'+i);
    cout<<s<<endl;
}
//---出力
A
B
C
D
E

ポイントはstring変数を用意したあとで、charを代入すること。
string s = char('A'+i);としたいところだけど、コンストラクタの関係とかでエラーになってしまう。1

この他にも、アルファベットの大文字小文字の間隔が32なので変換が簡単にできたりします。
'A'+32とすれば'a'になり、'a'-32とすれば'A'になる。といった具合。

対応一覧

ASCIIコード一覧
10進数 16進数 ASCII
1 0x01 SOH(ヘッダ開始)
2 0x02 STX(テキスト開始)
3 0x03 ETX(テキスト終了)
4 0x04 EOT(転送終了)
5 0x05 ENQ(照会)
6 0x06 ACK(受信確認)
7 0x07 BEL(警告)
8 0x08 BS(後退)
9 0x09 HT(水平タブ)
10 0x0a LF(改行)
11 0x0b VT(垂直タブ)
12 0x0c FF(改頁)
13 0x0d CR(復帰)
14 0x0e SO(シフトアウト)
15 0x0f SI(シフトイン)
16 0x10 DLE(データリンクエスケー プ)
17 0x11 DC1(装置制御1)
18 0x12 DC2(装置制御2)
19 0x13 DC3(装置制御3)
20 0x14 DC4(装置制御4)
21 0x15 NAK(受信失敗)
22 0x16 SYN(同期)
23 0x17 ETB(転送ブロック終了)
24 0x18 CAN(キャンセル)
25 0x19 EM(メディア終了)
26 0x1a SUB(置換)
27 0x1b ESC(エスケープ)
28 0x1c FS(フォーム区切り)
29 0x1d GS(グループ区切り)
30 0x1e RS(レコード区切り)
31 0x1f US(ユニット区切り)
32 0x20 SPC(空白文字)
33 0x21 !
34 0x22 "
35 0x23 #
36 0x24 $
37 0x25 %
38 0x26 &
39 0x27 '
40 0x28 (
41 0x29 )
42 0x2a *
43 0x2b +
44 0x2c ,
45 0x2d -
46 0x2e .
47 0x2f /
48 0x30 0
49 0x31 1
50 0x32 2
51 0x33 3
52 0x34 4
53 0x35 5
54 0x36 6
55 0x37 7
56 0x38 8
57 0x39 9
58 0x3a :
59 0x3b ;
60 0x3c <
61 0x3d =
62 0x3e >
63 0x3f ?
64 0x40 @
65 0x41 A
66 0x42 B
67 0x43 C
68 0x44 D
69 0x45 E
70 0x46 F
71 0x47 G
72 0x48 H
73 0x49 I
74 0x4a J
75 0x4b K
76 0x4c L
77 0x4d M
78 0x4e N
79 0x4f O
80 0x50 P
81 0x51 Q
82 0x52 R
83 0x53 S
84 0x54 T
85 0x55 U
86 0x56 V
87 0x57 W
88 0x58 X
89 0x59 Y
90 0x5a Z
91 0x5b [
92 0x5c \
93 0x5d ]
94 0x5e ^
95 0x5f _
96 0x60 `
97 0x61 a
98 0x62 b
99 0x63 c
100 0x64 d
101 0x65 e
102 0x66 f
103 0x67 g
104 0x68 h
105 0x69 i
106 0x6a j
107 0x6b k
108 0x6c l
109 0x6d m
110 0x6e n
111 0x6f o
112 0x70 p
113 0x71 q
114 0x72 r
115 0x73 s
116 0x74 t
117 0x75 u
118 0x76 v
119 0x77 w
120 0x78 x
121 0x79 y
122 0x7a z
123 0x7b {
124 0x7c
125 0x7d }
126 0x7e ~
127 0x7f DEL(削除)

openCV3/4のメモ

openCV3/4のメモ

要約

openCv4をopenframeworksで使うまでの手順。
プロジェクトの生成については、ほかサイトで見なかった簡単な方法をメモ。
めちゃ雑記です。

概要

oFでopenCV3とか4とか使ってみます。
この記事この記事にそって進めてみる。
opencv4でないといけないことは特にないです。ただただBackgroundSubtractorを試してみたかった。
後日また雑な記事かきます。テストの動画だけ貼っときます。なにかのための証拠。

環境とりあえずMac

openCVのinstall

まずはopenCV3 or 4のインストール。
※ 基本最新で上書きされるっぽい。3,4を共存させる方法もあるらしいが、自分は openCv4.1.0でこれといって不具合はないので、opencv4のみになっています。

brew tap homebrew/scienceは使えなくなったらしい。参考
そのため brew tap brewsci/science こちらのコマンドで環境アップデート。

  • opencv3の場合
    brew install openCV3で入れる。
  • opencv4の場合
    opencv4についてはこちらが詳しい。
    brew upgrade opencv でopenCV4(最新版 ex: 4.1.0)を入れる。
途中xcodeのコマンドラインをインストールしてね的なエラーが出たので、xcode-select --installをして、再度upgradeかけると、エラーなく無事完了した。  
過去に入れた気がするのにと思っていたけど、どうもOSをアップグレードすると再度入れる必要があるらしい。  

普通にすすめると、たいていは/usr/local/Cellar/opencv/が更新されるはず。

Xcodeで新規プロジェクト作成

色んなサイトでは以下の方法があげられていたが、パス間違える可能性があったり、記入が面倒だったりなので、個人的にはおすすめじゃない。

紹介されていたプロジェクト生成方法

open
  1. Project.xcconfigでOPENCV_PATHを設定 パスは適宜変えてください。
//OpenCV3
OPENCV_PATH = /usr/local/Cellar/opencv/3.4.1_2
//OpenCV4
OPENCV_PATH = /usr/local/Cellar/opencv/4.1.0_2  
  1. BuildSettingsのHeader Search PathsにOpenCVのインクルードパスを追加
    $(OPENCV_PATH)/include/opencv4
  2. Build SettingsのOther Linker Flagsに必要なdlybを追加
    ここが面倒、、

openCV4をインストールすると、libフォルダにdylib以外に.aファイルもありました。
これらおそらく中身は同じですが、動的ライブラリか、静的ライブラリかの違いがあります。  
こちらでは動的のほうがファイルサイズ小さく、使用メモリも少なくできるっぽい。
dylibを追加するのが面倒な場合は、
.aファイルをGeneralのLinked Frameworks and Librariesにドラッグドロップしても起動可能です。

(たぶんProject.xcconfigのOTHER_LDFLAGSこのあたりの設定でどうにかなるのだけど、、)

#include <opencv2/core.hpp>ここでリンク貼れてないよってエラー出たけど、単純にheader search pathに$(OPENCV_PATH)/includeを入れてないのが原因でした。

おすすめの生成方法

ProjectGeneratorでプロジェクトを作り、

  1. プロジェクトのSearchPaths > HeaderSearchPathsに/usr/local/Cellar/opencv/4.1.0_2/include/opencv4 を追加。(パスは適宜変更してください。)
  2. /usr/local/Cellar/opencv/4.1.0_2/libから必要なdylibを General>LinkedFrameworks and Libraries にドラッグドロップで追加

どのヘッダ呼び出すときにどのlibが必要になるのか、どこを見ればいいんだろう。。。今の所勘で追加しています。。。
このやり方が簡単安定な気がする。Debug/Releaseで変更の必要ない?
紹介されていたプロジェクト生成方法だと必要かもだけど。


画像は適当に追加したのでごちゃっとしています。どうやら.aの静的ライブラリよりは、.dylibなど動的ライブラリのほうが実行ファイルが軽く、メモリの消費を抑えられるとかどうとか。。。

ofxCvとの連携と利用

oFでopenCVを扱う際に、関数群を使いやすくまとめてくれているofxCvを使うとめっちゃ便利。

ProjectGeneratorでofxCvのみ追加してプロジェクト生成。
あとは、上の1.2.を同様に。
なんかもしかしたら、もうちょうっと設定必要だったかも。わすれてもうた。


おまけめも

ofxOpenCvDnnSegmentation など

やはりどこにでも先人がいるもので、馬場先生のofxOpenCvDnnSegmentationがあった。openCVのdnnライブラリをいろいろまとめてらっしゃる。

配布されていたopencv2.aでうまくいかなかったので、自分でメイクしてみる。参考

が、原因はどうもそこではなかった。ので、makeの手順は隠す。

makeの手順
  1. python build_framework.py osxを実行するが、python3ではうまくいかないみたい。
    自分の場合は python2 build_framework.py osc とするとうまくいった。
    python -Vでバージョンを確認したり、which python, which python2でpythonの2.7以上が使われているか確認するとよさそう。
    参考1 参考2

エラー(returned non-zero exit status 65)について
** BUILD FAILED **

The following build commands failed:
    CompileC /Users/hiraoshugo/openCV/opencv-4.1.0/platforms/osx/osx/build/build-x86_64-macosx/modules/world/OpenCV.build/Release/opencv_world.build/Objects-normal/x86_64/opencl_kernels_video.o /Users/hiraoshugo/openCV/opencv-4.1.0/platforms/osx/osx/build/build-x86_64-macosx/modules/world/opencl_kernels_video.cpp normal x86_64 c++ com.apple.compilers.llvm.clang.1_0.compiler
(1 failure)
============================================================
ERROR: Command '['xcodebuild', 'MACOSX_DEPLOYMENT_TARGET=10.12', 'ARCHS=x86_64', '-sdk', 'macosx', '-configuration', 'Release', '-parallelizeTargets', '-jobs', '4', '-target', 'ALL_BUILD', 'build']' returned non-zero exit status 65

こんなエラーでた。どうやらcmakeのバージョン(3.10.2)がダメらしい。参考
てわけで、cmakeのupgrade

cmake --version
// cmake version 3.10.2
brew upgrade cmake
// .....
cmake --version
// cmake version 3.15.2
python2 build_framework.py osx
// .....

  1. python build_framework.py –contrib <opencv_contribへのパス> osx

そんなこんな。。

結論、こちらのように#include "opencv2/imgproc/imgproc_c.h"をofxCvのWrappers.hに追加した。

modelデータは以下から直接落とした。
http://dl.caffe.berkeleyvision.org/fcn8s-heavy-pascal.caffemodel


最近いろんな出会いがあって楽しい。特に音楽やってる人とよく出会う。
春よりも春らしい。

明日は学生CGコンテスト25周年のパーティーにいってきます。
夏がもうすぐ終わるからね。季節の変わり目。春の訪れ。
秋はいずこへ。