2012-01-18 3 views
1

私は、文字 "A"のようなアルファベット1文字に対して複数のデータを受け入れることができるようにプログラムを修正しようとしています。キーボードからの1つのキーだけが1つのデータを保持できるようにする何らかの種類のContainsKey関数がありました。複数のデータを保持する方法を教えてください。複数のデータを保持できる辞書を作成するにはどうすればよいですか?

私はこれを非常に明確にするつもりです。これは、監督されていないニューラルネットワークを使用したオンラインOCRプログラムです。ユーザが描画空間に文字を描くと、学習データに文字を追加して後で訓練するという選択肢があります。彼らが文字を追加するとき、彼らはキーボード上のキーを使用して入力したばかりの文字を定義する必要があります。たとえば、文字 'A'を描き、その文字のキーボードからキーを入力するようにポップアップウィンドウが表示されます。

学習データにすでに文字 'A'がある場合、別の文字 'A'を追加することはできません。そのキーAはすでに前の 'A'を保持しています。私はキーAを複数の文字 'A'を保持することができるようにしたかった。

私はここにプログラムのコード全体を掲載するつもりです。これは私のプログラムではなく、Heaton Researchのもので、私はそれを修正しようとしています。少し早いですがお礼を。

public partial class Form1 : Form 
    { 
    /** 
    * The downsample width for the application. 
    */ 
    const int DOWNSAMPLE_WIDTH = 10; 

    /** 
    * The down sample height for the application. 
    */ 
    const int DOWNSAMPLE_HEIGHT = 12; 

    private Bitmap entryImage; 
    private Graphics entryGraphics; 
    private int entryLastX; 
    private int entryLastY; 
    private Pen blackPen; 
    private bool[] downsampled; 
    private Dictionary<char, List<bool[]>> letterData = new Dictionary<Char, List<bool[]>>(); 
    private double[][] trainingSet; 
    private SelfOrganizingMap network; 

    public Form1() 
    { 
     InitializeComponent(); 
     blackPen = new Pen(Color.Black); 
     entryImage = new Bitmap(entry.Width, entry.Height); 
     entryGraphics = Graphics.FromImage(entryImage); 
     downsampled = new bool[Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH]; 
     ClearEntry(); 
    } 

    private void entry_Paint(object sender, PaintEventArgs e) 
    { 
     Graphics g = e.Graphics; 
     g.DrawImage(entryImage, 0, 0); 
     Pen blackPen = new Pen(Color.Black); 
     g.DrawRectangle(blackPen, 0, 0, entry.Width - 1, entry.Height - 1); 

    } 

    private void btnDelete_Click(object sender, EventArgs e) 
    { 
     string str = (string)this.letters.Items[this.letters.SelectedIndex]; 
     char ch = str[0]; 
     this.letterData.Remove(ch); 
     this.letters.Items.Remove(str); 
     ClearEntry(); 
    } 

    private void btnLoad_Click(object sender, EventArgs e) 
    { 
     try 
     { 

      OpenFileDialog openFileDialog1 = new OpenFileDialog(); 
      openFileDialog1.Filter = "Data File (*.dat)|*.dat"; 
      if (openFileDialog1.ShowDialog() == DialogResult.OK) 
      { 

       TextReader f = new StreamReader(openFileDialog1.FileName); 

       String line; 

       this.letterData.Clear(); 
       this.letters.Items.Clear(); 

       while ((line = f.ReadLine()) != null) 
       { 
        int sampleSize = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH; 
        char ch = char.ToUpper(line[0]); 
        bool[] sample = new bool[sampleSize]; 

        int idx = 2; 
        for (int i = 0; i < sampleSize; i++) 
        { 
         if (line[idx++] == '1') 
          sample[i] = true; 
         else 
          sample[i] = false; 
        } 

        this.letterData.Add(ch, sample); 
        this.letters.Items.Add("" + ch); 
       } 

       f.Close(); 
      } 
      MessageBox.Show(this, "File Loaded"); 

     } 
     catch (Exception ex) 
     { 
      MessageBox.Show("Error: " + ex.Message); 
     } 
    } 

    private void btnSave_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      SaveFileDialog saveFileDialog1 = new SaveFileDialog(); 
      saveFileDialog1.Filter = "Data File (*.dat)|*.dat"; 
      if (saveFileDialog1.ShowDialog() == DialogResult.OK) 
      { 
       TextWriter f = new StreamWriter(saveFileDialog1.FileName); 
       int size = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH; 

       for (int i = 0; i < this.letters.Items.Count; i++) 
       { 
        char ch = ((string)this.letters.Items[i])[0]; 
        bool[] data = this.letterData[ch]; 

        f.Write(ch + ":"); 
        for (int j = 0; j < size; j++) 
        { 
         f.Write(data[j] ? "1" : "0"); 

        } 
        f.WriteLine(""); 


       } 
       f.Close(); 

       MessageBox.Show("File Saved"); 

      } 
     } 
     catch (Exception e2) 
     { 
      MessageBox.Show("Error: " + e2.Message, "Training"); 
     } 
    } 

    private void btnBeginTraining_Click(object sender, EventArgs e) 
    { 
     int inputCount = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH; 
     int letterCount = this.letters.Items.Count; 
     this.trainingSet = new double[letterCount][]; 
     int index = 0; 
     foreach (char ch in this.letterData.Keys) 
     { 
      this.trainingSet[index] = new double[inputCount]; 
      bool[] data = this.letterData[ch]; 
      for (int i = 0; i < inputCount; i++) 
      { 
       this.trainingSet[index][i] = data[i] ? 0.5 : -0.5; 
      } 
      index++; 
     } 

     network = new SelfOrganizingMap(inputCount, letterCount, NormalizationType.Z_AXIS); 

     this.ThreadProc(); 

    } 

    private void btnAdd_Click(object sender, EventArgs e) 
    { 
     DownSample ds = new DownSample(this.entryImage); 
     this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT); 
     this.sample.Invalidate(); 
     String Prompt = "Enter the letter you just draw (from the keyboard)"; 
     String Title = "Letter definition Required"; 
     String Default = " "; 
     Int32 XPos = ((SystemInformation.WorkingArea.Width/2) - 200); 
     Int32 YPos = ((SystemInformation.WorkingArea.Height/2) - 100); 

     bool valid = false; 
     for (int i = 0; i < this.downsampled.Length; i++) 
     { 
      if (this.downsampled[i]) 
      { 
       valid = true; 
      } 
     } 


     if (!valid) 
     { 
      MessageBox.Show("Please draw a letter before adding it."); 
      return; 
     } 



     String Result = Microsoft.VisualBasic.Interaction.InputBox(Prompt, Title, Default, XPos, YPos); 
     if (Result != null) 
     { 
      Result = Result.ToUpper(); 
      if (Result.Length == 0) 
      { 
       MessageBox.Show("Please enter a character."); 
      } 
      else if (Result.Length < 1) 
      { 
       MessageBox.Show("Please enter only a single character."); 
      } 
      //else if (this.letterData.ContainsKey(Result[0])) 
      //{ 
      // MessageBox.Show("That letter is already defined, please delete first."); 
      //} 
      else 
      { 
       if (this.letterData.ContainsKey(Result[0])) 
       { 
        this.letterData[Result[0]].Add(this.downsampled); 
       } 
       else 
       { 
        this.letterData.Add(Result[0], new List<bool[]>() {this.downsampled}); 
       } 

       this.letters.Items.Add(Result); 
       //this.letterData.Add(Result[0], this.downsampled); 
       this.ClearEntry(); 
      } 
     } 


    } 

    private void btnRecognize_Click(object sender, EventArgs e) 
    { 
     DownSample ds = new DownSample(this.entryImage); 
     this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT); 
     this.sample.Invalidate(); 

     if (this.network == null) 
     { 
      MessageBox.Show("The program needs to be trained first"); 
      return; 
     } 

     int sampleSize = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH; 
     double[] input = new double[sampleSize]; 

     for (int i = 0; i < sampleSize; i++) 
     { 
      input[i] = this.downsampled[i] ? 0.5 : -0.5; 
     } 

     int best = this.network.Winner(input); 
     char[] map = mapNeurons(); 
     this.result.Text = " " + map[best]; 
     MessageBox.Show(" " + map[best] + " (Neuron #" 
         + best + " fired)", "That Letter You Enter Is"); 
     //ClearEntry(); 
    } 

    private void btnClear_Click(object sender, EventArgs e) 
    { 
     ClearEntry(); 
    } 

    private void btnSample_Click(object sender, EventArgs e) 
    { 
     DownSample ds = new DownSample(this.entryImage); 
     this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT); 
     this.sample.Invalidate(); 
    } 
    public void ClearEntry() 
    { 
     Brush whiteBrush = new SolidBrush(Color.White); 
     entryGraphics.FillRectangle(whiteBrush, 0, 0, entry.Width, entry.Height); 
     entry.Invalidate(); 
     DownSample ds = new DownSample(this.entryImage); 
     this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT); 
     this.sample.Invalidate(); 
    } 

    private void entry_MouseDown(object sender, MouseEventArgs e) 
    { 
     entry.Capture = true; 
     entryLastX = e.X; 
     entryLastY = e.Y; 
    } 

    private void entry_MouseUp(object sender, MouseEventArgs e) 
    { 
     entryGraphics.DrawLine(blackPen, entryLastX, entryLastY, e.X, e.Y); 
     entry.Invalidate(); 
     entry.Capture = false; 
    } 

    private void entry_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (entry.Capture == true) 
     { 
      entryGraphics.DrawLine(blackPen, entryLastX, entryLastY, e.X, e.Y); 
      entry.Invalidate(); 
      entryLastX = e.X; 
      entryLastY = e.Y; 
     } 
    } 

    private void sample_Paint(object sender, PaintEventArgs e) 
    { 
     Graphics g = e.Graphics; 

     int x, y; 
     int vcell = sample.Height/Form1.DOWNSAMPLE_HEIGHT; 
     int hcell = sample.Width/Form1.DOWNSAMPLE_WIDTH; 
     Brush whiteBrush = new SolidBrush(Color.White); 
     Brush blackBrush = new SolidBrush(Color.Black); 
     Pen blackPen = new Pen(Color.Black); 

     g.FillRectangle(whiteBrush, 0, 0, sample.Width, sample.Height); 



     for (y = 0; y < Form1.DOWNSAMPLE_HEIGHT; y++) 
     { 
      g.DrawLine(blackPen, 0, y * vcell, sample.Width, y * vcell); 
     } 
     for (x = 0; x < Form1.DOWNSAMPLE_WIDTH; x++) 
     { 
      g.DrawLine(blackPen, x * hcell, 0, x * hcell, sample.Height); 
     } 

     int index = 0; 
     for (y = 0; y < Form1.DOWNSAMPLE_HEIGHT; y++) 
     { 
      for (x = 0; x < Form1.DOWNSAMPLE_WIDTH; x++) 
      { 
       if (this.downsampled[index++]) 
       { 
        g.FillRectangle(blackBrush, x * hcell, y * vcell, hcell, vcell); 
       } 
      } 
     } 

     g.DrawRectangle(blackPen, 0, 0, sample.Width - 1, sample.Height - 1); 
    } 

    private void letters_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     if (this.letters.SelectedIndex >= 0) 
     { 
      string str = (string)this.letters.Items[this.letters.SelectedIndex]; 
      char ch = str[0]; 
      this.downsampled = this.letterData[ch]; 
      this.sample.Invalidate(); 
     } 
    } 

    public void ThreadProc() 
    { 
     TrainSelfOrganizingMap train = new TrainSelfOrganizingMap(
      this.network, this.trainingSet, TrainSelfOrganizingMap.LearningMethod.SUBTRACTIVE, 0.5); 

     int tries = 1; 

     do 
     { 
      train.Iteration(); 
      this.txtTries.Text = "" + tries; 
      this.txtBestError.Text = "" + train.BestError; 
      this.txtLastError.Text = "" + train.TotalError; 
      tries++; 
      Application.DoEvents(); 
     } while (train.TotalError > 0.01 && (tries <= 100)); 
     MessageBox.Show("Training complete."); 
    } 

    /** 
    * Used to map neurons to actual letters. 
    * 
    * @return The current mapping between neurons and letters as an array. 
    */ 
    public char[] mapNeurons() 
    { 
     char[] map = new char[this.letters.Items.Count]; 

     for (int i = 0; i < map.Length; i++) 
     { 
      map[i] = '?'; 
     } 
     for (int i = 0; i < this.letters.Items.Count; i++) 
     { 
      double[] input = new double[Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH]; 
      char ch = ((string)(this.letters.Items[i]))[0]; 
      bool[] data = this.letterData[ch]; 
      for (int j = 0; j < input.Length; j++) 
      { 
       input[j] = data[j] ? 0.5 : -0.5; 
      } 

      int best = this.network.Winner(input); 
      map[best] = ch; 
     } 
     return map; 
    } 

} 
+1

'valid'を' true'に設定した後、ループから '中断してはいけませんか? – ChaosPandion

答えて

2

Dictionary<>は、あなたが最も効率的な方法でキーと値のペアにアクセスできるように作成されます。今度はDictionary<>に同じキーで2つのペアを持つことはできません。これを行うには、 何ができるのですか?Dictionary<char, List<bool[]>>のような辞書を作成します。ここでは、複数の値を持つ1つのキーを保存することができます。

更新

複数の値を持つ一つのキーを格納するために、その後Dictionary<char, List<bool[]>>に辞書を変更する場合は、キーとしてstringしたい場合は、代わりに、

private bool[] downsampled; 
private Dictionary<char, List<bool[]>> letterData = new Dictionary<Char, List<bool[]>>(); 

// 
//  Your Code 
// 

if (Result != null) 
{ 
    Result = Result.ToUpper(); 
    if (Result.Length == 0) 
    { 
     MessageBox.Show("Please enter a character."); 
    } 
    else if (Result.Length < 1) 
    { 
     MessageBox.Show("Please enter only a single character."); 
    } 
    else 
    { 
     if (this.letterData.ContainsKey(Result[0])) 
     { 
      this.letterData[Result[0]].Add(this.downsampled); 
     } 
     else 
     { 
      this.letterData.Add(Result[0], new List<bool[]>() { this.downsampled }); 
     } 
     this.letters.Items.Add(Result);    
     this.ClearEntry(); 
    } 
} 

を次のようになりますcharの場合、Dictionary<string, List<bool[]>>を使用します。

これはあなたの質問にお答えします。

+0

それは間違いなく私がそれを行うつもりである方法ですが、私はそれを行う方法がわかりません – hafizhans

+0

そのオプションの横に、 '文字'に '文字'を変更することを考えていたので、 'A1'、 'A2'などを保持できますが、多くの 'char'が 'string'エラーになります – hafizhans

+0

複数のbool値を含む1つのcharを追加しますか?複数のbool []を持つ1つのchar? –

0

.NETのLookupクラスを見てください。これにより、同じ「キー」値を複数回持つことができます。

+0

いいですが、そのクラスにはpublicコンストラクタもありません。 – leppie

+0

@hafizhans対話型デバッグセッションとしてStack Overflowを使用しないでください。 Moreso、コメントでそれをやめてください。あなたが本当の、解決可能な問題について特定の質問をしているなら、質問*として投稿してください。 – casperOne

+0

私は何かを尋ねることができると思って、私はまだこのウェブサイトの新しい、次回より専門的になると思う。 tq – hafizhans

関連する問題