1

エッジ検出方法をプログラムしようとしています。そして、emgucv Image クラスを使用しました。グレー値が必要なので、次のように宣言しました

Image<Gray,float> MyImage = new Image<Gray,float>;

画像を選択し、そのピクセル値を MyImage に次のように割り当てます。

public void selectImage()
          { 
               OpenFileDialog opp = new OpenFileDialog();
              if (opp.ShowDialog() == DialogResult.OK)
              {                 
                   MyImage = new Image<Gray,float>(opp.FileName);
                  InputArray = new Image<Gray, float>(opp.FileName);
                  Convert.ToString(MyImage);
                  pictureBox1.Image = MyImage.ToBitmap();                
              }             
          }

エッジ検出ボタンをクリックすると、メインの再帰関数が呼び出されます

private void detect_edges_Click(object sender, EventArgs e)
        {          
           hueckel_operator(1, 1);
        }

この演算子は、5 ピクセル間隔で繰り返されます。つまり、x パラメータを 5 ずつ増やして x 軸に適用し、行の最後で y 軸を 5 ずつ増やしていきます。

hueckel_operator では、非常に重い式を再計算する関数「a()」が 8 回呼び出されています。ここに a() 関数があります

 public double a(int j,  int counter6,  int counter7)
            {

                for (int II = 0; II <= j ; II++)
                {
                    for (KK = 1; KK < 70; KK++)
                    {
                         x_value = input_i_x(KK); //this function brings the x coordinate
                         y_value = input_i_y(KK); // this function brings the y coordinate

                result += HueckelDisk(x_value,y_value,j) * MyImage[x_value+counter6, y_value+counter7].Intensity;
                //MyImage.Dispose();
                    }
                }                           
                return result;
            }

しかし、問題は座標 (75,5) 付近にあり、スタック オーバーフロー例外がスローされます。パフォーマンス分析でデバッグしたところ、MyImage がすべてのメモリを消費しているようです。おそらく再帰関数を見たいと思うでしょうが、大きすぎるのでここに置くことはできません.再帰関数(hueckel_operator())が何回呼び出されたかがわかったので、終了条件に到達できないと確信しています. 私が欲しいのは、より効率的な方法で「結果」を計算する別の方法があるかどうかを調べることです。

私の他の質問は、オブジェクト MyImage が関数 a() で 69*j 回使用され、a() が呼び出されるたびにメモリ空間を 69*j 回割り当てるということですか?

私の必死の試みの間に、メモリ使用量を減らすために、ほとんどすべての変数をグローバルとして宣言および定義しました。それは良いまたは必要なアプローチですか?

私は 4 つの非常にネストされた重い関数を使用しており、クラスは使用していません。それが主な問題でしょうか?正直なところ、ここにはクラスに変換するものは何もありません。

あまりにも多くの質問をしてきましたが、今は本当に必死です。数週間前から記事を読んでいますが、キックスタートが必要だと思います。どんな助けでも大歓迎です。

ここに画像の説明を入力

4

1 に答える 1

3

スタック オーバーフローの例外は、実際にはメモリの使用とはあまり関係がありません。スタックの使用によるものです。あなたの場合、再帰呼び出し。

スタックが使い果たされるまで、再帰は非常に深くなることができます。それが発生すると、スタックオーバーフローが発生します。

無制限の再帰ではなく、さらに深くする必要がある場合は、スレッドを作成するときにスタック サイズを指定し、その上で再帰関数を実行できます。

var stackSize = 10000000;
var thread = new Thread(new ThreadStart(StartDetection), stackSize);

ただし、デフォルトのサイズは 1MB です。これは、ほとんどのタスクにとってかなり大きいサイズです。再帰が実際にバインドされていないこと、または再帰を削減または削除できないことを確認したい場合があります。

于 2012-07-09T13:02:03.977 に答える