8

AForge.NET フレームワークを使用して誰かが色検出を行っていることを示す、http://www.youtube.com/watch? v=Ha5LficiSJM のこの YouTube ビデオを偶然見つけました。その作者が行ったことを複製したいのですが、画像処理を行う方法がわかりません。

AForge.NET フレームワークを使用すると、ビデオ ソースからビットマップ形式の画像を取得できるようです。私の質問は、誰かが私を方向に向けたり、特定の色を見つけるために Bitmap オブジェクトに問い合わせる方法についてのガイダンスを提供したりできますか? (たとえば、画像に「赤」または「紫」が X 秒間存在する場合、「ColorDetected」などのイベントを発生させたいと思います...)

どこから始めるべきかについて誰か提案がありますか?

ありがとう、

-R.

編集: Bitmap オブジェクト全体を調べて、各ピクセルの色を調べる必要がありますか? そのように:http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.getpixel.aspx

4

2 に答える 2

21

そうですね、いつでも GDI+ メソッドを使用できます。

Bitmap b = new Bitmap( "some path" );
Color x = b.GetPixel( x, y );

ただし、GetPixel は実際にはかなり遅いです。最初はその方法で試してみてください。ただし、比較的大きな画像を多数スキャンする必要がある場合は、うまくいかない可能性があります。その場合は、LockBits を使用して、連続したメモリ チャンクへのポインタを取得します。その後、画像をすばやくループできますが、ポインターの操作方法を知っている必要がありますが、それほど複雑ではありません。

編集: LockBits を使用して各ピクセルを調べる:

Bitmap b = new Bitmap( "some path" );
BitmapData data = b.LockBits( new Rectangle( 0, 0, b.Width, b.Height ),
ImageLockMode.ReadOnly, b.PixelFormat );  // make sure you check the pixel format as you will be looking directly at memory

unsafe
{         
    // example assumes 24bpp image.  You need to verify your pixel depth
    // loop by row for better data locality
    for( int y = 0; y < data.Height; ++y )
    {
        byte* pRow = (byte*)data.Scan0 + y * data.Stride;
        for( int x = 0; x < data.Width; ++x )
        {
            // windows stores images in BGR pixel order
            byte r = pRow[2];
            byte g = pRow[1];
            byte b = pRow[0];

            // next pixel in the row
            pRow += 3;
        }
    }
}

b.UnlockBits(data);

画像が最後にパディングされている場合は、BitmapData.Stride プロパティを使用して、新しい各行の先頭に到達できます (そうしないと、がらくたを読み取ることになり、オフセットが厄介になります)。

于 2010-09-25T19:41:21.470 に答える
5

Ed Swangrenの答えに加えてLockBits、ポインターをすべて一緒に回避できます。WPF を使用している (またはアクセスできる) 場合は、次のようなことができます。

var bitmap = new BitmapImage(uri);

//Pixel array
byte[] pixels = new byte[width * height * 4]; //account for stride if necessary

bitmap.CopyPixels(..size, pixels, fullStride, 0); 

pixelsこれで、ポインターなしで通常の配列スキャンを実行できるようになりました。このスニペットは数年前のもので、私が独自の AmbiLight ソリューションを開発したプロジェクトからのものなので、かなり高速です。繰り返しますが、これは数年前のものなので、WriteableBitmapなどの新しいクラスの方が優れており、配列のコピーを避けることができます。最初のソリューションではポインターを使用していましたが、ポインターが不要であることがわかったときに切り替えました。

于 2010-09-25T19:54:56.650 に答える