【C#】画像の2値化(閾値固定)
画像処理として、2値化をやってみる
※閾値を固定にしています。いつか判別分析で求めてみたい。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; namespace TestImage { public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// Formロード時処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Load(object sender, EventArgs e) { // 元の画像を表示(左) string imagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "test.jpg"); pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; pictureBox1.ImageLocation = imagePath; // 変換後の画像を表示(右) pictureBox2.SizeMode = PictureBoxSizeMode.Zoom; Bitmap img = new Bitmap(imagePath); CreateImage(img); pictureBox2.Image = img; } /// <summary> /// 画像を2値化する(24ビット画像のみ) /// </summary> /// <param name="srcImg">変換する画像</param> public void CreateImage(Bitmap srcImg) { BitmapData srcData = null; try { //===================================================================== // 変換する画像の1ピクセルあたりのバイト数を取得 //===================================================================== PixelFormat pixelFormat = srcImg.PixelFormat; int pixelSize = Image.GetPixelFormatSize(pixelFormat) / 8; //===================================================================== // 変換する画像データをアンマネージ配列にコピー //===================================================================== srcData = srcImg.LockBits( new Rectangle(0, 0, srcImg.Width, srcImg.Height), ImageLockMode.ReadWrite, pixelFormat); byte[] buf = new byte[srcData.Stride * srcData.Height]; Marshal.Copy(srcData.Scan0, buf, 0, buf.Length); //===================================================================== // 2値化 //===================================================================== for (int y = 0; y < srcData.Height; y++) { for (int x = 0; x < srcData.Width; x++) { // ピクセルで考えた場合の開始位置を計算する int pos = y * srcData.Stride + x * pixelSize; // ピクセルの輝度を算出 int gray = (int)(0.299 * buf[pos + 2] + 0.587 * buf[pos + 1] + 0.114 * buf[pos]); if (gray > 127) { // 閾値を超えた場合、白 buf[pos] = 0xFF; buf[pos + 1] = 0xFF; buf[pos + 2] = 0xFF; } else { // 閾値以下の場合、黒 buf[pos] = 0x0; buf[pos + 1] = 0x0; buf[pos + 2] = 0x0; } } } Marshal.Copy(buf, 0, srcData.Scan0, buf.Length); } catch (Exception ex) { MessageBox.Show(ex.Message); } finally { if (srcImg != null && srcData != null) { srcImg.UnlockBits(srcData); } } } } }
結果は以下の通り
閾値をちゃんとしないとダメですね。。