3

画像があり、Martix を使用してすべてのピクセルの色を読み取ることができます...ピクセルの RGB を変更するにはどうすればよいですか (黒、赤、または白) から最も近い色に変換したい場合

マトリックスで画像を読み取るための私のコードは次のとおりです。

string sourceimg = @"D:\ProductionTools\Taskes\Image Processing\Test\001.jpg";
//...
Bitmap imageoriginal = new Bitmap(sourceimg);
int height = imageoriginal.Height;
int width = imageoriginal.Width;
Color[][] colormatrix = new Color[width][];
for (int i = 0; i < width; i++) {
    colormatrix[i] = new Color[height];
    for (int j = 0; j < height; j++) {
        colormatrix[i][j] = new Color();
        colormatrix[i][j] = imageoriginal.GetPixel(i, j);
    }
}  
4

2 に答える 2

5

あなたのコメントで指摘されているように、問題は色の距離についてであり、それは些細なことではありません。また、使用する色空間にも関係するため、ここではRGB、HSV、HLS、およびCIELABの例を示します。また、距離を計算するには、数式が必要です。簡単にするために、次のようにユークリッド距離に固執しましょう。ここに画像の説明を入力してください

次に、質問に簡単に答えるために、現在の色qから3つのターゲットpi(黒、赤、白)までの距離を計算します。最小距離は、置き換える色を示します。同点の場合は、最短距離の最も早い色を使用します。

さて、色空間はユークリッド距離の意味を確立するので、このタスクでも非常に重要です。サンプル画像は次のとおりです。

ここに画像の説明を入力してください

RGBに変換:

ここに画像の説明を入力してください

HLSで変換(つまり、RGBカラーがHLSに変換され、距離が計算されます):

ここに画像の説明を入力してください

HSV:

ここに画像の説明を入力してください

CIELAB:

ここに画像の説明を入力してください

于 2013-01-09T14:55:54.563 に答える
1

指摘されているように、この問題の最も難しい部分は、特定の色が黒、白、または赤に「近い」かどうかを知ることです。私はあなたのために働くかもしれない何かを一緒に投げました:

Color GetNearestOfBWR(Color c)
{
     float redness = Math.Abs(180 - c.GetHue()) / 180;
     float brightness = c.GetBrightness();
     float saturation = c.GetSaturation();

それぞれ 0 から 1 の間の 3 つの値があり、0 から 1 に増加すると、赤に近づくことを意味します (大まかに言えば、赤を増やす/緑と青を減らす、色を増やす/黒を減らす、色を増やす/灰色を減らす)。

どの時点で色が「赤」を構成するかを決定する必要があり、正直なところ、それは判断の呼びかけです. あなたは単に持つことができます

     double brightColourfulRedness = Math.Sqrt(
         redness*redness + brightness*brightness + saturation*saturation);
     if (brightColourfulRedness > 1)
         return Color.FromArgb(255, 0, 0); // red;

(単純なユークリッド ノルム) しかし、特定のプロパティを別のプロパティよりも強く重み付けしたり、単に1しきい値を変更したりしたい場合があります。

次に、何を黒または白にマップするかを決定する必要があります。これは次のように簡単です

    if (brightness > 0.5)
        return Color.FromArgb(255, 255, 255); // white
    return Color.FromArgb(0, 0, 0); // black
}

すごい!これで、好みに応じて色を赤、白、または黒にマッピングする関数ができました。あとは、ビットマップの各ピクセルに適用するだけです。ファイルからロードした を上書きしてBitmapも問題ない場合は、配列は必要ありません。あなたはただ行うことができます:

int height = imageoriginal.Height;
int width = imageoriginal.Width;
for (int i = 0; i < width; i++)
{
    for (int j = 0; j < height; j++)
    {
        Color origC = imageoriginal.GetPixel(i, j);
        Color newC = GetNearestOfBWR(origC);
        imageoriginal.SetPixel(i, j, newC);
    }
}

これは非常に遅くなる可能性があるため、代わりに DmitryG のLockBitsコードを使用することもできますが、提供される と が必要とする の間で変換する必要がありintます。(そしてこれを行う、と私は信じています。)ColorGetNearestOfBWRFromArgbToArgb

于 2013-01-09T14:46:02.343 に答える