トップ 差分 一覧 ソース 検索 ヘルプ PDF RSS ログイン

C#/画像処理

一部の情報は非常に古いもの(20年以上前〜)ですので、利用する際はご注意ください(Java 1.4 とか .NET 1.0 とか、Windows 2000 とか)
お問い合せは wiki@shise.net まで。Gmail に転送されるので、スパムは全部カットされます。


 

最初に補足

このページでは、C# 単体で画像のグレースケール変換を行っています。

画像の複雑な処理、画像の認識などの場合は OpenCV を利用すると良いと思います(外部 DLL 使います)

参考 URL:
schima.hatenablog.com - OpenCvSharpをつかう
C# で画像の中に一致するパターンがあるか探す


まず

画像処理をしたいと思った。
Bitmap クラスには、GetPixel 、SetPixel というメソッドがあるので、それを使って一ピクセルずつ処理してみた。

が!!!

これがまたクソ遅い。半端じゃない。
なので、バイト列をいぢって画像を操作する方法を検索して、出来たのでメモ。

ちなみに、ピクセル操作と、バイト列操作では、100 倍くらい処理時間が違う。
SetPixel、GetPixel を使って処理すると、9000ms かかるが、
バイト列を取り出して操作すると、90ms で終わる、といった具合。

int 型とかビットシフトとかで演算してるけど、浮動小数点の演算が得意な CPU があるとか無いとかで、下手に int でやるより float でやったほうが早いとの話もあるが、試してないのでよく分からない。

・・・・・・・・・・てか、
画像処理は MSDN に、ちゃんとサンプルあったし。(ノ∀`)ペチッ
http://msdn.microsoft.com/ja-jp/library/system.drawing.imaging.bitmapdata.scan0.aspx

グレイスケール化

using System;
using System.Drawing; // 参照設定に System.Drawing を追加する必要アリ
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

// 画面キャプチャ
Bitmap bmp = ScreenCapturer.CaptureDesktopImage();

// 画像データをメモリ上に固定?
BitmapData bmpdata = bmp.LockBits(
    new Rectangle(0, 0, bmp.Width, bmp.Height),
    ImageLockMode.ReadWrite,
    PixelFormat.Format32bppArgb
);

// グレイスケール用のアレ
int rp = (int)(0.298912 * 1024);
int gp = (int)(0.586611 * 1024);
int bp = (int)(0.114478 * 1024);

// バイト配列にコピー
byte[] ba = new byte[bmp.Width * bmp.Height * 4];
Marshal.Copy(bmpdata.Scan0, ba, 0, ba.Length);

// 処理
int pixsize = bmp.Width * bmp.Height * 4;
for (int i = 0; i < pixsize; i += 4)
{
    // 画像のバイト列って、ARGB じゃなくて、BGRAになってるっぽい??
    // リトルエンディアンか。
    byte g = (byte)((bp * ba[i + 0] + gp * ba[i + 1] + rp * ba[i + 2]) >> 10);
    ba[i + 0] = g;      // ブルー
    ba[i + 1] = g;      // グリーン
    ba[i + 2] = g;      // レッド
    ba[i + 3] = 0xFF;   // アルファ
}

// 元のところに書き込む。
Marshal.Copy(ba, 0, bmpdata.Scan0, ba.Length);

bmp.UnlockBits(bmpdata);

これで、bmp は、グレイスケール化されました。
めでたしめでたし。

ちなみに、ScreenCapturer は、どこかこのへんからコピってきた、C# でスクリーンキャプチャー(スクリーンショット?)とれるやつ。