【C#】画像の輝度値の取得

C#で画像ファイルの輝度値を取得するにはLockBits~UnlockBitsでポインタを取得して配列へコピーするなどするのが、C#では定番となっています。

例えば、下記のようなサンプルコード

var bmp = new Bitmap("01.png");

// Bitmapをロック
var bmpData = bmp.LockBits(
        new Rectangle(0, 0, bmp.Width, bmp.Height),
        System.Drawing.Imaging.ImageLockMode.ReadWrite,
        bmp.PixelFormat
    );

// メモリの幅のバイト数を取得
var stride = Math.Abs(bmpData.Stride);

// 画像データ格納用配列
var data = new byte[stride * bmpData.Height];

// Bitmapデータを配列へコピー
System.Runtime.InteropServices.Marshal.Copy(
    bmpData.Scan0,
    data,
    0,
    stride * bmpData.Height
    );

// アンロック
bmp.UnlockBits(bmpData);

このプログラムで、ほとんどの場合、問題ない事が多いのですが、モノクロ8Bitのpng画像ファイルを開くと、なぜか?32bitカラーの画像として認識してしまいます。

(評価に用いた画像) Deep Learningでは定番のMNISTの手書き文字に似せて作成した8bitモノクロ画像
csharp_get_bright

(デバッグ画面)もとの画像は8bitモノクロ画像ですが、PixelFormatがFormat32bppArgbになっています。

csharp_get_bright

8bitの画像が32bitとして認識してしまうという事は、無駄に画像データが4倍大きくなってしまうので、画像処理的には処理速度的にも不都合が起こります。

そこで、私は基本WindowsFormsを使っているのですが、クラスだけWPFのクラスを使う事で問題を解決します。

WPFのクラスを用いるにはプロジェクトの参照から
csharp_get_bright

下記の2つを追加します。

PresentationCore
WindowsBase

csharp_get_bright

これでWPFのクラスが使えるようになります。
そこで、最初に書いたBitmapクラスを用いたプログラムと同等のことをWPFのクラスを用いて作成すると

byte[] data;

using (var fs = new System.IO.FileStream("01.png", System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
    var bitmapFrame = System.Windows.Media.Imaging.BitmapFrame.Create(
        fs,
        System.Windows.Media.Imaging.BitmapCreateOptions.PreservePixelFormat,
        System.Windows.Media.Imaging.BitmapCacheOption.Default
        );

    int stride = ((bitmapFrame.PixelWidth * bitmapFrame.Format.BitsPerPixel + 31) / 32) * 4;

    // 画像データ格納用配列
    data = new byte[stride * bitmapFrame.PixelHeight];

    // 輝度データを配列へコピー
    bitmapFrame.CopyPixels(data, stride, 0);
}

となります。

これでFormatもGray8となり、正しいサイズで画像データを取得できるようになります。

csharp_get_bright

画像処理のためのC#テクニックへ戻る

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

関連記事

関連記事

関連記事
スポンサーリンク

同一カテゴリ人気記事