C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: VB.NET)四次元配列を用いての2点間距離計測


(過去ログ 25 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■11081 / inTopicNo.1)  VB.NET)四次元配列を用いての2点間距離計測
  
□投稿者/ Flowen (1回)-(2007/12/06(Thu) 16:08:33)

分類:[.NET 全般] 

VB.NET2003を使い始めてまだ3ヶ月です。
文脈がわかりづらいかもしれませんが、何卒お願いします。

今回お尋ねしたいのは、4次元配列の宣言時にオーバーフローすることです。

VB.NET2003を用いて、ダーツなどに使われる的の円の検出を、ハフ変換で行っています。
一般的なハフ変換は要素を抽出して・・・という方法がありますが、今回は2点間の距離を求める方法で行います。
理論としては、ある画素p1と、別の画素p2との距離を計測し、距離が等しい点の数を集計して、
もっとも点の数が多かった距離と点をそれぞれ求める円の半径、中心点とする方法を用いています。

今回躓いて悩んでいるのが、2点間の距離を記録しておく領域についてです。
以下、2点間の距離を求めているプログラムを載せます。
---------------------------------------------------------------------------------

            Dim maxX = Edgebmp.Width - 1 'X座標の最大値
            Dim maxY = Edgebmp.Height - 1  'Y座標の最大値
      Dim D(maxX,maxY,maxX,maxY) As Double '----ここでオーバーフローエラーが発生----'

            '2点間の距離を四次元配列に保存
            For x As Integer = 0 To maxX
                For y As Integer = 0 To maxY
                    For i As Integer = 0 To maxX
                        For j As Integer = 0 To maxY
                          D(x,y,i,j)=Math.Sqrt(Math.Pow(x - i, 2) + Math.Pow(y - j, 2))
                        Next j
                    Next i
                Next y
            Next x
---補足------------------------------------------------------------------
EdgebmpとはBitmapで宣言した、Form上のPictureboxの画像を取り込んだものです。
D( A , B , C , D )について、
Aには求める円の仮定中心点x軸座標(プログラムで言えば、変数 x
Bには求める円の仮定中心点y軸座標(プログラムで言えば、変数 y
Cには求める円の仮定中心点x軸座標(プログラムで言えば、変数 i
Dには求める円の仮定中心点y軸座標(プログラムで言えば、変数 j
------------------------------------------------------------------------
四次元配列Dの宣言時、maxXとmaxYの大きさは画像に依存しますが、
画像の大きさが小さいものならばエラーがないときもあり、処理ができます。できないときもあります。
画像が大きいものはほとんど処理が通りません。

エラーメッセージは
「'System.OutOfMemoryException'のハンドルされていない例外が.exeで発生しました」
となります。

四次元の配列領域がでかすぎるのかと思い、条件わけをするなどして減らしたりしましたがうまくいきません。
エラーを出さずに処理を行う方法、または四次元に代わる方法をご教授いただけないでしょうか?

稚拙な文章で申し訳ないですが、よろしくお願いいたします


引用返信 編集キー/
■11082 / inTopicNo.2)  Re[1]: VB.NET)四次元配列を用いての2点間距離計測
□投稿者/ PATIO (2回)-(2007/12/06(Thu) 16:19:44)
No11081 (Flowen さん) に返信
> 今回お尋ねしたいのは、4次元配列の宣言時にオーバーフローすることです。
>
> Dim maxX = Edgebmp.Width - 1 'X座標の最大値
> Dim maxY = Edgebmp.Height - 1 'Y座標の最大値
>       Dim D(maxX,maxY,maxX,maxY) As Double '----ここでオーバーフローエラーが発生----'


> エラーメッセージは
> 「'System.OutOfMemoryException'のハンドルされていない例外が.exeで発生しました」
> となります。
>
> 四次元の配列領域がでかすぎるのかと思い、条件わけをするなどして減らしたりしましたがうまくいきません。
> エラーを出さずに処理を行う方法、または四次元に代わる方法をご教授いただけないでしょうか?

えーと、実際に扱っている数値を使って試算してみましたか?
例えば、32×32ピクセルの画像を考えたとして単純に計算すると32×32×32×32×8となって8388608なんて数値に
これって8MBになっちゃいます。たった32ピクセル四方の画像で8MBです。
後は推して知るべしで画像が大きくなれば、途方も無い数値になるのは当たり前です。

で、本当に全ての計算結果を最後まで取っておく必要があるんでしょうか?
部分毎にやるとかできませんか?
もしくはファイルに書き出すとかもありえるでしょうけれど。
最近のPCがいくらメモリをたくさん載せているからと言っても一つのプロセスが使えるメモリの上限は決まってますし、
それでなくてもリソースと言うのは上限と言うのが存在します。
全部メモリに展開できれば楽なのは間違いない話ですが、現実には限られた範囲内でしか無理です。
少なくとも全てをメモリ上に展開するのは無理だと思うので処理方法を再検討された方が良いと思います。

引用返信 編集キー/
■11085 / inTopicNo.3)  Re[2]: VB.NET)四次元配列を用いての2点間距離計測
□投稿者/ Tom Yama (33回)-(2007/12/06(Thu) 16:49:37)
No11081 (Flowen さん) に返信
>「'System.OutOfMemoryException'のハンドルされていない例外が.exeで発生しました」
は、メモリ不足エラーです。オーバーフローエラーではありません。

で、何でわざわざ、2点間の距離を配列に記憶するわけ?
必要になったら、その場で、計算すればいいじゃん。

引用返信 編集キー/
■11095 / inTopicNo.4)  Re[1]: VB.NET)四次元配列を用いての2点間距離計測
□投稿者/ れい (266回)-(2007/12/06(Thu) 21:21:15)
No11081 (Flowen さん) に返信
> VB.NET2003を用いて、ダーツなどに使われる的の円の検出を、ハフ変換で行っています。
> 一般的なハフ変換は要素を抽出して・・・という方法がありますが、今回は2点間の距離を求める方法で行います。
> 理論としては、ある画素p1と、別の画素p2との距離を計測し、距離が等しい点の数を集計して、
> もっとも点の数が多かった距離と点をそれぞれ求める円の半径、中心点とする方法を用いています。
>...
> 四次元の配列領域がでかすぎるのかと思い、条件わけをするなどして減らしたりしましたがうまくいきません。
> エラーを出さずに処理を行う方法、または四次元に代わる方法をご教授いただけないでしょうか?

距離と位置の相関関数を求める手法ですね。
他の方も言ってますが、距離をすべて配列に保存するのは容量が圧倒的に足りません。
速度的にも無駄ですし、情報量的にも無駄ですので、その都度求めるべきです。

ただでさえ、ハフ変換はメモリを大量に消費します。
今回は半径と座標x,yの3つのパラメータがありますので、
何も考えずに変換をすると
x*y*sqrt(x^2+y^2)〜O(n^3)程度の領域を強度保存用に確保しなければいけません。
オーダーが一つ違うのは大変な違いです。

ですので、パラメータ数の多い(3つ以上)ハフ変換を使う場合、
メモリ消費を緩和するため、
部分的に変換したり、漸近的手法を用いたりといった手法を使います。

どの手法を用いるかはメモリ消費量の見積もりがなければ判断できません。
もう一度見積もりからはじめるべきだと思います。
引用返信 編集キー/
■11117 / inTopicNo.5)  Re[3]: VB.NET)四次元配列を用いての2点間距離計測
□投稿者/ Flowen (2回)-(2007/12/07(Fri) 10:21:05)
2007/12/07(Fri) 10:24:18 編集(投稿者)

みなさん迅速な回答ありがとうございます

No11082 (PATIO さん) に返信
> えーと、実際に扱っている数値を使って試算してみましたか?
> 例えば、32×32ピクセルの画像を考えたとして単純に計算すると32×32×32×32×8となって8388608なんて数値に
> これって8MBになっちゃいます。たった32ピクセル四方の画像で8MBです。
> 後は推して知るべしで画像が大きくなれば、途方も無い数値になるのは当たり前です。
>
> で、本当に全ての計算結果を最後まで取っておく必要があるんでしょうか?
> 部分毎にやるとかできませんか?
部分ごととは、その計算した数値が必要になったとき、ということでよろしいでしょうか?
その計算結果を基にした配列を使って処理を行いたいため、です。
その計算結果を使えないので再検討が急務、ですね・・・

> 少なくとも全てをメモリ上に展開するのは無理だと思うので処理方法を再検討された方が良いと思います。
はい、ご指摘のとおりこのままの処理では実現ができないようなので再検討いたします。


No11085 (Tom Yama さん) に返信
> ■No11081 (Flowen さん) に返信
> >「'System.OutOfMemoryException'のハンドルされていない例外が.exeで発生しました」
> は、メモリ不足エラーです。オーバーフローエラーではありません。
すみません、勉強不足でした^^;
ご指摘ありがとうございます。

>> で、何でわざわざ、2点間の距離を配列に記憶するわけ?
> 必要になったら、その場で、計算すればいいじゃん。
この処理の後、2点間の距離をIndexとした配列を使って処理を行う必要があるからです。
配列に距離を記録しておくことで、1つのループの間に数回、二次式の計算を行うのを避けたかったためです。

No11095 (れい さん) に返信
> 距離と位置の相関関数を求める手法ですね。
> 他の方も言ってますが、距離をすべて配列に保存するのは容量が圧倒的に足りません。
> 速度的にも無駄ですし、情報量的にも無駄ですので、その都度求めるべきです。
はい、処理を随時計算する仕様に変更したいと思います。

> ただでさえ、ハフ変換はメモリを大量に消費します。
> 今回は半径と座標x,yの3つのパラメータがありますので、
> 、パラメータ数の多い(3つ以上)ハフ変換を使う場合、
> メモリ消費を緩和するため、
> 部分的に変換したり、漸近的手法を用いたりといった手法を使います。
> どの手法を用いるかはメモリ消費量の見積もりがなければ判断できません。
> もう一度見積もりからはじめるべきだと思います。
はい、開発環境の見直しからやりたいと思います。


迅速な回答、皆様ありがとうございます、
まとめさせていただきますと、

・メモリ不足エラーであり、配列に数値を保存しておくのは非現実的。再検討の余地あり。
・開発環境から見直し、メモリ消費量を見積もる。
・というか処理方法ダメダメ。もっかいガンガレ。

ということですね・・・がんばります。

また、ご指摘ありがとうございます。
引用返信 編集キー/
■11119 / inTopicNo.6)  Re[2]: VB.NET)四次元配列を用いての2点間距離計測
□投稿者/ Mr.T (135回)-(2007/12/07(Fri) 10:46:05)
Mr.Tです、こんにちは。
ちょっとだけ、突っ込み。
>・開発環境から見直し、メモリ消費量を見積もる。
いや、実行環境でも見直さないとだめじゃないですか?
#自分とこじゃ動いたんだけど、って話もあるし。
引用返信 編集キー/
■11122 / inTopicNo.7)  Re[4]: VB.NET)四次元配列を用いての2点間距離計測
□投稿者/ れい (271回)-(2007/12/07(Fri) 10:55:32)
No11117 (Flowen さん) に返信
> この処理の後、2点間の距離をIndexとした配列を使って処理を行う必要があるからです。
> 配列に距離を記録しておくことで、1つのループの間に数回、二次式の計算を行うのを避けたかったためです。 

んー。
なんかわかってないような気がします。

確かに「その都度」とは言いましたが、
ハフ変換時に画素ごと求めよといったつもりではないのですが、
わかっているでしょうか?

ハフ変換なので、距離を指標にするのはわかりますが、
座標の組1個に対して距離演算は1/16回とか1/8回でできます。
そうでなくては使えないというか、
本質的にそうなるものなんですよね。

そうならない場合はハフ変換がよく理解できてないのではないでしょうか。

距離というのはx方向の差とy方向の差の二つで決まりますから、
xとyが離散化されてるなら

For x As Integer = 0 To maxX
  For y As Integer = 0 To maxY
  D(x,y)=Math.Sqrt(x*x+y*y)
  Next y
Next x

としておいて、距離を求める際には
D(abs(x1-x2),abs(y1-y2))
とすればOKで。

これだと配列も2次で済みます。

xとyは逆でも同じ距離になるはずですから、
本当は配列をさらに約半分に減らせます。
つまり、Dにはユニークな値しか入らないようにするんです。

と、こんな感じで処理するとハフ変換の半分くらいは終わってしまいます。
特に、Dにはユニークな値しか入ってないので、
ソートすればそのまま指標に用いることができますね。

これ、都合よすぎると思いませんか?

配列の次数や領域を減らして消費メモリを減らしたら、
計算回数も減って速度も速くなって、
しかも配列をそのまま指標に用いることができるんです。

この辺にハフ変換の意味とかがあるんで、
よく考えるとよいと思います。

引用返信 編集キー/
■11126 / inTopicNo.8)  Re[5]: VB.NET)四次元配列を用いての2点間距離計測
□投稿者/ れい (273回)-(2007/12/07(Fri) 11:06:57)
そうそう。もう一点。

指標の選び方を工夫すれば、
>   D(x,y)=Math.Sqrt(x*x+y*y)
これすら、無駄になりますよ。

8bitCPUですら高価で手が出ない時代に考えられた手法ですからね。
しかも今回は問題がオリジナルの霧箱とほぼ同じ。
相当軽く作れますよ。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -