2016/5/14 【OpenCVSharp,c#】AndroidをWebカメラ代わりにして画像処理
画像処理をしたいときによく使われるライブラリとしてOpenCVというものがあるのですが、
それをc#で使えるような形にしたOpenCVSharpというものがあるそうです。
そのOpenCVSharpとWebカメラを使って何か画像処理をしたいなぁと思ったものの、
Webカメラは持ってないのでどうしようかなという感じだったのですが、
DroidCamというAndroidをWebカメラの代わりとして使うことが出来るソフトを見つけました。
ですので、今回はこの2つを使って簡単な画像処理をやってみました。
使っているPCのスペックの問題でガタガタな動画になってしまっていますが、
Androidで撮っている映像をリアルタイムでPCに送り、エッジ検出などをさせています。
作り方を以下に書いていきます。
開発環境は、windows7とVisual Studio Express 2013です!
下準備
OpenCVSharpを開発した方のブログを参考にして入れました。
DroidCamはパソコンとスマホの両方にインストールする必要があるのですが、
パソコンの方は公式サイトから入手できます。
今のところはClient v6.0.0とClient v5.0.1の2つのバージョンが出ているみたいです。
こちらのサイトの環境では v5.0.1 しか動かなかったようですが、
自分の環境では逆に v6.0.0 だけが動きました。この辺りは各自で確かめてみて下さい。
スマホの方はGoogle Playで探したら出てきました。
無料版と有料版(500円)があるみたいなので、無料版の方を入れてみました。
Wi-Fiで繋いでもUSBケーブルで繋いでも良いみたいなので、今回はWi-Fiで繋いでみます。
スマホをWi-Fiに繋いだ状態でDroidCamを開いて、
下のように繋がっているWi-Fiの情報が出てきたらスマホ側の準備は終了です。
次にパソコン側でDroidCamを起動して、下のような画面が出てくるので
スマホの画面に出ていたWi-FiのIPを入力してstartボタンを押せば
カメラで読み取った映像が出てきます。
下準備はこれで完了です!
2016/12/26 追記
Webカメラが使えなくなることがあるようです。
思わぬところに落とし穴が……^^;
参考URL:https://answers.microsoft.com/ja-jp/windows/forum/windows_10-hardware/windows-10-%E3%81%A7-web/a6357cee-7bf7-447b-a7f5-00a984837d94
プログラム
ここからはプログラムを組んでいきます。
フォームの見た目は下のような感じで、
送られた映像をそのまま映すモード、ラプラシアンフィルタによるエッジ検出モード、
ネガポジ変換モードの3つを用意して、ボタンで自由に切り替えられるようにしてみます。
LabelとButtonは元からあるコントロールですが、PictureBoxIplというのは
OpenCVSharpで扱うIplImageという画像の型をPictureBoxでも扱えるようにしたコントロールです。
開発者の方のブログを参考に導入しました。
そうして出来たプログラムが下のような感じです。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using OpenCvSharp; namespace testCSharp { public partial class Form1 : Form { BackgroundWorker worker; public Form1() { InitializeComponent(); worker = new BackgroundWorker(); // 非同期をキャンセルさせる worker.WorkerSupportsCancellation = true; // ProgressChangedイベントを発生させるようにする worker.WorkerReportsProgress = true; // ReportProgressメソッドで呼ばれるProgressChangedのイベントハンドラを追加 worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged); // RunWorkerAsyncメソッドで呼ばれるDoWorkに、 // 別スレッドでUSBカメラの画像を取得し続けるイベントハンドラを追加 worker.DoWork += new DoWorkEventHandler(worker_DoWork); } private void worker_DoWork(object sender, DoWorkEventArgs e) { // カメラからの映像を受け取る using (var capture = Cv.CreateCameraCapture(CaptureDevice.Any)) { IplImage frame; while (true) { frame = Cv.QueryFrame(capture); // 新しい画像を取得したので、 // ReportProgressメソッドを使って、ProgressChangedイベントを発生させる worker.ReportProgress(0, frame); } } } private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { // frameがe.UserStateプロパティにセットされて渡されてくる IplImage image = (IplImage)e.UserState; CvSize size = new CvSize(320, 240); IplImage reImage = new IplImage(size, image.Depth, image.NChannels); Cv.Resize(image, reImage, Interpolation.NearestNeighbor); switch (label1.Text) { case "negaposi": Cv.Not(reImage, reImage); break; case "laplace": Cv.Laplace(reImage, reImage); break; } pictureBoxIpl1.ImageIpl = reImage; } private void Form1_Load(object sender, EventArgs e) { // DoWorkイベントハンドラの実行を開始 worker.RunWorkerAsync(); } private void defaultButton_Click(object sender, EventArgs e) { label1.Text = "default"; } private void laplaceButton_Click(object sender, EventArgs e) { label1.Text = "laplace"; } private void negaposiButton_Click(object sender, EventArgs e) { label1.Text = "negaposi"; } } }
3つのどれかのボタンが押されるとlabel1のtextの値が変化し、
その値によって画面の処理を変えるというものです。
BackGroundWorkerというクラスは今回始めて使ってみたのですが、
このクラスを使用することで、フォームのボタンの操作と映像を受け取る処理を
別スレッドで行っているようです。
こちらとこちらのブログが参考になりました。
2016/12/26 追記
という質問を頂いたので、新たにページを作りました。
http://sssignal.web.fc2.com/column/column21.html
この記事の手順通りにOpenCVSharpをインストールされているなら
3行程書くだけで実装できるので、合わせて参考にして頂ければと思います。
2017/1/4 追記
-
Please
- feedly
- hatena bookmark
- Google plus
Share!