少し前に、かなり有名なサイトからファイルを自動的にダウンロードするプログラムを作成しなければなりませんでした。 問題は、一見すると、キャプチャがあったことです。 しかし、それを一目で理解するのに十分であり、すぐに解決しました:)数年後、私は再びそのプロジェクトに出会い、ハブに置くことにしました。 すぐに予約します。キャプチャはまだ存在しているため、電話をかけません。
ステージ1:情報の収集
何よりもまず、キャプチャ画像でアドレスを取得し、受信した画像を別のフォルダに保存する簡単なプログラムが作成されました。 プログラムがプルした50枚の画像を見ると、思ったよりも簡単だとわかりました。
見て、これらはキャプチャの例です:
色はほとんどなく、背景の色と数字自体は時々変更されますが、数字の面ははっきりと見え、ノイズはありません。 したがって、私は最も単純なソリューション-最も単純なマスク分析を選択しました。
ステージ2:初期画像分析、マスク作成
マスクを作成するには、2色の画像を作成する必要があります。 これを行うために、別のプログラムがサイトから画像をダウンロードするプログラムに書き込まれ、画像を取得し、画像に存在する色を計算し、各色の代わりに白い背景+黒マスクをカットしました。 画像を解析した後、いくつかのディスクが取得され、そのうちの1つにキャプチャで使用されているシンボルが明確に表示されました。
これらの画像の例を示します。
ここでは、最も一般的な色のみのマスクを用意しました。 余分な部分を取り除くために、フォーム上の25ピクセル未満を含むすべての色をマスクから削除しました。 原則として、キャプチャに25ピクセル未満を占める1〜2文字がある場合、マークを逃すことができますが、このキャプチャにはそのような画像は見られず、気にしませんでした。
したがって、最後の表示では、実際にマスクを持っていることがわかります。 エディターでは次のようになりますが、完全にクリーンです。
カラーマスクオプションを引き出したコードを示します。
public Bitmap ClearBitmap(Bitmap input, Color clr) { var result = new Bitmap(input.Width, input.Height); for (var x = 0; x < input.Width; x++) { for (var y = 0; y < input.Height; y++) { var color = input.GetPixel(x, y); result.SetPixel(x, y, clr == color ? Color.Black : Color.White); } } return result; } public void Main() { var bitmap = new Bitmap("D:\\check_image1227.png"); var palette = new Dictionary<Color, int>(); for (var x = 0; x < bitmap.Width; x++) { for (var y = 0; y < bitmap.Height; y++) { var clr = bitmap.GetPixel(x, y); if (!palette.ContainsKey(clr)) { palette.Add(clr, 1); } else { palette[clr] = palette[clr] + 1; } } } var i = 0; foreach (var c in palette) { if (c.Value > 30) { var temp = this.ClearBitmap(bitmap, c.Key); temp.Save(String.Format("D:\\mask-{0}.bmp", i)); i++; } } }
ステージ3:戦闘へ!
上記のコードの動作を見たとき、キャプチャで使用されるすべての数字を収集して続行するだけです。 これを行うために、200枚の画像を取得するためにキャプチャ画像を保存するプログラムが起動されました。 取得した画像から、すべてのメインキャラクターが表示され、上記のコードを使用してマスクが取得された画像を選択しました。 この作業の結果は次のようになりました。
何らかの理由で、シンボル9はキャプチャで使用されませんでしたが、問題ではありません。 残りは簡単です。 各数値を正方形に取り、右側が最小ビット、左側が最大ビットです。 8086でアセンブラーを使用し、キャラクターマスクを実行した人は私を理解しますが、残りは例です:
上の画像では、ビット番号が設定されており、右側が完成した番号です。 さらに明確にするために、黒い点を1、白い点をゼロに置き換えます。 たとえば、バイナリの指定された番号の一番上の行は0001111111000のようになります。 1016から10進数。 マトリックスを記述する配列が各桁ごとに作成されました。
さらなるアルゴリズムはこのように見えました。 結果として生じる画像を、上部、下部、および側面の白い点からクリアする関数が作成されました。 また、指定された領域を表す数値の配列を返す関数が作成されました。 その後、すべてが簡単になりました。 すべてが自動的に行われたため、画像をクリーンアップして不要なデータを切り取った後、画像の高さが桁のサイズより下に収まることを確認するためにチェックを行いました(この場合、桁を探すのが理にかなっています)。 その後、左から右へのサイクルで、各数字の領域が一致するまで比較されました。 数字は一致しました->文字幅の右側の画像を移動します。 次のエリアなどを確認してください。 その結果、すべてがそれほど速くないことが判明しました。プロジェクトを添付して、自分で確認できるようにしますが、ソリューションは100%正しく認識されたキャプチャを返しました。
PS強くプロジェクトコードを蹴らないでください。長い間、そしてスピードのために書かれています。 多くを最適化することができますが、もちろん興味深いのであれば、これはすでにあなたのためのタスクです:)
PPSそれでも同じように、サイトのアドレスを指定しても何も変わらないと思います
。cracks.msでしたVS2010のプロジェクト