画像処理ってなんかかっこよくってやってみたかっただけなんです(小並感)
備忘録兼ねてどんな順番で処理が進んで行くのか簡単にまとめました。
環境
- macOS Sierra バージョン10.12.6
- Unity 2018.2.5.f1 (C#で書きます)
使ったアセット
FaceTrackerExample
OpenCVForUnity
シーン上に用意するもの
- MainCamera
- EventSystem
- Quad
今回はアセット「OpenCVForUnity」のサンプルシーン、ThinPlateSplineShapeTransformerExample.unityをそのまま使って作成したお試しです。
シーンにあるものもほとんどそのままですが、参考までにQuadのinspectorの画像を載せておきます。くっついてるスクリプトは次で説明します。
画像処理の手順
簡単なコードの説明
- 画像/映像を読み込む
- 読み込んだ画像/映像のテクスチャをマットにコピー
- 画像処理用のマット画像をつくる
- グレースケール用のマットを作って、RGBA画像をグレースクケールに変換
- 画像の平坦化
- グレースケールのマットをテクスチャに変換
ここまできてようやく自分のやりたい処理がかけるみたいです。
処理が終わったら描画です。あとちょっと。
- 描画用の2Dのテクスチャを用意して、そこにマットをテクスチャに変換したものを入れる
- これを描画させたいゲームオブジェクトにレンダリングして終わり!!
長いですね...
さっそくやってみよう
最初に下の1行を入れておいてくださいね。
using OpenCVForUnity;
今回はWebCamを使ってリアルタイムで処理と描画をしてみました。(やりたい処理によってはびっくりするほど重たくなるので注意してください)
次、わーっといきます。私も完全に理解できてなくてこう書いたらできた!って感じなのでところどころよくわかってないところあります...申し訳ない...
WebCamTexture webCamTexture;
// もしWebCamでやりたかったらStart()でWebCamを起動します。
// 画像を読み込む場合は同じくStart()でテクスチャに画像を読み込ませれば以下同じように動きます。
void Start (){
WebCamDevice[] devices = WebCamTexture.devices;
webCamTexture = new WebCamTexture(devices[0].name, Width, Height, FPS);
GetComponent<Renderer>().material.mainTexture = webCamTexture;
webCamTexture.Play ();
}
void Update (){
// テクスチャをマットにコピー
Mat origin = new Mat(webCamTexture.height, webCamTexture.width, CvType.CV_8UC4);
Utils.webCamTextureToMat(webCamTexture, origin);
//画像処理用Mat画像
Mat mat_proc = new Mat(origin.rows(), origin.cols(), CvType.CV_8UC1);
Imgproc.cvtColor(origin, mat_proc, Imgproc.COLOR_RGBA2GRAY);
// グレースケールにする処理
// グレイスケールMat
Mat gray = new Mat (origin.rows (), origin.cols (), CvType.CV_8UC1);
// RGBA画像をグレイスケールに変換
Imgproc.cvtColor (origin, gray, Imgproc.COLOR_RGBA2GRAY);
// 画像の平坦化
Imgproc.equalizeHist (gray, gray);
// グレイスケールのMatをテクスチャに変換
Texture2D texture_out = new Texture2D (gray.cols (), gray.rows (), TextureFormat.RGBA32, false);
Utils.setDebugMode (true);
Utils.texture2DToMat (texture_out, gray);
/*
ここに自分のやりたい処理を書きます
*/
// 下で使ってるresはやりたい処理済みのデータが入ったMatです。
Texture2D texture = new Texture2D (res.cols (), res.rows (), TextureFormat.RGBA32, false);
Utils.matToTexture2D (res, texture);
// 描画したいゲームオブジェクトにレンダリング
gameObject.GetComponent<Renderer> ().material.mainTexture = texture;
Utils.setDebugMode (false);
}
今回作った試作は完全にアセットに入ってるサンプルシーンに頼りきってるので、新しく作ったシーンにこれを丸々コピペしたらどうなるか私にもわからないです(きっとどこかから引っ張ってきてるメソッドがエラー吐きます)
きっと色々間違ってるところもあると思います。何かわかる方いらっしゃいましたらコメント等いただけるとありがたいです。
ここまで読んでいただいてありがとうございました! それでは!