<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>橋本商会 &#187; VS2008</title>
	<atom:link href="http://shokai.org/blog/archives/tag/vs2008/feed" rel="self" type="application/rss+xml" />
	<link>http://shokai.org/blog</link>
	<description>なんか作ったりした記録を忘れないうちに書くblog</description>
	<lastBuildDate>Sun, 20 May 2012 10:50:20 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com/" />
			<item>
		<title>Playstation EyeをOpenCVで使う</title>
		<link>http://shokai.org/blog/archives/4594</link>
		<comments>http://shokai.org/blog/archives/4594#comments</comments>
		<pubDate>Tue, 07 Jul 2009 06:12:12 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[OpenCV]]></category>
		<category><![CDATA[PS3Eye]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[VS2008]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=4594</guid>
		<description><![CDATA[プレステ3のカメラをWindowsのVisualStudio2008環境のOpenCVで使う方法をまとめる。 ゲーム用の画像解析用のカメラなので 解像度は640&#215;480もしくは320&#215;240と高くは無 [...]]]></description>
			<content:encoded><![CDATA[<p>
プレステ3のカメラをWindowsのVisualStudio2008環境のOpenCVで使う方法をまとめる。<br />
<br />
ゲーム用の画像解析用のカメラなので<br />
<ul>
<li>解像度は640&#215;480もしくは320&#215;240と高くは無いが、320&#215;240の時は最大120FPSでキャプチャできる</li>
<li>レンズのモードを切り替える事が出来て、かなり広角になる</li>
<li>オートフォーカスが無いので画像処理しやすい</li>
<li>ゲインやホワイトバランスの調整が高速</li>
<li>4000円前後で手に入る。性能の割に安い</li>
</ul>
などの利点がある。また、後述するWindows用のドライバを使うとゲインやホワイトバランスを任意の値にしたり、自動調整をオフにしたりできるので画像処理には便利。<br />
<br />
この記事で使ったプログラムは全部<a href="http://shokai.org/projects/opencv-study/">OpenCV勉強リポジトリ</a>にアップロードした。<br />
<br />
<br />
<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B001ANDJSG/shokai-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/41LjeQ5m8%2BL._SL160_.jpg" alt="PLAYSTATION Eye(CEJH-15001)" style="border: none;" /></a></div><div class="amazlet-info" style="float:left;margin-left:15px;line-height:120%"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B001ANDJSG/shokai-22/ref=nosim/" name="amazletlink" target="_blank">PLAYSTATION Eye(CEJH-15001)</a><div class="amazlet-powered-date" style="font-size:7pt;margin-top:5px;font-family:verdana;line-height:120%">posted with <a href="http://www.amazlet.com/browse/ASIN/B001ANDJSG/shokai-22/ref=nosim/" title="PLAYSTATION Eye(CEJH-15001)" target="_blank">amazlet</a> at 09.07.07</div></div><div class="amazlet-detail">ソニー・コンピュータエンタテインメント (2008-07-24)<br />売り上げランキング: 1418<br /></div><div class="amazlet-review" style="margin-top:10px; margin-bottom:10px"><div class="amazlet-review-average" style="margin-bottom:5px">おすすめ度の平均: <img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-4-5.gif" alt="4.5" /></div><img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-3-0.gif" alt="3" /> GAMEはあんまり・・・<br /><img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-3-0.gif" alt="3" /> まぁ、及第点<br /><img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-4-0.gif" alt="4" /> 確実に使用できるＷｅｂカメラ<br /><img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-4-0.gif" alt="4" /> 気になる点を<br /><img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-5-0.gif" alt="5" /> お得！WindowsXP, VISTAでも問題なく使用できましたよ！<br /></div><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B001ANDJSG/shokai-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jp で詳細を見る</a></div></div><div class="amazlet-footer" style="clear: left"></div></div>
<br />
<br />
<br />
■準備<br />
詳しくは<a href="http://d.hatena.ne.jp/shokai/20090611/1244740739">VS2008 OpenCVでPlaystation3 eyeを使う</a>にまとめた。<br />
<br />
Macではmacamを通せば普通のwebcamとして使えるし、<a href="http://mizupc8.bio.mie-u.ac.jp/pukiwiki/index.php?PLAYSTATION%20Eye#uc2b2ffb">LinuxでもgpscaにOV534というPS3Eyeが使っているチップのドライバを入れれば動く</a>らしい<br />
<br />
Windowsの場合、<a href="http://alexpopovich.wordpress.com/2008/10/02/sony-ps3eye-camera-directshow-capture-source-filter/">Alexさんという方が作ったドライバ</a>を入れれば使える。ただし普通のwebcamとして認識は出来ないのでFlashなどからは使えない。<br />
ドライバと一緒にIPS3EyeLib.hが付いてきて、これを通すとDirectShowのFilterとして使えるようになる。<br />
Visual Studio2008のC++でOpenCVを使いたいので、これもプロジェクトに読み込むようにした。<br />
<br />
Visual Studio2008でのOpenCVのセットアップ自体は<a href="http://d.hatena.ne.jp/shokai/20090129/1233241388">VC++2008にOpenCV環境セットアップ、カメラでキャプチャ</a>に書いた。<br />
<br />
<br />
■キャプチャしてみる<br />
IPS3EyeLib.hなどへのパスを通したら、プログラムを書いてみる。<br />
<a href="http://www.atinfinity.info/blog/archives/113">dandelion&#8217;s log ? PS3EyeLibで遊んでみた</a>に書いてあるコードが参考になった。<br />
<br />
作ったのはこれ → <a href="http://d.hatena.ne.jp/shokai/20090706/1246860032">PlayStation3 eyeでキャプチャして表示</a><br />
このプログラムは、<a href="http://d.hatena.ne.jp/shokai/20090706/1246857372">普通のwebcamでキャプチャして表示するだけプログラム</a>のカメラ取得と画像取得データ部分をPS3Eye用に置き換えたもの。比較するとわかりやすいと思う。<br />
<br />
違いは、カメラを取得するのが<br />
<pre class="prettyprint">cvCreateCameraCapture(0);</pre>
の代わりに<br />
<pre class="prettyprint">IPS3EyeLib::Create();</pre>
でカメラを取得するのと、<br />
<pre class="prettyprint">image = cvQueryFrame(capture);</pre>
で画像を取ってこれる所が<br />
<pre class="prettyprint">
PBYTE capBuffer = new BYTE[(WIDTH * HEIGHT * DEPTH) / 8];<br />
capture-&gt;GetFrame(capBuffer, DEPTH, false)<br />
memcpy(image-&gt;imageData, capBuffer, image-&gt;imageSize);<br />
</pre>
という風に一度バッファに渡さないとならない。面倒。<br />
<br />
<br />
<br />
■画像処理してみる<br />
Teleshadowでも使っている、<a href="http://d.hatena.ne.jp/shokai/20090212/1234440251">cvRunningAvgを使って背景統計を取り背景差分する</a>のコードをPS3Eyeで動かしてみる。<br />
背景差分して影を作る。写真の通り、かなり近づいてカメラの外側にいるのに画面にちゃんと体が写っていることから広角っぷりがわかる。<br />
<a href="http://www.flickr.com/photos/shokai/3693367961/" title="R0012068 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3542/3693367961_2a4bc16617.jpg" width="500" height="375" alt="R0012068" /></a><br />
<br />
コードは<a href="http://shokai.org/projects/opencv-study/index.cgi/file/dcd37cb7a048/BgSubAvgPs3eye/bgsubAvgPs3eye.cpp">OpenCV Study: dcd37cb7a048 BgSubAvgPs3eye/bgsubAvgPs3eye.cpp</a>にアップロードした。<br />
<br />
PS3Eyeはゲインやホワイトバランスの調整やオートゲイン調整のon/offができるんだけど、一度オートをoffにしてプログラムを終了させてから再度起動すると前にoffにした設定が引き継がれてしまって真っ暗になる。起動時に全部onにしなければならない。<br />
今回は最初だけオートにしつつゲインだけ固定して、安定したら全部オートをoffにするようにした。これが一番安定して影が作れる。<br />
<br />
<br />
bgsubAvgPs3eye.cpp<br />
<pre class="prettyprint">
#include&nbsp;&lt;stdio.h&gt;<br />
#include&nbsp;&lt;highgui.h&gt;<br />
#include&nbsp;&lt;cv.h&gt;<br />
#include&nbsp;&lt;highgui.h&gt;<br />
#include&nbsp;&lt;ctype.h&gt;<br />
#include&nbsp;&lt;iostream&gt;<br />
#include&nbsp;&lt;cstdlib&gt;<br />
#include&nbsp;&lt;IPS3EyeLib.h&gt;<br />
<br />
#define&nbsp;WIDTH&nbsp;&nbsp;320<br />
#define&nbsp;HEIGHT&nbsp;240<br />
#define&nbsp;FPS&nbsp;&nbsp;&nbsp;&nbsp;30<br />
#define&nbsp;DEPTH&nbsp;&nbsp;24<br />
<br />
#define&nbsp;INIT_TIME&nbsp;200<br />
#define&nbsp;BG_RATIO&nbsp;0.02&nbsp;//&nbsp;背景領域更新レート<br />
#define&nbsp;OBJ_RATIO&nbsp;0.005&nbsp;//&nbsp;物体領域更新レート<br />
#define&nbsp;Zeta&nbsp;10.0<br />
<br />
int&nbsp;main(int&nbsp;argc,&nbsp;char**&nbsp;argv)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;isStop&nbsp;=&nbsp;false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*img&nbsp;=&nbsp;cvCreateImage(cvSize(WIDTH,&nbsp;HEIGHT),&nbsp;IPL_DEPTH_8U,&nbsp;3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IPS3EyeLib&nbsp;*capture&nbsp;=&nbsp;IPS3EyeLib::Create();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capture-&gt;AutoAGC(false);&nbsp;//&nbsp;ゲイン固定<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capture-&gt;SetGain(1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capture-&gt;AutoAWB(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capture-&gt;AutoAEC(true);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(capture&nbsp;==&nbsp;NULL){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;capture&nbsp;device&nbsp;not&nbsp;found!&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;-1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgAverage&nbsp;=&nbsp;cvCreateImage(cvSize(WIDTH,&nbsp;HEIGHT),&nbsp;IPL_DEPTH_32F,&nbsp;3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgSgm&nbsp;=&nbsp;cvCreateImage(cvSize(WIDTH,&nbsp;HEIGHT),&nbsp;IPL_DEPTH_32F,&nbsp;3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgTmp&nbsp;=&nbsp;cvCreateImage(cvSize(WIDTH,&nbsp;HEIGHT),&nbsp;IPL_DEPTH_32F,&nbsp;3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*img_lower&nbsp;=&nbsp;cvCreateImage(cvSize(WIDTH,&nbsp;HEIGHT),&nbsp;IPL_DEPTH_32F,&nbsp;3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*img_upper&nbsp;=&nbsp;cvCreateImage(cvSize(WIDTH,&nbsp;HEIGHT),&nbsp;IPL_DEPTH_32F,&nbsp;3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgSilhouette&nbsp;=&nbsp;cvCreateImage(cvSize(WIDTH,&nbsp;HEIGHT),&nbsp;IPL_DEPTH_8U,&nbsp;1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgSilhouetteInv&nbsp;=&nbsp;cvCreateImage(cvSize(WIDTH,&nbsp;HEIGHT),&nbsp;IPL_DEPTH_8U,&nbsp;1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgResult&nbsp;=&nbsp;cvCreateImage(cvSize(WIDTH,&nbsp;HEIGHT),&nbsp;IPL_DEPTH_8U,&nbsp;3);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capture-&gt;SetFormat(IPS3EyeLib::GetFormatIndex(WIDTH,&nbsp;HEIGHT,&nbsp;FPS));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PBYTE&nbsp;capBuffer&nbsp;=&nbsp;new&nbsp;BYTE[(WIDTH&nbsp;*&nbsp;HEIGHT&nbsp;*&nbsp;DEPTH)&nbsp;/&nbsp;8];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capture-&gt;StartCapture();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;背景初期化中...&yen;n&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSetZero(imgAverage);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;INIT_TIME;&nbsp;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(capture-&gt;GetFrame(capBuffer,&nbsp;DEPTH,&nbsp;false)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memcpy(img-&gt;imageData,&nbsp;capBuffer,&nbsp;img-&gt;imageSize);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvAcc(img,&nbsp;imgAverage);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;輝度平均&nbsp;%d/%d&yen;n&quot;,&nbsp;i,&nbsp;INIT_TIME);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvertScale(imgAverage,&nbsp;imgAverage,&nbsp;1.0&nbsp;/&nbsp;INIT_TIME);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSetZero(imgSgm);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;INIT_TIME;&nbsp;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(capture-&gt;GetFrame(capBuffer,&nbsp;DEPTH,&nbsp;false)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memcpy(img-&gt;imageData,&nbsp;capBuffer,&nbsp;img-&gt;imageSize);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvert(img,&nbsp;imgTmp);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSub(imgTmp,&nbsp;imgAverage,&nbsp;imgTmp);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvPow(imgTmp,&nbsp;imgTmp,&nbsp;2.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvertScale(imgTmp,&nbsp;imgTmp,&nbsp;2.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvPow(imgTmp,&nbsp;imgTmp,&nbsp;0.5);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvAcc(imgTmp,&nbsp;imgSgm);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;輝度振幅&nbsp;%d/%d&yen;n&quot;,&nbsp;i,&nbsp;INIT_TIME);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvertScale(imgSgm,&nbsp;imgSgm,&nbsp;1.0&nbsp;/&nbsp;INIT_TIME);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;背景初期化完了&yen;n&quot;);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capture-&gt;AutoAWB(false);&nbsp;//&nbsp;ホワイトバランス固定<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capture-&gt;AutoAEC(false);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;winNameCapture[]&nbsp;=&nbsp;&quot;Capture&quot;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;winNameSilhouette[]&nbsp;=&nbsp;&quot;Silhouette&quot;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvNamedWindow(winNameCapture,&nbsp;0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvNamedWindow(winNameSilhouette,&nbsp;0);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;waitKey&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(1){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!isStop){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(capture-&gt;GetFrame(capBuffer,&nbsp;DEPTH,&nbsp;false)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memcpy(img-&gt;imageData,&nbsp;capBuffer,&nbsp;img-&gt;imageSize);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(img&nbsp;==&nbsp;NULL)&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvert(img,&nbsp;imgTmp);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;輝度範囲<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSub(imgAverage,&nbsp;imgSgm,&nbsp;img_lower);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSubS(img_lower,&nbsp;cvScalarAll(Zeta),&nbsp;img_lower);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvAdd(imgAverage,&nbsp;imgSgm,&nbsp;img_upper);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvAddS(img_upper,&nbsp;cvScalarAll(Zeta),&nbsp;img_upper);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvInRange(imgTmp,&nbsp;img_lower,&nbsp;img_upper,&nbsp;imgSilhouette);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;輝度振幅<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSub(imgTmp,&nbsp;imgAverage,&nbsp;imgTmp);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvPow(imgTmp,&nbsp;imgTmp,&nbsp;2.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvertScale(imgTmp,&nbsp;imgTmp,&nbsp;2.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvPow(imgTmp,&nbsp;imgTmp,&nbsp;0.5);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;背景領域を更新<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvRunningAvg(img,&nbsp;imgAverage,&nbsp;BG_RATIO,&nbsp;imgSilhouette);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvRunningAvg(imgTmp,&nbsp;imgSgm,&nbsp;BG_RATIO,&nbsp;imgSilhouette);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;物体領域を更新<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvNot(imgSilhouette,&nbsp;imgSilhouetteInv);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvRunningAvg(imgTmp,&nbsp;imgSgm,&nbsp;OBJ_RATIO,&nbsp;imgSilhouetteInv);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvErode(imgSilhouette,&nbsp;imgSilhouette,&nbsp;NULL,&nbsp;1);&nbsp;//&nbsp;収縮<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvDilate(imgSilhouette,&nbsp;imgSilhouette,&nbsp;NULL,&nbsp;2);&nbsp;//&nbsp;膨張<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvErode(imgSilhouette,&nbsp;imgSilhouette,&nbsp;NULL,&nbsp;1);&nbsp;//&nbsp;収縮<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvMerge(imgSilhouette,&nbsp;imgSilhouette,&nbsp;imgSilhouette,&nbsp;NULL,&nbsp;imgResult);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvShowImage(winNameCapture,&nbsp;img);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvShowImage(winNameSilhouette,&nbsp;imgResult);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;waitKey&nbsp;=&nbsp;cvWaitKey(33);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(waitKey&nbsp;==&nbsp;'q')&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(waitKey&nbsp;==&nbsp;'&nbsp;'){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isStop&nbsp;=&nbsp;!isStop;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(isStop)&nbsp;printf(&quot;stop&yen;n&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;printf(&quot;start&yen;n&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;[]&nbsp;capBuffer;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capture-&gt;StopCapture();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvDestroyWindow(winNameCapture);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvDestroyWindow(winNameSilhouette);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;<br />
}<br />
</pre>
<br />
<br />
今回は320&#215;240で30FPSで動かしたが、<br />
<a href="http://www.atinfinity.info/blog/archives/113">dandelion&#8217;s log  PS3EyeLibで遊んでみた</a>より<br />
</p>
<blockquote><p>
320&#215;240@15fps<br />
320&#215;240@30fps<br />
320&#215;240@60fps<br />
320&#215;240@75fps<br />
320&#215;240@100fps<br />
320&#215;240@125fps<br />
640&#215;480@15fps<br />
640&#215;480@30fps<br />
640&#215;480@40fps<br />
640&#215;480@50fps<br />
640&#215;480@60fps<br />
640&#215;480@75fps<br />
</p></blockquote>
<p>
で動くらしい。<br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/4594/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC# Formアプリから使う</title>
		<link>http://shokai.org/blog/archives/4477</link>
		<comments>http://shokai.org/blog/archives/4477#comments</comments>
		<pubDate>Fri, 24 Apr 2009 12:11:15 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CLI]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[DLL]]></category>
		<category><![CDATA[OpenCV]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[VS2008]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=4477</guid>
		<description><![CDATA[重い画像処理をC++の画像処理ライブラリであるOpenCVでやって、ネットワーク処理は慣れ親しんだC#.NETでやりたい。 そこで、色々試行錯誤した結果、C#からは「処理し終わった画像を表示してくれるカメラ」に見えるよう [...]]]></description>
			<content:encoded><![CDATA[<p>
重い画像処理をC++の画像処理ライブラリであるOpenCVでやって、ネットワーク処理は慣れ親しんだC#.NETでやりたい。<br />
そこで、色々試行錯誤した結果、C#からは「処理し終わった画像を表示してくれるカメラ」に見えるような、OpenCVの処理部分を含んだDLLをC++/CLIで作ることにした。<br />
（OpenCVそのものについてと開発環境構築は<a href="http://shokai.org/blog/archives/4141">橋本商会 ? OpenCVをはじめた</a>に書いた）<br />
<br />
<br />
他にも連動のさせかたは<a href="http://www.cs.ru.ac.za/research/groups/SharperCV/">SharperCV</a>というC#ラッパーを使うとか、<a href="http://cv.nextfoods.jp/index.php?opencv%2Fsample%2Fstreaming">SocketでOpenCVで処理した結果の画像だけ送る</a>とか色々とやり方はあるけど、<br />
前者は2003年でプロジェクトが止まっていてcvPow等の配列関連の関数が無く、後者は俺のMicrosoft SDKのWinUser.hの6373行目あたりから文字化けしていてWinSocketが使えなかったりしたのでDLLを作るやり方に落ち着いた。<br />
<br />
<br />
この方法のメリットは、まず納得のいくOpenCVの処理をC++単体のプロジェクトでいつもどおり書いて、それをほぼコピペすればDLLができてしまうところ。<br />
ShaperCVを使う場合は全て関数を照らし合わせてC#で書き直さなければならないので面倒。<br />
Socketを使う方はよく知らない。<br />
<br />
<br />
DLLの作り方はかせいさんとこが参考になった。CLIを使う場合と使わない場合が解説されている。（今回は楽する為にCLIを使う）<br />
<ul>
<li><a href="http://d.hatena.ne.jp/kasei_san/20070511/p1">DLLの概要と実装方法。 &#8211; かせいさんとこ</a></li>
<li><a href="http://d.hatena.ne.jp/pota_dahon/20080305">C#からC++のDLLを利用する方法 &#8211; pota_dahonの日記</a></li>
</ul>
<br />
<br />
■今回つくるもの<br />
<a href="http://shokai.org/projects/opencv-study/">mercurialリポジトリ</a>をアップロードした。左のバーからzipでダウンロードするか、<br />
</p>
<blockquote><p>hg clone http://shokai.org/projects/opencv-study/ opencv-study</p></blockquote>
<p>
してリポジトリを複製してください。<br />
<br />
<ul>
<li><a href="http://shokai.org/projects/opencv-study/index.cgi/file/7537970cfc6b/ShadowCamera">OpenCV Study: 7537970cfc6b /ShadowCamera/</a> : 影カメラライブラリ</li>
<li><a href="http://shokai.org/projects/opencv-study/index.cgi/file/7537970cfc6b/ShadowCameraSample">OpenCV Study: 7537970cfc6b /ShadowCameraSample/</a> : 影カメラライブラリを使うFormアプリケーション</li>
</ul>
の2つを作ります。<br />
影カメラライブラリの方は、<a href="http://shokai.org/projects/opencv-study/index.cgi/file/7537970cfc6b/BgSubAvg/bgsubAvg.cpp">OpenCV Study: 7537970cfc6b BgSubAvg/bgsubAvg.cpp</a>をDLL化したもので、cvRunningAvgを使って背景統計を取って背景差分して人型の影を作るもの → <a href="http://d.hatena.ne.jp/shokai/20090212/1234440251">cvRunningAvgを使って背景統計を取り背景差分する &#8211; 橋本詳解</a><br />
<br />
<br />
完成図はこれ。C#で作ったFormアプリで、ボタンを押すとDLLに書いてあるOpenCVの処理が起動してウィンドウが開き画像処理結果が表示/毎フレーム更新される。<br />
<a href="http://www.flickr.com/photos/shokai/3470022957/" title="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3499/3470022957_55c118a20c.jpg" width="500" height="249" alt="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う" /></a><br />
<br />
<br />
<br />
■C++でDLLを作る<br />
まず空のソリューションを作る。<br />
ソリューション名を右クリックして新しいプロジェクト追加<br />
<a href="http://www.flickr.com/photos/shokai/3470811574/" title="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3507/3470811574_e25fa193ee.jpg" width="454" height="404" alt="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う" /></a><br />
<br />
<br />
VC++のクラスライブラリを作成する。名前はShadowCameraにした<br />
<a href="http://www.flickr.com/photos/shokai/3469998341/" title="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3506/3469998341_e92f96d625_o.png" width="796" height="408" alt="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う" /></a><br />
<br />
<br />
できたShadowCameraプロジェクトを右クリックしてプロパティを編集<br />
<a href="http://www.flickr.com/photos/shokai/3470815346/" title="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3035/3470815346_32fd943140.jpg" width="319" height="180" alt="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う" /></a><br />
<br />
<br />
OpenCV用のライブラリを読み込む。<br />
すべての構成->入力->追加の依存ファイル に<br />
</p>
<blockquote><p>$(NoInherit) highgui.lib cxts.lib cv.lib cxcore.lib ml.lib cvaux.lib cvhaartraining.lib</p></blockquote>
<p>
を書く <br />
<a href="http://www.flickr.com/photos/shokai/3470817812/" title="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3595/3470817812_ea25865e46_o.png" width="856" height="479" alt="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う" /></a><br />
<br />
<a href="http://shokai.org/projects/opencv-study/index.cgi/file/7537970cfc6b/ShadowCamera/ShadowCamera.h">ShadowCamera.h</a>のClass名をCameraに変更、さらにint runCapture()関数を書く。<br />
この関数の中にOpenCVのmain()を全部突っ込んでしまえばそのまま動く。今回は<a href="http://shokai.org/projects/opencv-study/index.cgi/file/7537970cfc6b/BgSubAvg/bgsubAvg.cpp">bgsubAvg.cpp</a>のmain()をコピペしたけど<a href="http://shokai.org/projects/opencv-study/index.cgi/file/7537970cfc6b/">他にも赤色重心追跡や肌色検出、単純なカメラ入力など色々作った</a>ので好きなものをコピペしてよい。<br />
OpenCV関連のヘッダを#includeで読み込むのを忘れずに。<br />
（試しにint asdf()という単に数値を返すだけの関数も作っておいた。これがC#から呼べればちゃんとDLLとして読み込めているはず）<br />
<br />
<a href="http://shokai.org/projects/opencv-study/index.cgi/file/7537970cfc6b/ShadowCamera/ShadowCamera.h">OpenCV Study: 7537970cfc6b ShadowCamera/ShadowCamera.h</a><br />
</p>
<blockquote><p>
//&nbsp;ShadowCamera.h<br />
#include&nbsp;&lt;cv.h&gt;<br />
#include&nbsp;&lt;highgui.h&gt;<br />
#include&nbsp;&lt;ctype.h&gt;<br />
#include&nbsp;&lt;stdio.h&gt;<br />
<br />
#pragma&nbsp;once<br />
<br />
using&nbsp;namespace&nbsp;System;<br />
<br />
namespace&nbsp;ShadowCamera&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ref&nbsp;class&nbsp;Camera<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;TODO:&nbsp;このクラスの、ユーザーのメソッドをここに追加してください。<br />
&nbsp;&nbsp;&nbsp;&nbsp;public:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;asdf(void){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;15;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;runCapture(void){<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;isStop&nbsp;=&nbsp;false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;int&nbsp;INIT_TIME&nbsp;=&nbsp;50;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;double&nbsp;BG_RATIO&nbsp;=&nbsp;0.02;&nbsp;//&nbsp;背景領域更新レート<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;double&nbsp;OBJ_RATIO&nbsp;=&nbsp;0.005;&nbsp;//&nbsp;物体領域更新レート<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;double&nbsp;Zeta&nbsp;=&nbsp;10.0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*img&nbsp;=&nbsp;NULL;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CvCapture&nbsp;*capture&nbsp;=&nbsp;NULL;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capture&nbsp;=&nbsp;cvCreateCameraCapture(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//capture&nbsp;=&nbsp;cvCaptureFromAVI(&quot;test.avi&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(capture&nbsp;==&nbsp;NULL){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;capture&nbsp;device&nbsp;not&nbsp;found!!&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;-1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;img&nbsp;=&nbsp;cvQueryFrame(capture);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;w&nbsp;=&nbsp;img-&gt;width;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;h&nbsp;=&nbsp;img-&gt;height;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgAverage&nbsp;=&nbsp;cvCreateImage(cvSize(w,&nbsp;h),&nbsp;IPL_DEPTH_32F,&nbsp;3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgSgm&nbsp;=&nbsp;cvCreateImage(cvSize(w,&nbsp;h),&nbsp;IPL_DEPTH_32F,&nbsp;3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgTmp&nbsp;=&nbsp;cvCreateImage(cvSize(w,&nbsp;h),&nbsp;IPL_DEPTH_32F,&nbsp;3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*img_lower&nbsp;=&nbsp;cvCreateImage(cvSize(w,&nbsp;h),&nbsp;IPL_DEPTH_32F,&nbsp;3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*img_upper&nbsp;=&nbsp;cvCreateImage(cvSize(w,&nbsp;h),&nbsp;IPL_DEPTH_32F,&nbsp;3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgSilhouette&nbsp;=&nbsp;cvCreateImage(cvSize(w,&nbsp;h),&nbsp;IPL_DEPTH_8U,&nbsp;1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgSilhouetteInv&nbsp;=&nbsp;cvCreateImage(cvSize(w,&nbsp;h),&nbsp;IPL_DEPTH_8U,&nbsp;1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IplImage&nbsp;*imgResult&nbsp;=&nbsp;cvCreateImage(cvSize(w,&nbsp;h),&nbsp;IPL_DEPTH_8U,&nbsp;3);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;背景初期化中&#8230;&yen;n&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSetZero(imgAverage);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;INIT_TIME;&nbsp;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;img&nbsp;=&nbsp;cvQueryFrame(capture);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvAcc(img,&nbsp;imgAverage);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;輝度平均&nbsp;%d/%d&yen;n&quot;,&nbsp;i,&nbsp;INIT_TIME);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvertScale(imgAverage,&nbsp;imgAverage,&nbsp;1.0&nbsp;/&nbsp;INIT_TIME);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSetZero(imgSgm);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;INIT_TIME;&nbsp;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;img&nbsp;=&nbsp;cvQueryFrame(capture);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvert(img,&nbsp;imgTmp);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSub(imgTmp,&nbsp;imgAverage,&nbsp;imgTmp);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvPow(imgTmp,&nbsp;imgTmp,&nbsp;2.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvertScale(imgTmp,&nbsp;imgTmp,&nbsp;2.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvPow(imgTmp,&nbsp;imgTmp,&nbsp;0.5);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvAcc(imgTmp,&nbsp;imgSgm);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;輝度振幅&nbsp;%d/%d&yen;n&quot;,&nbsp;i,&nbsp;INIT_TIME);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvertScale(imgSgm,&nbsp;imgSgm,&nbsp;1.0&nbsp;/&nbsp;INIT_TIME);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;背景初期化完了&yen;n&quot;);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;winNameCapture[]&nbsp;=&nbsp;&quot;Capture&quot;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;winNameSilhouette[]&nbsp;=&nbsp;&quot;Silhouette&quot;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvNamedWindow(winNameCapture,&nbsp;0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvNamedWindow(winNameSilhouette,&nbsp;0);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(1){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!isStop){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;img&nbsp;=&nbsp;cvQueryFrame(capture);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(img&nbsp;==&nbsp;NULL)&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvert(img,&nbsp;imgTmp);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;輝度範囲<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSub(imgAverage,&nbsp;imgSgm,&nbsp;img_lower);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSubS(img_lower,&nbsp;cvScalarAll(Zeta),&nbsp;img_lower);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvAdd(imgAverage,&nbsp;imgSgm,&nbsp;img_upper);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvAddS(img_upper,&nbsp;cvScalarAll(Zeta),&nbsp;img_upper);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvInRange(imgTmp,&nbsp;img_lower,&nbsp;img_upper,&nbsp;imgSilhouette);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;輝度振幅<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvSub(imgTmp,&nbsp;imgAverage,&nbsp;imgTmp);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvPow(imgTmp,&nbsp;imgTmp,&nbsp;2.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvConvertScale(imgTmp,&nbsp;imgTmp,&nbsp;2.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvPow(imgTmp,&nbsp;imgTmp,&nbsp;0.5);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;背景領域を更新<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvRunningAvg(img,&nbsp;imgAverage,&nbsp;BG_RATIO,&nbsp;imgSilhouette);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvRunningAvg(imgTmp,&nbsp;imgSgm,&nbsp;BG_RATIO,&nbsp;imgSilhouette);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;物体領域を更新<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvNot(imgSilhouette,&nbsp;imgSilhouetteInv);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvRunningAvg(imgTmp,&nbsp;imgSgm,&nbsp;OBJ_RATIO,&nbsp;imgSilhouetteInv);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvErode(imgSilhouette,&nbsp;imgSilhouette,&nbsp;NULL,&nbsp;1);&nbsp;//&nbsp;収縮<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvDilate(imgSilhouette,&nbsp;imgSilhouette,&nbsp;NULL,&nbsp;2);&nbsp;//&nbsp;膨張<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvErode(imgSilhouette,&nbsp;imgSilhouette,&nbsp;NULL,&nbsp;1);&nbsp;//&nbsp;収縮<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvMerge(imgSilhouette,&nbsp;imgSilhouette,&nbsp;imgSilhouette,&nbsp;NULL,&nbsp;imgResult);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvShowImage(winNameCapture,&nbsp;img);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvShowImage(winNameSilhouette,&nbsp;imgResult);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;waitKey&nbsp;=&nbsp;cvWaitKey(33);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(waitKey&nbsp;==&nbsp;&#8217;q')&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(waitKey&nbsp;==&nbsp;&#8217;&nbsp;&#8217;){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isStop&nbsp;=&nbsp;!isStop;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(isStop)&nbsp;printf(&quot;stop&yen;n&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;printf(&quot;start&yen;n&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvReleaseCapture(&amp;capture);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvDestroyWindow(winNameCapture);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cvDestroyWindow(winNameSilhouette);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;};<br />
}<br />
</p></blockquote>
<p>
<br />
<br />
■C#でFormアプリを作る<br />
新しいプロジェクトを作る。<br />
ソリューションエクスプローラで[参照設定]→[プロジェクト参照]でShadowCameraを参照。<br />
<a href="http://www.flickr.com/photos/shokai/3470892320/" title="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3497/3470892320_427521cbab.jpg" width="246" height="236" alt="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う" /></a><br />
なお、同一Solution内ならプロジェクト参照が便利だけど、<br />
ReleaseにShadowCamera.dllができているのでそれを他の人に配布して、[ファイルを参照]してもらってdllから呼び出してもらっても同じ機能が使えます<br />
<br />
<br />
ボタンを1つ置く。buttonStartという名前にして、ダブルクリックしてクリックイベントの雛形を作る<br />
<a href="http://www.flickr.com/photos/shokai/3470835562/" title="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3553/3470835562_906e5d2262.jpg" width="464" height="494" alt="Cで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う" /></a><br />
<br />
<br />
<br />
ShadowCameraを読み込んで<br />
</p>
<blockquote><p>using ShadowCamera;</p></blockquote>
<p>
<br />
新しいCameraクラスのインスタンスを作って、startButtonイベント内でさっき作ったrunCapture関数を呼ぶようにする<br />
<a href="http://shokai.org/projects/opencv-study/index.cgi/file/7537970cfc6b/ShadowCameraSample/ShadowCameraForm.cs#l1">OpenCV Study: 7537970cfc6b ShadowCameraSample/ShadowCameraForm.cs</a><br />
</p>
<blockquote><p>
using&nbsp;System;<br />
using&nbsp;System.Collections.Generic;<br />
using&nbsp;System.ComponentModel;<br />
using&nbsp;System.Data;<br />
using&nbsp;System.Drawing;<br />
using&nbsp;System.Linq;<br />
using&nbsp;System.Text;<br />
using&nbsp;System.Windows.Forms;<br />
using&nbsp;ShadowCamera;<br />
<br />
namespace&nbsp;ShadowCameraSample<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;partial&nbsp;class&nbsp;ShadowCameraForm&nbsp;:&nbsp;Form<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Camera&nbsp;cam;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ShadowCameraForm()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeComponent();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cam&nbsp;=&nbsp;new&nbsp;Camera();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;void&nbsp;buttonStart_Click(object&nbsp;sender,&nbsp;EventArgs&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cam.runCapture();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</p></blockquote>
<p>
<br />
<br />
ShadowCameraSampleを（右クリックして）スタートアッププロジェクトに設定し、<br />
ビルドするとShadowCameraFormが起動する。ボタンを押すとしばらくカメラを読み込んで、数秒後にOpenCVのHighGUIのウィンドウが起動するはず。<br />
<a href="http://www.flickr.com/photos/shokai/3470022957/" title="Ｃで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3499/3470022957_55c118a20c.jpg" width="500" height="249" alt="Ｃで書いたOpenCVのコードをC++/CLIで.NET用DLLにしてC#から使う" /></a><br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/4477/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>openFrameworksでサンプルプロジェクトのコンパイル</title>
		<link>http://shokai.org/blog/archives/4126</link>
		<comments>http://shokai.org/blog/archives/4126#comments</comments>
		<pubDate>Mon, 12 Jan 2009 14:31:32 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[openFrameworks]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[VS2008]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=4126</guid>
		<description><![CDATA[WindowsでVisualStudio2008 Professional C++で、openFrameworks v0.05のサンプルをコンパイルする所まで。 今のところDirectX SDKは必要ないみたいだ。 op [...]]]></description>
			<content:encoded><![CDATA[<p>
WindowsでVisualStudio2008 Professional C++で、openFrameworks v0.05のサンプルをコンパイルする所まで。<br />
今のところDirectX SDKは必要ないみたいだ。<br />
<br />
<a href="http://www.openframeworks.cc/download">openFrameworks: download</a>の「visual studio FAT」をダウンロード。ライブラリと、サンプルプロジェクトのソースコードが入っている。<br />
<br />
同じ場所にある「win32 example apps」にはコンパイル済みの実行ファイルが入っている。動的に波形を生成して音を出したり、3Dを回したりカメラの画像にエフェクトをかけるサンプルがたくさん入っている。<br />
<br />
<br />
まず適当なソリューション(.slnファイル)を開いてビルドする。<br />
エラーがでる。GLaux.libが見つからないらしい。<br />
OpenGL関係のライブラリらしくて、<br />
</p>
<blockquote><p>C:\Program Files\Microsoft SDKs\Windows\v5.0\Lib\IA64</p></blockquote>
<p>
で発見したので<br />
</p>
<blockquote><p>\libs\glu</p></blockquote>
<p>
にコピーして置いた。<br />
VS2003の頃は<a href="http://mail2.nara-edu.ac.jp/~asait/open_gl/opengl.htm">Platform SDKの下にある</a>らしいけど、俺はMicrosoft SDKの下にあった。<a href="http://social.msdn.microsoft.com/Forums/en-US/windowssdk/thread/b66e5f7a-91f6-4dbe-b388-0c131008b08f/">無いと言っている人</a>もいる。<br />
VS2005も過去にこのマシンにインストールしていたから、この位置にあるのかな？<br />
どうしても見つからない人は連絡ください。<br />
<br />
<br />
再びビルド。今度はrtAudioD.libでエラーが起こる。<br />
libs\rtAudio\rtAudioD.libのバージョンが古いらしい。<br />
<a href="http://www.openframeworks.cc/files/rtaudio-vs2008.zip">http://www.openframeworks.cc/files/rtaudio-vs2008.zip</a><br />
をダウンロードしてきて<br />
Release\rtAudio.libをrtAudioD.libにリネームして<br />
</p>
<blockquote><p>\libs\rtAudio</p></blockquote>
<p>
に置く。<br />
<br />
これでコンパイル通って動く。<br />
文字コードがCP932だよというwarningが出るので、後で文字コードは後でUTF-8に統一しよう<br />
<br />
<br />
openCVのサンプルを動かしてみた。背景差分とblob判定してる。<br />
<a href="http://www.flickr.com/photos/shokai/3190655121/" title="openFrameworks by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3399/3190655121_69d595d0d2.jpg" width="500" height="313" alt="openFrameworks" /></a><br />
<br />
<br />
ofVideoGrabberのサンプル。processing並にカメラの画像取得のコードが短い。<br />
<a href="http://www.flickr.com/photos/shokai/3190673129/" title="openFrameworks by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3104/3190673129_e617c60bc0.jpg" width="500" height="194" alt="openFrameworks" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/4126/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VS2008で単体テスト</title>
		<link>http://shokai.org/blog/archives/2325</link>
		<comments>http://shokai.org/blog/archives/2325#comments</comments>
		<pubDate>Sat, 06 Dec 2008 18:47:03 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[VS2008]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=2325</guid>
		<description><![CDATA[VisualStudio2008 professionalからIDE標準で単体テスト機能（ブラックボックステスト）が付いているので使ってみた。 俺は今まで単体テストはRSpecぐらいしかやったことがなかったし、何かライブ [...]]]></description>
			<content:encoded><![CDATA[<p>
VisualStudio2008 professionalからIDE標準で単体テスト機能（ブラックボックステスト）が付いているので使ってみた。<br />
俺は今まで単体テストは<a href="http://jp.rubyist.net/magazine/?0021-Rspec">RSpec</a>ぐらいしかやったことがなかったし、何かライブラリを作った時はそれを使うGUI付きサンプルアプリケーションを作ることでしか動作確認してこなかったけど、これは次回からどんどん使っていく事にした。<br />
<br />
この種のテストをブラックボックステストと呼ぶらしい。テスト対象のクラスの関数1つずつをブラックボックスと見るテストで、入出力の値に注目する。ある値を関数に入れてみて、予想した値が返ってくるかチェックすることで、関数が仕様を満たしているかチェックする。<br />
<br />
今回は<a href="http://www.bitbucket.org/shokai/benchmark-counter-net/">BenchmarkCounter.NET</a>の中の処理時間を計るためのOrg.Shokai.Util.Benchmark.Counterクラスのテストを作った。Startメソッドで計測開始し、Stopメソッドで停止、その間の処理時間をミリ秒で保存できる。Start/Stopを複数回行った場合、その間の平均処理時間も求める事が出来る。<br />
<br />
テストでは、出力値が正しい値になっているかどうかチェックする。このBenchmarkCounterのテストでは<br />
<ul>
	<li>処理時間を取得するメソッドの場合<br />
→ 時間の値が0以上でなければエラー</li>
	<li>計測回数を取得するメソッドの場合<br />
→ 何回か計測してみて、計測回数が合わなければエラー</li>
	<li>計測中かどうか？フラグの場合<br />
→ Startメソッドにfalseだったらエラー<br />
→ Stopメソッド後にtrueだったらエラー</li>
</ul>
という感じ。<br />
<br />
<span id="more-2325"></span><br />
■テストする<br />
その前に<br />
<a href="http://www.atmarkit.co.jp/fdotnet/special/vs2008test01/vs2008test01_01.html">Visual Studio 2008単体テスト機能のすべて − ＠IT</a><br />
この記事が詳しい。<a href="http://www.atmarkit.co.jp/fdotnet/special/vs2008test01/vs2008test01_04.html">4ページ目</a>に値を比較するAssertの関数の説明もある。<br />
<br />
こちらのテストサンプルプロジェクトも参考にさせてもらった。<br />
<a href="http://blogs.msdn.com/tomohn/pages/MSDNOFF2007.aspx">長沢智治のライフサイクルブログ : MSDN オフラインセミナー＜全国ツアー｜チーム開発編＞ 2007 Winter フォローアップページ</a><br />
<br />
<br />
ソリューションを右クリックして新しいプロジェクトを追加する。「テスト プロジェクト」というのがある<br />
<a href="http://www.flickr.com/photos/shokai/3086595995/" title="vs2008 TDD by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3084/3086595995_c327c0c375_o.png" width="392" height="363" alt="vs2008 TDD" /></a><br />
Benchmarkプロジェクトのテストなので、BenchmarkTestという名前にした。<br />
<br />
<br />
テストプロジェクトを右クリックしてテストクラスを追加する。<br />
（元からあるテストクラス使わないので削除してよい）<br />
<a href="http://www.flickr.com/photos/shokai/3087436238/" title="vs2008 TDD by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3055/3087436238_db646998ed.jpg" width="409" height="322" alt="vs2008 TDD" /></a><br />
<br />
<br />
「単体テストウィザード」を選択<br />
<a href="http://www.flickr.com/photos/shokai/3086670225/" title="vs2008 TDD by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3226/3086670225_b59f6771c3.jpg" width="500" height="396" alt="vs2008 TDD" /></a><br />
<br />
<br />
現在あるメソッドのテストを一括して作成できる。<br />
とりあえず全メソッド選択して作ってしまう<br />
<a href="http://www.flickr.com/photos/shokai/3086672197/" title="vs2008 TDD by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3056/3086672197_1c6f8ed5d8.jpg" width="479" height="424" alt="vs2008 TDD" /></a><br />
<br />
<br />
ちなみに、関数を右クリックしてテストを作る事もできる。<br />
テストはクラス毎に1つのテストクラスになるので、右クリックから行った場合は既にあるテストクラスの一番下に追加される。<br />
<a href="http://www.flickr.com/photos/shokai/3086674293/" title="vs2008 TDD by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3235/3086674293_530fc1195c.jpg" width="429" height="238" alt="vs2008 TDD" /></a><br />
<br />
<br />
テストプロジェクトを右クリックして「スタートアッププロジェクトに設定」する<br />
これでこのテストプロジェクト内のテストが行える。<br />
<a href="http://www.flickr.com/photos/shokai/3086628101/" title="vs2008 TDD by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3209/3086628101_8a0f990f53_o.png" width="289" height="393" alt="vs2008 TDD" /></a><br />
<br />
<br />
とりあえず、動かしてみる。<br />
F5もしくはツールメニューから「デバッグ開始」すればテストプロジェクトが走り、テスト結果が表示される。<br />
まだテストコードを書いていないので全て「結果を作成できません」になる。<br />
<br />
ある程度テストコードを書いていくと、こんな風に失敗したり成功したりする。<br />
<a href="http://www.flickr.com/photos/shokai/3086632819/" title="vs2008 TDD by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3264/3086632819_0b8a50b56a.jpg" width="500" height="119" alt="vs2008 TDD" /></a><br />
<br />
<br />
■テストコードの書き方<br />
例として、Countingアクセサ（実体は関数）のテストを書く。計測中かどうかを表す関数で、Startして計測中はtrueになり、Stopするとfalseになる。この切り替えがちゃんと動いているかを確認したい。<br />
<br />
Testを作成した直後はこうなっているはず<br />
</p>
<blockquote><p>///&nbsp;&lt;summary&gt;<br />
///Counting&nbsp;のテスト<br />
///&lt;/summary&gt;<br />
[TestMethod()]<br />
public&nbsp;void&nbsp;CountingTest()<br />
{<br />
&nbsp;&nbsp;Counter&nbsp;target&nbsp;=&nbsp;new&nbsp;Counter();&nbsp;//&nbsp;TODO:&nbsp;適切な値に初期化してください<br />
&nbsp;&nbsp;bool&nbsp;actual;<br />
&nbsp;&nbsp;actual&nbsp;=&nbsp;target.Counting;<br />
&nbsp;&nbsp;Assert.Inconclusive(&quot;このテストメソッドの正確性を確認します。&quot;);<br />
}</p></blockquote>
<p>
<br />
このまま実行すると「このテストメソッドの正確性を確認します」と出るが、これは「これから私がテストコードを書き直して確認します」という意味なので削除して、自分で書く。<br />
<br />
<br />
2種類チェックしたいのでCountingTest2も作った。手書きでテストを追加してもちゃんとテスト実行時に呼び出される。</p>
<blockquote><p>[TestMethod()]<br />
public&nbsp;void&nbsp;CountingTest()<br />
{<br />
&nbsp;&nbsp;Counter&nbsp;target&nbsp;=&nbsp;new&nbsp;Counter();&nbsp;//&nbsp;TODO:&nbsp;適切な値に初期化してください<br />
<br />
&nbsp;&nbsp;target.Start();<br />
&nbsp;&nbsp;target.Stop();<br />
&nbsp;&nbsp;target.Start();<br />
&nbsp;&nbsp;bool&nbsp;actual&nbsp;=&nbsp;target.Counting;<br />
&nbsp;&nbsp;Assert.IsTrue(actual,&nbsp;&quot;計測中フラグが立っていません&quot;);<br />
}<br />
<br />
[TestMethod()]<br />
public&nbsp;void&nbsp;CountingTest2()<br />
{<br />
&nbsp;&nbsp;Counter&nbsp;target&nbsp;=&nbsp;new&nbsp;Counter();<br />
&nbsp;&nbsp;target.Start();<br />
&nbsp;&nbsp;target.Stop();<br />
&nbsp;&nbsp;bool&nbsp;actual&nbsp;=&nbsp;target.Counting;<br />
&nbsp;&nbsp;Assert.IsFalse(actual,&nbsp;&quot;計測中フラグが消えていません&quot;);<br />
}</p></blockquote>
<p>
Assert.条件(値1, &#8220;エラーメッセージ&#8221;);や<br />
Assert.条件(値1, 値2, &#8220;エラーメッセージ&#8221;); という風に書く。<br />
Assert条件文の最後の引数がエラーメッセージなのがちょっとわかりにくいが<br />
Assert.AreEqual(a, b, &#8220;error! a != b&#8221;);<br />
の場合、aとbが同じかどうか確かめてみて、違ったらerror!と表示する。<br />
<br />
他にも色々条件式があって<a href="http://www.atmarkit.co.jp/fdotnet/special/vs2008test01/vs2008test01_04.html">この記事の下の方</a>で解説されている<br />
<br />
<br />
全部テストが通るとこうなる。<br />
<a href="http://www.flickr.com/photos/shokai/3087473284/" title="vs2008 TDD by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3273/3087473284_4a68a858d4_o.png" width="514" height="263" alt="vs2008 TDD" /></a><br />
<br />
チェック項目が2つ以上ある関数の場合、1つのテスト関数で複数回Assertする事も出来るが、1つのテスト関数につき1つAssertする事にした。こうしておいた方がどちらの条件でエラーがでたのかわかりやすい為。<br />
<br />
<br />
今回は先に出来ていたクラスのテストを後から作ったが、次は先にテストを作成して後から実装するテスト駆動開発でやりたい。先にテストを書き、Assertのエラー文を<br />
</p>
<blockquote><p>Assert.IsTrue(actual,&nbsp;&quot;Startメソッドで実行した後はtrueになるべきです&quot;);</p></blockquote>
<p>
のように書けば、これがそのまま詳細設計になる。<br />
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/2325/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>条件付きコンパイルシンボルで実行ファイルを色々作る</title>
		<link>http://shokai.org/blog/archives/1549</link>
		<comments>http://shokai.org/blog/archives/1549#comments</comments>
		<pubDate>Thu, 19 Jun 2008 18:06:49 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[VS2008]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=1549</guid>
		<description><![CDATA[VisualStudioではコンパイル時にコンパイラに渡す定数を定義しておいて、コード上のプリプロセッサで実行ファイルにその部分を含めるか定義する事が出来る事をさっき知った。 こういうコードだと、定数ZANMAIが定義さ [...]]]></description>
			<content:encoded><![CDATA[<p>
<p>VisualStudioではコンパイル時にコンパイラに渡す定数を定義しておいて、コード上のプリプロセッサで実行ファイルにその部分を含めるか定義する事が出来る事をさっき知った。</p>
<p>こういうコードだと、定数ZANMAIが定義されていればざんまい！！されていなければかず助になる。実行中に条件分岐するのではなく、実行ファイルに丸ごと含まれるか/含まれないかが、コンパイル構成プロファイル毎に変化する。<code>#ifZANMAI<br /><br />
MessageBox.Show("ざんまい！！");<br /><br />
#else<br /><br />
MessageBox.Show("かず助！！！！");<br /><br />
#endif</code></p>
<p>構成プロファイル「NIKU」を新規作成する。<br /><br />
<a href="http://www.flickr.com/photos/shokai/2593453750/" title="構成マネージャ by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3173/2593453750_2359f4ddf2_o.png" width="436" height="271" alt="構成マネージャ" /></a></p>
<p>プロジェクトのプロパティのビルドで、条件付きコンパイルシンボルをNIKUプロファイル固有の定数として追加しておく<br /><br />
<a href="http://www.flickr.com/photos/shokai/2593456748/" title="条件付きコンパイルシンボル by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3211/2593456748_a2be599a67_o.png" width="566" height="158" alt="条件付きコンパイルシンボル" /></a></p>
<p>この部分を含んでコンパイルするか、含まない実行ファイルを作るかを解釈するようになる。<br /><br />
動作の違う実行ファイルをそれぞれ書き出せるようになると、それだけ設定画面などを作る必要がなくなるのでうまく使えば便利そう</p>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/1549/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C#3.0 &#8211; DirectShow.NET2.0でwebcam撮影、JPEG保存する</title>
		<link>http://shokai.org/blog/archives/1546</link>
		<comments>http://shokai.org/blog/archives/1546#comments</comments>
		<pubDate>Mon, 16 Jun 2008 18:04:16 +0000</pubDate>
		<dc:creator>shokai</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[DirectShow]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[VS2008]]></category>
		<category><![CDATA[webcam]]></category>

		<guid isPermaLink="false">http://shokai.org/blog/?p=1546</guid>
		<description><![CDATA[Windowsでカメラからの画像入力を使うには、Flash(Air)やProcessing、Max/MSPを除くとDirectXかVideo for Windowsを使わなければならないんだけど、これらをC#から直接使う [...]]]></description>
			<content:encoded><![CDATA[<p>
<p>Windowsでカメラからの画像入力を使うには、<a href="http://shokai.org/blog/archives/1479">Flash(Air)</a>や<a href="http://shokai.org/blog/archives/1332">Processing</a>、Max/MSPを除くとDirectXかVideo for Windowsを使わなければならないんだけど、これらをC#から直接使うのはとてもめんどい。</p>
<p>で、DirectX自体はラッパーを介して使えるので問題ないんだけど、DirectShow（カメラの入力に使う）だけはなぜかC#用のラッパーが無いので<a href="http://directshownet.sourceforge.net/">DirectShow.NET</a>の出番になる。このライブラリは<a href="http://shokai.org/blog/archives/1207">s.h.log  DirectShow.NETで静止画キャプチャ</a>でも使ったんだけど、去年ぐらいからDirectShow.NETがver 2.0になってさらに良くなっていた。</p>
<p>ちょっといじってみたが、C++が苦手な馬鹿には便利すぎて感動したので、<br /><br />
webcam撮影→JPEG画像に保存のサンプルを作って置いておきます</p>
<p>■作ったもの<br /><br />
→ <a href="http://shokai.org/archive/cs3.0/0806_DshowNetCapture/">Download (VisualStudio 2008 + C#3.0)</a></p>
<p>昨日の朝に<a href="http://d.hatena.ne.jp/shokai/20080616/1213567007">DirectShow.NET2.0でwebcamキャプチャ、JPEG保存 &#8211; 橋本詳解</a>で書いたのとほぼ同じだが、デバイスの選択ができるようになった。<br /><br />
<a href="http://www.flickr.com/photos/shokai/2582231672/" title="select capture devices by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3090/2582231672_ac922404c1_o.png" width="481" height="302" alt="select capture devices" /></a></p>
<p>あと、DirectShow.NETを使えば、インストールすると1GBぐらいになるDirectX SDKを入れなくても済むのも嬉しい。</p>
<p>■プログラムの準備<br /><br />
まず準備として<a href="http://directshownet.sourceforge.net/">DirectShow.NET</a>のサイトからDirectShowLib-2005.dll本体と、サンプルを手に入れる。<br /><br />
DirectShowLib-2005.dllにパスを通し、sampleに入っているCapture.csもpublic domainなのでコピーしてありがたく使わせていただく。</p>
<p>そして、いくつか使うnamespaceを通す<br /><br />
<code>usingDirectShowLib;<br /><br />
usingSnapShot;<br /><br />
usingSystem.Runtime.InteropServices;<br /><br />
usingSystem.Drawing.Imaging;</code></p>
<p>■カメラデバイスを取得してプレビュー表示する<br /><br />
なんでもいいが、System.Windows.Forms.Controlを継承しているPanelやPictureBoxやFormなどを、カメラのプレビュー用に用意しなければならない。プレビューを画面に出したくなければVisible = falseしておけばいい。<br /><br />
そのコントロールをCaptureクラスのコンストラクタに渡してやると、cameraのプレビュー表示がリアルタイムに表示されるようになる。<br /><br />
<code>PanelpanelPreview=newPanel();<br /><br />
this.Controls.Add(panelPreview);<br /><br />
Capturecam=newCapture(0,640,480,24,panelPreview);//device,x,y,24FPS,preview</code><br /><br />
Capture()の第一引数は画像入力デバイスのindexで、0からはじまる。存在しないデバイスindexを選んでしまうとエラーになるので注意。FPSやカメラのXYサイズも指定できる。</p>
<p>■現在のカメラ表示を保存する<br /><br />
別のコントロールを用意して、そっちに保存する。<a href="http://www.flickr.com/photos/shokai/2582231672/">今回のサンプルアプリ</a>の場合は、左の動画が右に静止画としてキャプチャされる。<br /><br />
PictureBoxにキャプチャするなら<br /><br />
<code>PictureBoxpicBox=newPictureBox();<br /><br />
this.Controls.Add(picBox);<br /><br />
IntPtrm_ip=cam.Click();<br /><br />
Bitmapb=newBitmap(cam.Width,cam.Height,cam.Stride,PixelFormat.Format24bppRgb,m_ip);<br /><br />
b.RotateFlip(RotateFlipType.RotateNoneFlipY);//上下反転しているので直す<br /><br />
picBox.Image=b;</code></p>
<p>Image型で静止画をコピーできたので、JpegファイルやPNGファイルなどに書き出すのも簡単。<br /><br />
<code>picBox.Image.Save("captured.jpg",ImageFormat.Jpeg);</code></p>
<p>もちろんPictureBoxを経由しないで、直接保存もできる<br /><br />
<code>b.Image.Save("captured.jpg",ImageFormat.Png);</code></p>
<p>カメラを閉じるのを忘れずに。<br /><br />
FormのFormClosedイベント内などでDispose()を呼べば良い<br /><br />
<code>cam.Dispose();</code></p>
<p>ちなみに、現在接続してあるデバイスの一覧はDsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)の中に入っている。<br /><br />
今回のサンプルでコンボボックスの中にデバイス名一覧を突っ込んだのはこんな感じでやった<br /><br />
<code>comboBoxDevices.Items.Clear();<br /><br />
foreach(DsDevicedsinDsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice))<br /><br />
{<br /><br />
comboBoxDevices.Items.Add(ds.Name);<br /><br />
}<br /><br />
comboBoxDevices.SelectedIndex=0;</code></p>
<p>ComboBox.SelectedIndexで現在選ばれたデバイス名のindexがわかって、それをCaptureのコンストラクタのデバイスindexとして使えば良い。</p>
</p>
]]></content:encoded>
			<wfw:commentRss>http://shokai.org/blog/archives/1546/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

