2

スコープ:

こんにちは皆さん、私はこのキャプチャを「白黒」(二値化)画像に変換しようとしています。ここで、文字は白で、残り全体(背景、線、ランダムな写真)は黒です。

キャプチャへのリンクはここにあります。更新すると、別のキャプチャが表示されます。

理由:

ほとんどの人がキャプチャをいじるのは間違っていると思っていることを知っているので、ここで私は自分自身を弁護しています. これは、知識/自己挑戦のみに使用されます。これらの画像を他の用途に使用する予定はありません。

問題:

これらの画像をしばらく調べた後、色を「白と黄」を「Color.Black」に置き換え、他のすべての色を「Color.White」に置き換えるのが良いアプローチであることがわかりました。

この後、色を「反転」して、必要な出力に導きます。

コードサンプル:

このコードでは、すべての画像の色「黒」を SkyBlue ピクセルに置き換えようとしています。

        WebRequests wr = new WebRequests(); // My class to handle WebRequests
        Bitmap bmp;
        string url = "http://www.fazenda.rj.gov.br/projetoCPS/codigoImagem";

        bmp = wr.GetBitmap (url);

        for (int i = 1; i < bmp.Height ; i++)
        {
            for (int j = 1 ; j < bmp.Width ; j++)
            {
                if (bmp.GetPixel(j,i).Equals(Color.Black))
                {
                    bmp.SetPixel(j,i, Color.SkyBlue);
                }
            }
        }

このコードはまったく機能しません。理由はわかりませんが、この例ではピクセルが置き換えられていません。

質問:

どうすればこれを機能させることができますか? ここで何が欠けていますか?

また、私にとって理想的なシナリオは、この画像のカラーパレットを「基本的な」色に「減らす」ことです。これにより、ここでの仕事がはるかに簡単になります。

色を減らすために使用しているAForge Frameworkを既に試しましたが、まったく機能していません。結果は期待したものではありません。

この画像を正しく二値化するために、ここで何ができますか?

前もって感謝します、

マルチェロ・リンス。

4

1 に答える 1

1

アルゴリズムが機能しない理由は、完全に一致するものを探しているためです。ただし、JPEG圧縮アーティファクトが原因で、画像の黒は実際には黒ではありません。私がロードした3つのCAPTCHAには、黒(0、0、0)のピクセルが1つもありませんでした。最も近い値は(0、0、4)で、黒く見えますが、そうではありません。

おおよそのアプローチは次のようになります。

  • チャネル平均が220未満のすべてのグレー(チャネルの差が5%未満)をグレーで削除します。これにより、薄い灰色の線と、灰色の背景に対するリンギング(JPEG)アーティファクトの多くが削除されます。
  • 赤、緑、または青のチャネルが他の2つのチャネルより25%以上上にあるすべてのピクセルを、灰色に置き換えます。これにより、赤、緑、青、およびそれらのリンギングアーティファクトのほとんどが処理されます。
  • 単純なスペックル除去を実行して、5つのグレーで囲まれ、同じ色の他のピクセルが20%以内にないすべての非グレーピクセルを削除します。

このプロセスの最後に、背景はすべて灰色になり、残りの灰色以外のピクセルはすべて文字になります。

いくつかの便利な機能:

// Very basic (and CIE-incorrect) check
public static int isGray(Color c)
{
    if (Math.Abs(c.R - c.G) > 5 * 2.55) return 0; // Not gray. R and G too different
    if (Math.Abs(c.R - c.B) > 5 * 2.55) return 0;
    if (Math.Abs(c.G - c.B) > 5 * 2.55) return 0;
    return 1;
}

// the blind man's test for shading :-)
public static int isShadeOfRed(Color c)
{
    if (4*c.R < 5*c.G) return 0; // Red not strong enough in respect to green
    if (4*c.R < 5*c.B) return 0; // Red not strong enough in respect to blue
    return 1; // Red is stronger enough than green and blue to be called "shade of red"
}

// (shades of green and blue left as an exercise)

// Very basic (and CIE-incorrect) check
public static int areSameColor(Color a, Color b)
{
    if (Math.Abs(a.R - b.R) > 5 * 2.55) return 0;
    if (Math.Abs(a.G - b.G) > 5 * 2.55) return 0; 
    if (Math.Abs(a.B - b.B) > 5 * 2.55) return 0;
    return 1; // "more or less" the same color
}

// This is more or less pseudo code...
public static int isNoise(int x, int y)
{
    if ((x < 1) || (y < 1)) return 0; // or maybe "return 1"
    if ((x+1 >= bmp.Width)||(y+1 >= bmp.Height)) return 0;
    pix = bmp.GetPixel(x,y);
    for (i = -1; i <= 1; i++)
        for (j = -1; j <= 1; j++)
        {
            if ((i == 0) && (j == 0)) continue;
            test = bmp.GetPixel(x+i, y+j);
            if (isGray(test)) grays++;
            if (isSameColor(pix, test)) same++;
        }
    // Pixel surrounded by grays, and has no neighbours of the same colour
    // (who knows, maybe we could skip gray calculation and check altogether?)
    // is noise.
    if ((grays == 5) && (same == 0))
       return 1;
    return 0;
}

// NOTE: do not immediately set to gray pixels found to be noise, for their neighbours
// will be calculated using the new gray pixel. Damage to image might result.
// Use a copy of bmp instead.
于 2012-09-17T21:11:46.177 に答える