画像処理 with Visual Studio(C#)
Mac派なのですが、今回はC#の画像処理のまとめを書きたいので、Visual Studioを使ってWindowsから更新したいと思います。
フォントの違和感がすごい。。。。
画像処理の原理
画像処理は基本的には、ピクセル(コンピュータで画像処理を扱うときの色情報をもつ最小単位、最小要素)を数値としてとらえ、それを行列的に処理することで不要な要素を削除したり、重要な要素を抽出したりします。
今回は基本となる二値化と画像の合成ができるアプリケーションを作成したいと思います。
まずはBitmapで画像を読み込み、画像のデータを取得する。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Imaging; class Program { static void Main(string[] args) { Bitmap src = new Bitmap("microsoft.jpg");//ファイル読み込み int width = src.Width; //ピクセル数 int height = src.Height; //ピクセル数 Bitmap dest = new Bitmap(src, width, height);//画像の作成 dest.Save("img02.jpg");//ファイルの書き出し } }
次に、取得したピクセル値等を使用してがぞうを加工してみる。
class Program { static void Main(string[] args) { Bitmap src = new Bitmap("microsoft.jpg"); Bitmap image = new Bitmap(src); int width = src.Width; int height = src.Height; Color col; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { col = src.GetPixel(i, j); int gray = col.R; image.SetPixel(i, j, Color.FromArgb(gray, gray, gray)); } } image.Save("img02.jpg"); } }
上のメソッドについて、GetPixelメソッドでピクセル値を獲得し、SetPixelメソッドでピクセル値を設定している。FromArgsメソッドはRGB成分からColor構造体を作成する。うえの例では白黒にしている。
処理後画像
処理前画像
次は二値化。ピクセル値0-255のあたいを150以上なら255、150以下なら0にし、画像として出力する。
class Program { static void Main(string[] args) { Bitmap src = new Bitmap("microsoft.jpg"); Bitmap image = new Bitmap(src); int width = src.Width; int height = src.Height; Color col; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { col = src.GetPixel(i, j); int gray = col.R; if (gray > 150) { gray = 255; } else { gray = 0; } image.SetPixel(i, j, Color.FromArgb(gray, gray, gray)); } } image.Save("img02.jpg"); } }
処理後画像
とりあえずこの処理をスクロールバーを用いて処理できるようなアプリにします。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace No1114 { public partial class Form1 : Form { OpenFileDialog openFileDialog1 = new OpenFileDialog(); Bitmap bitmap1; public Form1() { InitializeComponent(); } private void openToolStripMenuItem_Click(object sender, EventArgs e) { // ダイアログのタイトルを設定する openFileDialog1.Title = "画像選択"; // 初期表示するディレクトリを設定する openFileDialog1.InitialDirectory = @"C:¥"; // 初期表示するファイル名を設定する openFileDialog1.FileName = "img.jpg"; // ファイルのフィルタを設定する openFileDialog1.Filter = "テキスト ファイル|*.txt;*.log|すべてのファイル|*.*"; // ファイルの種類 の初期設定を 2 番目に設定する (初期値 1) openFileDialog1.FilterIndex = 2; // ダイアログボックスを閉じる前に現在のディレクトリを復元する(初期値 false) openFileDialog1.RestoreDirectory = true; // 複数のファイルを選択可能にする (初期値 false) openFileDialog1.Multiselect = true; // [ヘルプ] ボタンを表示する (初期値 false) openFileDialog1.ShowHelp = true; // [読み取り専用] チェックボックスを表示する (初期値 false) openFileDialog1.ShowReadOnly = true; // [読み取り専用] チェックボックスをオンにする (初期値false) openFileDialog1.ReadOnlyChecked = true; // 存在しないファイルを指定した場合は警告を表示する (初期値 true) openFileDialog1.CheckFileExists = true; // 存在しないパスを指定した場合は警告を表示する (初期値true) openFileDialog1.CheckPathExists = true; // 拡張子を指定しない場合は自動的に拡張子を付加する (初期値 true) openFileDialog1.AddExtension = true; // ダイアログを表示し、戻り値が [OK] の場合は、選択したファイルを表示する if (openFileDialog1.ShowDialog() == DialogResult.OK) { MessageBox.Show(openFileDialog1.FileName); // Multiselect が true の場合はこのように列挙する //foreach (string nFileName in openFileDialog1.FileNames) { // MessageBox.Show(nFileName); //}} // 不要になった時点で破棄する (正しくは オブジェクトの破棄を保証する を参照) openFileDialog1.Dispose(); } openFileDialog1.RestoreDirectory = true; if (openFileDialog1.ShowDialog() == DialogResult.OK) { bitmap1 = new Bitmap(openFileDialog1.FileName); pictureBox1.Image = bitmap1; } } private void hScrollBar1_Scroll(object sender, ScrollEventArgs e) { hScrollBar1.Minimum = 0; hScrollBar1.Maximum = 254 + hScrollBar1.LargeChange; label1.Text = Convert.ToString(hScrollBar1.Value); Bitmap outBit = new Bitmap(bitmap1); int width = bitmap1.Width; int height = bitmap1.Height; Color col; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { col = bitmap1.GetPixel(i, j); int co = col.R; if (co < hScrollBar1.Value) { co = 0; } else { co = 255; } outBit.SetPixel(i, j, Color.FromArgb(co, co, co)); } } pictureBox2.Image = outBit; } } }
スクショ
バイオインフォマティクスぶって、実験で使用したMRI画像にしてみました。
スクロール値で二値化する閾値を決定し、それに伴い画像が変化します。
続きは次回!!