へっぽこ元ロボコニスト

ロボコンに燃え尽きた自分が日々の出来事を書くだけのブログです

2019/5/2(OpenCVでWebカメラの画像をモノクロにする)

GW中に高校の友達とご飯を食べに行ったときに,意外な進路をたどっていたので驚いた


前回の記事です
mozyanari.hatenablog.com

前回は自分の顔を判定する機能を実装しましたがOpenCVが動くのを確認しただけなので,次はWebカメラの画像をモノクロにしてUnity上で
表示します

今回参考にしたのは以下のページです

ssssota.hatenablog.com


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OpenCvSharp;

public class web_camera : MonoBehaviour {
    [SerializeField] private int m_WebCamIndex = 1;
    private Texture2D texture2D;
    private VideoCapture videoCapture;
    private Mat mat;
    private Mat grey;

	// Use this for initialization
	void Start () {
        videoCapture = new VideoCapture(m_WebCamIndex);
        texture2D = new Texture2D(videoCapture.FrameWidth, videoCapture.FrameHeight, TextureFormat.RGB24, false);
        GetComponent<Renderer>().material.mainTexture = texture2D;
        mat = new Mat();
        grey = new Mat();
	}
	
	// Update is called once per frame
	void Update () {
        videoCapture.Read(mat);
        Cv2.CvtColor(mat, grey, ColorConversionCodes.BGR2GRAY);
        texture2D.LoadImage(grey.ImEncode());
	}

    private void OnDestroy()
    {
        videoCapture.Dispose();
        videoCapture = null;
    }
}

startの部分

videoCapture = new VideoCapture(m_WebCamIndex);

どのWebカメラを起動するかをここで選択して,カメラに関する情報を変数videoCaptureで取得します
自分のノートPCは内臓カメラがあったので,ここの引数は1だと内蔵カメラ,2だとUSB接続したカメラになります

texture2D = new Texture2D(videoCapture.FrameWidth, videoCapture.FrameHeight, TextureFormat.RGB24, false);

カメラ画像に関する情報をtexture2Dで保持します
1つ目の引数で画像の横幅,2つ目で画像の縦幅を入力します
ここの引数をカメラの性能が分かっているなら決め打ちでもいいかもしれませんが,基本的にvideoCaptureから取得したほうが便利です
3つ目と4つ目はいまいち理解していません

GetComponent<Renderer>().material.mainTexture = texture2D;

これを実行することでUnity上でアタッチしているオブジェクトにtexture2Dを張り付けることを示すことができます
今回はPlaneのオブジェクトにアタッチする予定です

mat = new Mat();
grey = new Mat();

参考にしたページでは書いていませんでしたが,自分の場合これを書いていないとmatが常にnullで動きませんでした


upadateの部分

videoCapture.Read(mat);

videoCaptureにはwebカメラのデータが常に更新されて保存されているので,mat形式で書きだします

Cv2.CvtColor(mat, grey, ColorConversionCodes.BGR2GRAY);

この部分がOpenCVの機能を使った部分で,変数matに入っているカメラ画像をモノクロ化(グレースケール化)して変数greyに格納しています

texture2D.LoadImage(grey.ImEncode());

texture2Dはstartの部分でUnityのオブジェクトにアタッチされていることを示されているので,texture2Dに変数greyを入力するだけで勝手に更新されてUnity上で表示してくれます
ただ,greyはmat形式なのでImEncodeを使ってpngに変換してから入力します


OnDestroyの部分
この部分は参考にしたページには書いていましたが,自分の場合Unity上で実行した後この部分でエラーが発生したのでなくてもいいのかもしれません


これをUnityのPlaneにアタッチすれば,Plane上にwebカメラの画像が出てくるはずです