dポイントプレゼントキャンペーン実施中!

失礼します。
OpenCVという画像処理ライブラリを用いてテンプレートマッチング法を使った物体追跡を行っています。
今、観測画面内でテンプレート画像とマッチングした箇所を矩形で囲んでその部分の座標X,Y(単位[pixel])を随時コマンドプロンプトに表示させています。

このとき、矩形で囲んでいる物体が一定の場所に置いてあっても、コマンドプロンプト上に表示させている座標にプラスマイナス2[pixel]ぐらいの誤差が生じてしまいます。
この誤差というのは[pixel]→[mm]に単位変換した場合どのくらいの誤差になるのでしょうか??

パソコンはWindows XPでモニターサイズは普通の15インチ(72dpi?)だと思います。観測画面は640×480の解像度でキャプチャーしています。

どうでもいいかもしれませんがmain内のテンプレートマッチングに関係した分のプログラムだけ貼っておきます。
よろしくお願いします。

int main( void ) {

int device1 = 0;
int key=0;

double max_interlinkage=0;
double min_interlinkage=0;

int X1 = 351;
int X2 = 351;
int Y1 = 349;
int Y2 = 349;
CvPoint end_point1;
CvPoint end_point2;

CvPoint max_point;
CvPoint min_point;
CvPoint corner_point;

char windowNameTemplate[] = "Template";//テンプレート画像を表示するウィンドウの名前
char windowNameDestination[] = "Destination";//マッチング結果を表示するウィンドウの名前

//videoInputオブジェクト
videoInput VI;

//利用可能なキャプチャデバイス数を取得
int numDevices = VI.listDevices();

//キャプチャデバイスが見つからなかったら終了
if(numDevices == 0)
{
cerr << "[Error] Capture device not found!!" << endl;
exit(-1);
}

//デバイス初期化(今回はデバイスID = 0,CAPTURE_WIDTH x CAPTURE_HEIGHTでキャプチャ)
VI.setupDevice(device1, CAPTURE_WIDTH, CAPTURE_HEIGHT);

IplImage *templateImage = cvLoadImage( "C:/Documents and Settings/ito/デスクトップ/cv_samples/image/temp.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR );
IplImage *tempGray = cvCreateImage( cvGetSize(templateImage), IPL_DEPTH_8U, 1 );

if ( templateImage == NULL ) {
//画像が見つからなかった場合
printf( "画像が見つかりません\n" );
return -1;
}

cvCvtColor(templateImage,tempGray,CV_BGR2GRAY);

IplImage *frameImage = cvCreateImage( cvSize(CAPTURE_WIDTH, CAPTURE_HEIGHT), IPL_DEPTH_8U, 3 );//画像用IplImage
IplImage *grayImage = cvCreateImage( cvSize(CAPTURE_WIDTH, CAPTURE_HEIGHT), IPL_DEPTH_8U, 1 );//元画像をグレースケール化した画像用IplImage
IplImage *dstImage = cvCreateImage( cvSize( frameImage->width - templateImage->width + 1, frameImage->height - templateImage->height + 1 ), IPL_DEPTH_32F, 1 );//相違度マップ画像用IplImage

memcpy(frameImage->imageData, VI.getPixels(device1, false , true), frameImage->imageSize);

cvCvtColor(templateImage,tempGray,CV_BGR2GRAY);

//ループ開始
while(1){

//カメラ・デバイスから画像取得
memcpy(frameImage->imageData, VI.getPixels(device1, false , true), frameImage->imageSize);

cvCvtColor(frameImage,grayImage,CV_BGR2GRAY);

end_point1=cvPoint(X1,Y1);
end_point2=cvPoint(X2,Y2);
cvRectangle(frameImage , end_point1 , end_point2 , CV_RGB(255,0,0) , LINE_THICKNESS , LINE_TYPE , SHIFT);

//テンプレートマッチングを行う
cvMatchTemplate( grayImage, tempGray, dstImage, CV_TM_CCOEFF_NORMED );

//テンプレートが元画像のどの部分にあるのかという情報を得る
cvMinMaxLoc( dstImage, &min_interlinkage, &max_interlinkage, &min_point, &max_point, NULL );

if(max_interlinkage>0.60){

corner_point=cvPoint(max_point.x+templateImage->width , max_point.y+templateImage->height);

printf("point x=%d ",max_point.x+templateImage->width);
printf(" y=%d ",max_point.y+templateImage->height);

cvRectangle(frameImage , max_point , corner_point , CV_RGB(255,0,0) , LINE_THICKNESS , LINE_TYPE , SHIFT);

printf("\n");

}else{

printf("point Lost\n");

}

A 回答 (6件)

単純な度量変換ですよ


dpiは ドット パー インチ すなわち 1インチあたりのドット数です
1インチをmmで表す場合 25.4mmとするのが一般的でしょう

Pixel / DPI X 25.4 といった式になります

2 / 72 * 25.4 = 0.70555
ぐらいでしょう …
    • good
    • 0
この回答へのお礼

ネットで調べればすぐ解決できるような質問でしたね。
回答してくださりありがとうございました!

お礼日時:2008/11/21 14:13

観測領域の640×480とか、カメラの解像度1600×1200とか、そういう数値をいくら並べ立てた所で、絶対に答えはでません。



唯一の方法は「被写体の円マークの大きさを計り、その円マークが何ピクセル分の画像になったか、手でドット数を数える」しかありません。

例えば、手でドット数を数えて「直径19.6mmの円マークの被写体は、253ドットくらいで写ってる」との結果になれば、1ドットは「19.6÷253(mm)」と判ります。2ドットなら「19.6÷253×2(mm)」なので「2ドットは約0.154mm」と判ります。

ぶっちゃけ、貴方が「解像度は…」とか「DPIは…」とか「観測領域は…」とか言った所で、絶対に答えは出ません。

で、画像1枚だけを数えても意味無いから、サンプル画像4~50枚で円が何ドットの大きさで写ってるか全部数え、平均を求めよう。

平均した値が「画像1ドットの大きさの平均」になるので、それを2倍すれば「画像2ドットの大きさの平均」になるから、それが求めたい「ミリ単位での誤差の平均」になる。

インテリや学者の欠点は「頭でだけで考えて行き詰まって悩む」と言う点。頭で考える前に先に手が動いてしまう「インテリでも学者でもない人」は、何も悩まず、まず「手作業」と言う強引な手段(今回の場合は、画像のドット数を数える)に訴えて簡単に問題を解決してしまいます。理論なんか、後から幾らでも辻褄合わせ出来ます。
    • good
    • 0

こんにちは.



リンク先のサイトは「画面上の画像を印刷したときにどのくらいのサイズになるか」,
を計算する目的であるように思います.
pointやpica,級というのは印刷で使われる単位だからです.
例えば級は写植機の送り装置のギアの回転に基づく単位です.

透視投影とは「遠くのものほど小さく映る」モデルです.
ですから,奥行きの情報無くして画像領域の物理的なサイズは計算できません.
さらにmm単位への変換には,「mm単位の焦点距離」,
「撮像素子の物理サイズ」,「画素単位の焦点距離」のうち二つが必要不可欠です.
これは透視投影というカメラの数学モデルの基礎ですが,
再三申し上げているこの内容もご理解いただけないようなので,
これを最後にしたいと思います.
少々厳しい物言いになりますが,
まともな書籍や文献を当たることなくWeb検索を繰り返している限り,
あなたが正解に到達することは無いでしょう.
    • good
    • 0

おはようございます.



重要なのは焦点距離(f=25mmとか書かれているあれです)と撮像素子のサイズです(こちらもmm単位).
これがあれば,
「光学中心からf mmだけ離れた像面上の一辺n mm の矩形領域は,
光学中心からZ mm だけ離れた場所において N mmなるサイズだから…」
と計算すれば良いわけです
(さすがに透視投影モデルについてはご存じですよね?).

なのですが,上記の量が公開されていない場合もあります.
一応,計算で焦点距離を求めることも可能なのですが,
この処理はかなり面倒なのでおすすめしません.
興味がある場合はOpenCVのCamera Calibrationで調べてみてください.
Zhangの方法と呼ばれるカメラ校正法に行き着くはずです.
この方法によれば「fは何画素分か」が分かります.
後はこれに画素の物理的なサイズを乗ずれば良いはずです.

色々勘案すると,「円が円として映る状況」で「右にN mm動かしたときに中心が m 画素ずれた,
だからこの奥行きにおいて 1 画素は N/m mm くらいだろう」とやるのが一番簡単です.

ところで,「フレームレート」というのは1秒当たりに何枚画像を撮影できるか,
ということではないのですか?
「アナログなテレビのフレームレートは29.97fps」と言った場合,
100秒で2997枚の画像が出てくるという意味なのですが…
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

OpenCVのCamera Calibrationも少し調べてみようと思います。

「フレームレート」はたしかに1秒当たりに何枚画像を撮影できるかでした。
さらなる勘違いをしていたようで、フレームレートではなく観測画面が「640×480」でした。

解像度などについていろいろ調べてたところ、こんがらがってきてしまったのですが観測画面サイズが「640×480」の場合、その解像度は「640×480dpi」でいいのでしょうか?

余談かもしれませんがpixelをいろいろな単位に変換してくれるサイトをみつけたのですが、このサイトは今回の問題を解決するのに使えるでしょうか??
ppiが出てきて正直混乱してます・・・・

http://www.gem.hi-ho.ne.jp/fortunefield/javascri …

お礼日時:2008/11/23 00:01

こんにちは.



結論から言うと「場合によって異なるので質問文からは絶対に計算できない」です.
これは以下のような理由によります.
(1)カメラの物理的な情報が皆無
(2)撮影対象の奥行きについて概算すらしていない
(3)諸々の不確かさ

順番に説明すると,
(1)デジタルカメラを使っているとすれば,
カメラの焦点距離とCCD素子のサイズから1画素の物理的な大きさが計算できます.
が,この情報が一切書かれていません.
(2)画素の物理的なサイズが分かっていても撮影対象の位置によって「1画素」に投影される体積が異なります.
例えば,1mの距離で画像面に正対した20mm平方の平板と2mの距離の40m平方の平板は画像上で同じ大きさ(画素数)に見えます.
対象物体に奥行きがある場合は遠方短縮によってもっと面倒なことになります.
(3)「キャプチャ」とありますのでNTSC信号などで入力をしていると思われますが,
この場合,A/D変換を経由する都合上,画素のサイズはフレームによって異なります.
入力されたアナログ信号をサンプリングするとしても,
その間隔はどうあっても「全く同じ」にならないからです.

まとめると,カメラの物理的な情報を調べるのでなければ,
撮影対象を既知の量だけ動かしたときに像面上でどの程度の変位が発生するかを「手で」見積もってください.
テンプレートマッチングをしないのはこの処理の評価関数が物理的な計量と無関係だからです.
一般的には評価関数として「画像間の輝度差」を使いますが,
これは「対象物体が全く動いてない」状況でも「片方の画像が明るくなる」だけで「誤差」が生じることからも確認できると思います.
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
安易に質問してしまいすいません。
情報が足りませんでした。

☆今使用しているUSBカメラの仕様を確認してみたところ、

撮影素子・画素数:CMOS・200万画素・オートフォーカス
解像度:最大1600×1200
最短接写距離:10cm

☆現在の観測環境

現在は対象物体とカメラ間の距離は15cmほどで観測しています。
それで自分勘違いしていまして、フレームレート=解像度だと思ってました。
なので確認してみたところ、解像度「1600×1200」、フレームレート「640×480」、対象物体とカメラ間距離15cmの環境において直径2cmほどの円を矩形で囲み追跡しています。

調べてみたところ、このくらいだったのですが、他にpixel→mmに単位変換する際に必要な情報はありますか?

お礼日時:2008/11/21 14:46

>この誤差というのは[pixel]→[mm]に単位変換した場合どのくらいの誤差になるのでしょうか??



「2Pixelは何mmか?」という事でしょうか?

>観測画面は640×480の解像度

重要なのは「観測している領域の大きさ」です。

640mm×480mmの領域を640×480の解像度でキャプチャしているなら、1ドットは1mm×1mmです。

320mm×240mmの領域を640×480の解像度でキャプチャしているなら、1ドットは0.5mm×0.5mmです。

64mm×48mmの領域を640×480の解像度でキャプチャしているなら、1ドットは0.1mm×0.1mmです。

質問文には「何mm×何mmの領域を撮影しているか」が書かれていませんので「2Pixelは何mmか?」は判りません。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

>「2Pixelは何mmか?」という事でしょうか?

そうですね。2[Pixel]の誤差が[mm]に単位変換すると何mmなのかということです。

>重要なのは「観測している領域の大きさ」です。

すいません、どうも自分勘違いしていたみたいで。。
画像サイズ=解像度だと思っていました。
どうやら違うみたいですね。
使用しているUSBカメラがCMOS200万画素なので、解像度は[1600×1200]に相当するようです。
それで「観測している領域の大きさ」が640×480でした。
まだ[mm]に単位変換するのに情報は足りないでしょうか??

お礼日時:2008/11/21 14:27

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!