LoginSignup
8
7

More than 5 years have passed since last update.

仮想Webカメラでウェブ画面をOpenCVで認識させるまでのメモ

Last updated at Posted at 2016-10-29

一番良いのはVisualStudio2010でコンパイルすることなのか?

詳しく分からないが、VisualStudio2015でコンパイルするとReleaseがコンパイルできない状態に陥ったりした。
この原因としてはWindowsランタイムが更新されているかららしい。
VisualStudio2010でBaseClassesやPushSouceFilterをコンパイルするとあっさりとコンパイルできる。
なのでここではVisualStudio2010を用いてPushSouceFilterのライブラリファイルを作成することにする。

ランタイムとやらが新しいバージョンと古いバージョンでコンパイルしてライブラリファイルを作った場合に、その後にVisualStudio2015などでそのライブラリファイルを利用する時にどう影響するのか?
.libファイルにしてしまえばランタイムの新しい古いは関係ないのか?
知識がなくて不明なのでここは調べる必要あり。

まずはVisualStudio2010を手に入れる

VISUAL STUDIO 2010 EXPRESSと旧版のダウンロード先まとめ http://wolfish.org/blog/p2010042901/というサイトからVisual Studio 2010 Expressをまずダウンロードする。
これを使ってコンパイルまでするのが一番確実。ダウンロードできたらVisualC++2010 Expressを選択。
Microsoft SilverlightとかMicroSoft SQL Server 2008 Express Service Pack1(x64)とかはインストールオプションでチェックを外す。
インストールするファイルは以下のとおり。
VisualStudio2010download.png
VisualStudio2010download2.png

次にSDKversion7.1を手に入れる

VisualStudio2015Communityとかが入ってるとダウンロードができないことがある。面倒だがアンインストールするなりして、これはどうにかするしかない。VisualStudio2015だとReleaseでエラーが出た。

ダウンロード先はMicrosoft Windows SDK for Windows 7 and .NET Framework 4
 https://www.microsoft.com/en-us/download/details.aspx?id=8279

Redistributable PackagesのMicrosoftVisualC++はまずは、インストールしないでおく。
Samplesと・Windows Headers and Librariesに☑を入れる。
※画像と違うので注意。Redistributable PackagesのMicrosoft Visual C++ 2010をインストールしてしまうと、Windows SDK 7.1 用 Microsoft Visual C++ 2010 Service Pack 1 コンパイラ更新プログラムがインストールできなくなる可能性があるので注意。
SDKinstall.png

ここで、C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshowにbaseclassesというフォルダがあり(これがDirectShowのベースとなるDLLを作る元)、C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\filtersにpushsourceというフォルダ(これががデスクトップキャプチャをするPushSourceDesktop.cppの存在場所)あることを確認する。

Windows SDK 7.1 用 Microsoft Visual C++ 2010 Service Pack 1 コンパイラ更新プログラムをインストール

これをインストールしないと、コンパイルするときにx64でコンパイルができない。
Windows SDK 7.1 用 Microsoft Visual C++ 2010 Service Pack 1 コンパイラ更新プログラム https://www.microsoft.com/ja-jp/download/details.aspx?id=4422をダウンロードしてインストール。

まずはbaseclasses.slnのコンパイル

x64でコンパイルするために追加のライブラリディレクトリにアドレスを追加

C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\baseclassesの中のbaseclasses.slnをVisualStudio2010で開く。
変換が必要ですとの注意がでるが、OKでバックアップを取って進む。

コンパイルするとWarningが出るかもしれないがそれは無視する。2重宣言みたいなやつ。

64bitでコンパイルするためには、下記のようにSDKv7.1のLib\x64を追加のライブラリへ記入する。
Debugの時はstrmbasd.libが、Releaseの時はstrmbase.libが生成されるので、下記のように出力ファイルにあらかじめ記入してもOK。

追加のライブラリディレクトリプロパティ.png
ここまででBaseClassesのコンパイル終了。

pushsource.slnのコンパイル

x64の場合だけ注意が必要で、プロジェクトのプロパティのリンカーの全般の追加のライブラリディレクトリに同じようにC:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\x64を追加する必要がある。
これをしないとx64ではコンパイルできない。

ここまででDLLの作成は終了 動くかどうか確かめる

ここで動くかどうか確かめてみる。必要なのはGraphEditというexeファイル。
Microsoftは再配布を行っていないとのことだが、ダウンロードはここ(GraphEdit 非公式ガイド)からできる。

まず、登録するファイルがc:\aaaa.dllの場合、

  • ActiveX.DLLの登録 C:>regsvr32 c:\aaaa.dll
  • ActiveX.DLLの削除 C:>regsvr32 /u c:\aaaa.dll

それかcdでdllファイルがあるフォルダまで飛んでから、regsvr32 PushSource.dllを実行する。
そうすると、GraphEditのDirectShowにPushSourceDesktopFilterが追加される。
GraphEditの操作方法は省略。いじりまくると分かる。とりあえずこれでフィルターは完成。

OpenCVのソースについて

cap_dshow.cpp

今のところこのファイルしか分からないが、RendererFilterを作っているだろうと思われる部分が見受けられた。

cap_dshow.cpp
//以下使用例
/*
    //videoInputオブジェクトを作成する
    videoInput VI;

    //利用可能なデバイスのリストをプリントし、見つかったデバイス番号を返す
    int numDevices = VI.listDevices();

    int device1 = 0;  //this could be any deviceID that shows up in listDevices
    int device2 = 1;  //this could be any deviceID that shows up in listDevices

    //もし異なるフレームレートでキャプチャしたければ(デフォルトは30)
    //このfpsを得られなければ、下のコードをここに書く。
    //VI.setIdealFramerate(dev, 60);

    //setup the first device - there are a number of options:

    VI.setupDevice(device1);                           //setup the first device with the default settings
    //VI.setupDevice(device1, VI_COMPOSITE);           //or setup device with specific connection type
    //VI.setupDevice(device1, 320, 240);               //or setup device with specified video size
    //VI.setupDevice(device1, 320, 240, VI_COMPOSITE); //or setup device with video size and connection type

    //VI.setFormat(device1, VI_NTSC_M);                //if your card doesn't remember what format it should be
                                                       //call this with the appropriate format listed above
                                                       //NOTE: must be called after setupDevice!

    //optionally setup a second (or third, fourth ...) device - same options as above
    VI.setupDevice(device2);

    //As requested width and height can not always be accomodated
    //make sure to check the size once the device is setup

    int width   = VI.getWidth(device1);
    int height  = VI.getHeight(device1);
    int size    = VI.getSize(device1);

    unsigned char * yourBuffer1 = new unsigned char[size];
    unsigned char * yourBuffer2 = new unsigned char[size];

    //to get the data from the device first check if the data is new
    if(VI.isFrameNew(device1)){
        VI.getPixels(device1, yourBuffer1, false, false);   //fills pixels as a BGR (for openCV) unsigned char array - no flipping
        VI.getPixels(device1, yourBuffer2, true, true);     //fills pixels as a RGB (for openGL) unsigned char array - flipping!
    }

    //same applies to device2 etc

    //to get a settings dialog for the device
    VI.showSettingsWindow(device1);


    //Shut down devices properly
    VI.stopDevice(device1);
    VI.stopDevice(device2);

このソースコードを見る限り、まずはvideoInput::listDevices関数を調べてみる必要がある。
ここでnumDevicesとしてデバイス番号が見つかれば映像がキャプチャされることになるのだろう。

videoInput::listDevices関数

余談 SCFHというニコ生配信用フリーウェア

ニコ生のゲーム配信ソフトにSCFHというフリーウェアがある。これを使ってみた。
ダウンロードして実行してみると、OpenCVで認識ができた。これを使って仮想Webカメラとしてモニターをキャプチャすることはできるのだが、なんか気持ち悪いのでちゃんとコーディングすることを目指す。

突如終了

Wind32APIを用いた方が良いとの話をもらったので、ここでDirectShowを用いた実装はひとまず中止する。
Win32APIで実装できたらまた記事に載せる。

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7