hello_world.py

"Doing good is part of our code"

画像処理 with Visual Studio(C#)

f:id:tanajun99:20150701004022j:plain

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構造体を作成する。うえの例では白黒にしている。

処理後画像

f:id:tanajun99:20150701013652j:plain


処理前画像

f:id:tanajun99:20150701013659j:plain


次は二値化。ピクセル値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");
        }
    }

処理後画像

f:id:tanajun99:20150701020938j:plain

とりあえずこの処理をスクロールバーを用いて処理できるようなアプリにします。

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;              
        }
    }
}

スクショ

f:id:tanajun99:20150704184907p:plain

バイオインフォマティクスぶって、実験で使用したMRI画像にしてみました。
スクロール値で二値化する閾値を決定し、それに伴い画像が変化します。

続きは次回!!