おもちゃラボ

Unityで遊びを作っていきます

【Unity】WebCamTextureで写真撮影

画面をタップしたときにパシャっと写真撮影し、撮影画像をPlaneなどに貼って表示するというのが意外と大変だったので、その手順をまとめました。

f:id:nn_hokuson:20211009190337p:plain:w300

写真撮影する流れ

画面がタップされてからカメラを起動→撮影とすると時間がかかってしまうため、基本的にカメラはバックグラウンドで起動しておき、タップされたときにカメラに映っている映像を取得する、という流れになります。

これをふまえて、写真撮影をする流れは次のようになります。

  1. カメラの映像をWebCamTextureで取得
  2. 取得した映像をRawImageで表示
  3. タップされたらRawImageの映像をTexture2Dに変換
  4. マテリアルのテクスチャに設定

図にするとこんな感じになります。

f:id:nn_hokuson:20211009184005p:plain:w500

プログラムを作る

WebCamControllerという名前でスクリプトを作成して、次のプログラムを入力してください。

using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(RawImage))]
public class WebCamController : MonoBehaviour
{
    WebCamTexture webcamTexture;
    RawImage rawImage;

    void Start()
    {
        WebCamDevice[] devices = WebCamTexture.devices;
        webcamTexture = new WebCamTexture(devices[0].name,1920, 1080, 30);
        this.rawImage = GetComponent<RawImage>();
        this.rawImage.texture = webcamTexture;
        this.rawImage.enabled = false;
        webcamTexture.Play();
    }

    void TakeShot()
    {
        Texture tex = this.rawImage.texture;
        int w = tex.width;
        int h = tex.height;

        RenderTexture currentRT = RenderTexture.active;
        RenderTexture rt = new RenderTexture(w, h, 32);

        Graphics.Blit(tex, rt);
        RenderTexture.active = rt;

        Texture2D result = new Texture2D(w, h, TextureFormat.RGBA32, false);
        result.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
        result.Apply();
        RenderTexture.active = currentRT;

        GetComponent<MeshRenderer>().material.mainTexture = result;
    }
 
    private void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            TakeShot();
        }
    }
}

Startメソッドの中では、WebCamTextureでカメラ映像を取得し、それをRawImageに設定しています。

具体的には、まずWebCamTexture.devicesでPCに接続されているカメラを取得し、カメラ名からWebCamTextureを作成します。作成したWebCamTexture をRawImageコンポーネントのテクスチャに設定することで、RawImageにカメラからの映像が表示されます。今回は写真を撮影したときにのみ画面表示を行いたいので、ここではRawImageのenableをfalseにしています。

f:id:nn_hokuson:20211009184151p:plain:w500

画面がタップされるとTakeShotメソッドが呼ばれます。TakeShotメソッドではRawImageの映像をTexture2Dに変換しています。

RawImageからTexture2Dへは、単純にキャストするだけでは変換できません。いったんRawImageをRenderTextureに書き出し、それをReadPixelsメソッドでTexture2Dに書き込んでいます。

f:id:nn_hokuson:20211009184231p:plain:w500

最後に、PlaneオブジェクトのMeshRendererコンポーネントを通してマテリアルを取得し、作成したTexture2D型の画像をマテリアルのmainTextureに設定しています。

f:id:nn_hokuson:20211009185629p:plain:w500

Planeに設定する

ヒエラルキーウインドウの「+」をクリックして「3D Object」→「Plane」を選択してください。シーンビューにPlaneが表示されます。

作成したPlaneにWebCamControllerスクリプトドラッグ&ドロップしてアタッチします。スクリプト中でRequireComponent(typeof(RawImage))としているため、RawImageコンポーネントも自動的にアタッチされます。

f:id:nn_hokuson:20211009185346j:plain

実行してみる

ここまでできたら実行してみてください。画面をクリックするとクリックした時点での写真が表示されます。

【Arduino】シリアルで出力した値をグラフ化する

Arduinoを使っているとシリアルで出力した値をグラフ化したいときがあります。
Arduinoエディタにはこんなときに使えるシリアルプロッタが標準で付属しています。
ここではシリアルプロッタの使い方を紹介します。

f:id:nn_hokuson:20211002152108p:plain:w600

目次は次のとおりです。

sin波を出力してみる

まずはシリアル通信でsin波を出力するプログラムを作ってください。

float t = 0;

void setup() 
{
  Serial.begin(19200);
}

void loop() {
  t += 0.05;
  int p = 50 * sin(t) + 50;

  String str = String(p);
  Serial.println(str);
}

setupメソッドの中で通信レート19200bpsに設定しています。また、loopメソッドでsin波の値を毎フレームごとシリアル通信で出力しています。

プログラムが作れたら、Arduinoに書き込んでおきましょう。

シリアルプロッタで表示

スケッチをArduinoに書き込めたら、いよいよシリアルプロッタを使ってグラフを表示してみましょう。

メニューバーからツール→シリアルプロッタを選択してください。

f:id:nn_hokuson:20211002153412p:plain:w300

シリアルプロッタの画面が表示されたら、画面左下のボーレートを19200に設定します。すると次のようなSin波が表示されるはずです。

f:id:nn_hokuson:20211002151544p:plain:w600

シリアルプロッタで複数の値を出力する

シリアルプロッタで複数のグラフを描画したい場合は、次のように、それぞれのグラフの値を「,(コンマ)」で区切って出力します。

Serial.println(値, 値, 値);

ここではsin波とcos波の2つのグラフをシリアルプロッタで表示してみます。プログラムを次のように変更してください。

float t = 0;

void setup() 
{
  Serial.begin(19200);
}

void loop() {
  t += 0.05;
  int p = 50 * sin(t) + 80;
  int q = 80 * cos(t*2) + 80;

  String str = String(p) + "," + String(q);
  Serial.println(str);
}

プログラムが作れたら、Arduinoに書き込んでからシリアルプロッタで表示を確認してみてください。次のように2つのグラフが表示されているはずです。

f:id:nn_hokuson:20211002152108p:plain:w600

凡例も表示したい

シリアルプロッタの表示に凡例も合わせて表示したい場合には、次のようなフォーマットでシリアル出力します。

Serial.println(凡例1:値1, 凡例2:値2, 凡例3:値3);

ここでは、それぞれのグラフに「sin」「cos」という凡例をつけて表示してみます。次のプログラムを入力してください。

float t = 0;

void setup() 
{
  Serial.begin(19200);
}

void loop() {
  t += 0.05;
  int p = 50 * sin(t) + 80;
  int q = 80 * cos(t*2) + 80;

  String str = "sin:"+String(p) + "," +"cos:" + String(q);
  Serial.println(str);
}

Arduinoにプログラムが書き込めたら、シリアルプロッタで表示を確認してみてください。シリアルプロッタの画面左上に正しく凡例が表示されていると思います。

f:id:nn_hokuson:20211002153555p:plain:w350

まとめ

Aruduinoでシリアル出力した値をグラフ化シたい場合には、Arduinoエディタに標準で付属しているシリアルプロッタが便利です。

超おすすめ!プラスアクア給水器 

この記事では、猫がよく水を飲んでくれる給水器
「プラスアクア」の紹介を
しています!

内容は次のとおりです

脱・給水器難民!

猫の水飲みを探し求めて三千里。。
いろんな種類の器(給水器)を試してきました。

猫壱の器だったり、

他社の自動給水器だったり、

色々試してはみたのですが、
どうも、猫が水をあまり飲んでくれません

猫は水を飲まないと尿路結石になりやすく
なってしまう
ので、できるだけ頻繁に
水を飲んでほしいのです。

そんな給水器難民だった私の目に止まったのが
「うちのこエレクトリック」の「プラスアクア」

これ、本当におすすめです!
2021年買ってよかったものリストのトップですねー笑

なにがそんなに良いのか?
説明していきたいと思います。

猫が頻繁に水を飲んでくれる

もちろん、これがオススメ理由TOPです!

プラスアクアは常に水が流れているので
猫が通りがかったときに
「気になってクンクン」→「そのまま水飲みへ移行」
という確率がめっちゃ高いです!

  1. 水が流れていること
  2. 静かなこと
  3. 水を飲むときの高さが最適なこと

などもあり、猫が水を飲む頻度は確実に上がりました!
とにかく猫のために考えつくされた
設計になっています。すごいぞプラスアクア!

プラスアクアはとにかく静か!

以前に使ってみた自動給水器は
ブーンっという音(モータで水を汲み上げる)が
ずっと鳴っていました。

それに比べると、このプラスアクアは
めちゃくちゃ静か!!
静かというか、耳を近づけても
ほとんどモータ音は聞こえません。

どちらかというと水の流れる音のほうが聞こえる(笑)

しかも無響室での測定までしてる。
無響室は電波暗室の音バージョンですね。
電気製品を作っている大手の企業をのぞいて
ここまでやっている製品はなかなか知りません!

f:id:nn_hokuson:20210918214219j:plain
(引用:https://petelect.jp/shop/products/detail/37

エンジニアからすると、これは信用度爆アガリです
なかなかここまでやりませんよ〜
すごいぞプラスアクア!!

お手入れのこともしっかり考えられてる

自動給水器のお手入れって、
思っている以上に大変なんです。

すぐにヌメヌメになるし、
なかなかヌメヌメ取れないし、
お掃除してもすぐにヌメヌメになるし。。

そこで、このプラスアクアです!
ヌメヌメの諸悪の根源であるモータの中まで
ちゃんとお掃除できる
ようになってるんです。

モータの軸と羽まで分解できるようになってる
こだわり仕様。タミヤかよ!

f:id:nn_hokuson:20210918213803j:plain:w245 f:id:nn_hokuson:20210918213812j:plain:w400

最近、お掃除が便利になるブラシも発売されて
鬼に金棒、弁慶に薙刀、猫に鰹節(違う)です!

(内緒なんですが、100均のブラシでええやろ、
と思って買ってみたら、全然あかんかったです、
良い子はちゃんと純正を買いましょう

意外と便利なプラスアクアの無線給電

うちのこエレクトリックのページには
「プラスアクアでは無線給電ができます!」と書かれています。

プラスアクアを買うまでは「新しいモノ好きのエンジニアが
気分でつけたんちゃうん〜??」と疑ってましたが
全然そんなことなかったですすみませんすみません。

猫の自動給水器って、家のどこかに設置するじゃないですか。
従来の自動給水器だと、洗おうとしたとき、キッチンまで運ぶために
コンセントを抜かなければ
だめだったんですね。
しかもコンセントをブラブラさせて洗わなければいけない。
これが結構なストレスでした。

プラスアクアだと無線給電のおかげで、
電源ケーブルがついた最外のケースと、モータが入った内側のケースが
別れているんです。なので、洗いたいときは内側のケースだけを
キッチンに持っていくだけ
でOK。すばらしい。技術の勝利です。

f:id:nn_hokuson:20210918213947j:plain:w500

まとめ

ということで、めちゃくちゃオススメなプラスアクア!
猫の水飲みを探されている方はぜひ購入を検討してみてください。

上にも書きましたけど、
水を飲まないと尿路結石になる可能性が
高くなってしまうので、ぜひ健康なうちから
対策
してあげると良いと思います!

ちなみに・・猫壱の器と猫との格闘は
こちらの記事に書いています!
nn-hokuson.hatenablog.com