C#で簡単に始める画像処理: 基本と応用

C#での画像処理の基本を学び、実際のプロジェクトで活用するための基礎知識とサンプルコードを紹介します。

目次

画像の読み込みと表示

C#で画像を読み込み、表示する方法について解説します。

画像の読み込み

C#で画像を読み込むためには、System.Drawing名前空間を使用します。以下は、画像を読み込む基本的なコード例です。

using System;
using System.Drawing;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Image image = Image.FromFile(imagePath);
        Console.WriteLine("画像が正常に読み込まれました。");
    }
}

画像の表示

コンソールアプリケーションでは画像を直接表示することはできませんが、Windows Formsアプリケーションを使用することで画像を表示できます。以下は、Windows Formsで画像を表示する例です。

using System;
using System.Drawing;
using System.Windows.Forms;

class Program : Form
{
    private PictureBox pictureBox;

    public Program()
    {
        pictureBox = new PictureBox
        {
            Dock = DockStyle.Fill,
            Image = Image.FromFile("path_to_your_image.jpg"),
            SizeMode = PictureBoxSizeMode.Zoom
        };
        Controls.Add(pictureBox);
    }

    static void Main()
    {
        Application.Run(new Program());
    }
}

このコードを実行すると、指定した画像がフォームに表示されます。これで画像の読み込みと表示の基本を理解できました。

画像の基本操作

画像の回転、反転、リサイズなどの基本操作を学びます。

画像の回転

C#で画像を回転させるには、ImageクラスのRotateFlipメソッドを使用します。以下は、画像を90度回転させる例です。

using System;
using System.Drawing;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Image image = Image.FromFile(imagePath);
        image.RotateFlip(RotateFlipType.Rotate90FlipNone);
        image.Save("rotated_image.jpg");
        Console.WriteLine("画像を90度回転させました。");
    }
}

画像の反転

画像を水平または垂直に反転させるには、同じRotateFlipメソッドを使用します。以下は、画像を水平に反転させる例です。

using System;
using System.Drawing;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Image image = Image.FromFile(imagePath);
        image.RotateFlip(RotateFlipType.RotateNoneFlipX);
        image.Save("flipped_image.jpg");
        Console.WriteLine("画像を水平に反転させました。");
    }
}

画像のリサイズ

画像をリサイズするには、Graphicsクラスを使用します。以下は、画像を特定のサイズにリサイズする例です。

using System;
using System.Drawing;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Image image = Image.FromFile(imagePath);
        int newWidth = 200;
        int newHeight = 200;
        Bitmap resizedImage = new Bitmap(newWidth, newHeight);

        using (Graphics g = Graphics.FromImage(resizedImage))
        {
            g.DrawImage(image, 0, 0, newWidth, newHeight);
        }

        resizedImage.Save("resized_image.jpg");
        Console.WriteLine("画像をリサイズしました。");
    }
}

これらの基本操作を使用して、画像の処理を行うことができます。

フィルターの適用

画像に対して様々なフィルターを適用する方法を説明します。

グレースケールフィルター

画像をグレースケールに変換することで、色情報を削除し、明るさの情報のみを残します。以下は、画像をグレースケールに変換する例です。

using System;
using System.Drawing;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);
        for (int y = 0; y < image.Height; y++)
        {
            for (int x = 0; x < image.Width; x++)
            {
                Color originalColor = image.GetPixel(x, y);
                int grayScale = (int)((originalColor.R * 0.3) + (originalColor.G * 0.59) + (originalColor.B * 0.11));
                Color grayColor = Color.FromArgb(grayScale, grayScale, grayScale);
                image.SetPixel(x, y, grayColor);
            }
        }
        image.Save("grayscale_image.jpg");
        Console.WriteLine("画像をグレースケールに変換しました。");
    }
}

ぼかしフィルター

ぼかしフィルターを適用することで、画像を滑らかにし、エッジを和らげることができます。以下は、簡単なぼかしフィルターの適用例です。

using System;
using System.Drawing;
using System.Drawing.Imaging;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);
        Bitmap blurredImage = new Bitmap(image.Width, image.Height);

        for (int y = 1; y < image.Height - 1; y++)
        {
            for (int x = 1; x < image.Width - 1; x++)
            {
                Color c1 = image.GetPixel(x - 1, y - 1);
                Color c2 = image.GetPixel(x, y - 1);
                Color c3 = image.GetPixel(x + 1, y - 1);
                Color c4 = image.GetPixel(x - 1, y);
                Color c5 = image.GetPixel(x, y);
                Color c6 = image.GetPixel(x + 1, y);
                Color c7 = image.GetPixel(x - 1, y + 1);
                Color c8 = image.GetPixel(x, y + 1);
                Color c9 = image.GetPixel(x + 1, y + 1);

                int avgR = (c1.R + c2.R + c3.R + c4.R + c5.R + c6.R + c7.R + c8.R + c9.R) / 9;
                int avgG = (c1.G + c2.G + c3.G + c4.G + c5.G + c6.G + c7.G + c8.G + c9.G) / 9;
                int avgB = (c1.B + c2.B + c3.B + c4.B + c5.B + c6.B + c7.B + c8.B + c9.B) / 9;

                blurredImage.SetPixel(x, y, Color.FromArgb(avgR, avgG, avgB));
            }
        }
        blurredImage.Save("blurred_image.jpg");
        Console.WriteLine("画像にぼかしフィルターを適用しました。");
    }
}

これで、基本的なフィルターの適用方法がわかりました。

画像の色調補正

画像の明るさやコントラストを調整する技術について解説します。

明るさの調整

画像の明るさを調整することで、全体のトーンを変更することができます。以下は、画像の明るさを調整する例です。

using System;
using System.Drawing;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);
        float brightnessFactor = 1.2f; // 明るさの係数 (1.0は変化なし、1.2は20%明るくする)

        for (int y = 0; y < image.Height; y++)
        {
            for (int x = 0; x < image.Width; x++)
            {
                Color originalColor = image.GetPixel(x, y);
                int r = (int)(originalColor.R * brightnessFactor);
                int g = (int)(originalColor.G * brightnessFactor);
                int b = (int)(originalColor.B * brightnessFactor);

                r = Math.Min(r, 255);
                g = Math.Min(g, 255);
                b = Math.Min(b, 255);

                image.SetPixel(x, y, Color.FromArgb(r, g, b));
            }
        }
        image.Save("brightness_adjusted_image.jpg");
        Console.WriteLine("画像の明るさを調整しました。");
    }
}

コントラストの調整

コントラストを調整することで、画像の明暗の差を強調することができます。以下は、画像のコントラストを調整する例です。

using System;
using System.Drawing;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);
        float contrastFactor = 1.2f; // コントラストの係数 (1.0は変化なし、1.2は20%コントラストを増加)

        for (int y = 0; y < image.Height; y++)
        {
            for (int x = 0; x < image.Width; x++)
            {
                Color originalColor = image.GetPixel(x, y);
                float r = originalColor.R / 255.0f;
                float g = originalColor.G / 255.0f;
                float b = originalColor.B / 255.0f;

                r = ((r - 0.5f) * contrastFactor + 0.5f) * 255.0f;
                g = ((g - 0.5f) * contrastFactor + 0.5f) * 255.0f;
                b = ((b - 0.5f) * contrastFactor + 0.5f) * 255.0f;

                int ir = Math.Min(Math.Max((int)r, 0), 255);
                int ig = Math.Min(Math.Max((int)g, 0), 255);
                int ib = Math.Min(Math.Max((int)b, 0), 255);

                image.SetPixel(x, y, Color.FromArgb(ir, ig, ib));
            }
        }
        image.Save("contrast_adjusted_image.jpg");
        Console.WriteLine("画像のコントラストを調整しました。");
    }
}

これらの調整を行うことで、画像の見栄えを大きく改善することができます。

エッジ検出

画像のエッジ検出アルゴリズムを紹介し、その実装方法を説明します。

エッジ検出の概要

エッジ検出は、画像内の物体の輪郭や境界を識別する技術です。一般的なアルゴリズムには、SobelフィルターやCannyエッジ検出があります。

Sobelフィルターの実装

Sobelフィルターを用いたエッジ検出の基本的な例を示します。以下は、Sobelフィルターを適用してエッジを検出するC#のコードです。

using System;
using System.Drawing;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);
        Bitmap edgeImage = new Bitmap(image.Width, image.Height);

        int[,] gx = {
            { -1, 0, 1 },
            { -2, 0, 2 },
            { -1, 0, 1 }
        };

        int[,] gy = {
            { -1, -2, -1 },
            { 0, 0, 0 },
            { 1, 2, 1 }
        };

        for (int y = 1; y < image.Height - 1; y++)
        {
            for (int x = 1; x < image.Width - 1; x++)
            {
                int pixelX = (
                    (gx[0, 0] * image.GetPixel(x - 1, y - 1).R) +
                    (gx[0, 1] * image.GetPixel(x, y - 1).R) +
                    (gx[0, 2] * image.GetPixel(x + 1, y - 1).R) +
                    (gx[1, 0] * image.GetPixel(x - 1, y).R) +
                    (gx[1, 2] * image.GetPixel(x + 1, y).R) +
                    (gx[2, 0] * image.GetPixel(x - 1, y + 1).R) +
                    (gx[2, 1] * image.GetPixel(x, y + 1).R) +
                    (gx[2, 2] * image.GetPixel(x + 1, y + 1).R)
                );

                int pixelY = (
                    (gy[0, 0] * image.GetPixel(x - 1, y - 1).R) +
                    (gy[0, 1] * image.GetPixel(x, y - 1).R) +
                    (gy[0, 2] * image.GetPixel(x + 1, y - 1).R) +
                    (gy[1, 0] * image.GetPixel(x - 1, y).R) +
                    (gy[1, 2] * image.GetPixel(x + 1, y).R) +
                    (gy[2, 0] * image.GetPixel(x - 1, y + 1).R) +
                    (gy[2, 1] * image.GetPixel(x, y + 1).R) +
                    (gy[2, 2] * image.GetPixel(x + 1, y + 1).R)
                );

                int magnitude = (int)Math.Sqrt((pixelX * pixelX) + (pixelY * pixelY));
                magnitude = Math.Min(255, magnitude);
                magnitude = Math.Max(0, magnitude);

                edgeImage.SetPixel(x, y, Color.FromArgb(magnitude, magnitude, magnitude));
            }
        }

        edgeImage.Save("edge_detected_image.jpg");
        Console.WriteLine("画像のエッジを検出しました。");
    }
}

このコードは、Sobelフィルターを適用して画像のエッジを検出し、新しい画像として保存します。これで、エッジ検出の基本を理解できました。

ノイズ除去

画像からノイズを除去する方法を解説し、サンプルコードを提供します。

ノイズ除去の概要

ノイズ除去は、画像から不要なノイズやアーティファクトを取り除く技術です。一般的な方法として、メディアンフィルターやガウシアンフィルターが使われます。

メディアンフィルターの実装

メディアンフィルターは、各ピクセルをその近傍のピクセルの中央値で置き換えることでノイズを除去します。以下は、メディアンフィルターを適用するC#のコードです。

using System;
using System.Drawing;
using System.Linq;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);
        Bitmap denoisedImage = new Bitmap(image.Width, image.Height);

        int radius = 1; // フィルターの半径

        for (int y = radius; y < image.Height - radius; y++)
        {
            for (int x = radius; x < image.Width - radius; x++)
            {
                int[] rValues = new int[(radius * 2 + 1) * (radius * 2 + 1)];
                int[] gValues = new int[(radius * 2 + 1) * (radius * 2 + 1)];
                int[] bValues = new int[(radius * 2 + 1) * (radius * 2 + 1)];

                int index = 0;
                for (int ky = -radius; ky <= radius; ky++)
                {
                    for (int kx = -radius; kx <= radius; kx++)
                    {
                        Color pixelColor = image.GetPixel(x + kx, y + ky);
                        rValues[index] = pixelColor.R;
                        gValues[index] = pixelColor.G;
                        bValues[index] = pixelColor.B;
                        index++;
                    }
                }

                Array.Sort(rValues);
                Array.Sort(gValues);
                Array.Sort(bValues);

                int medianR = rValues[rValues.Length / 2];
                int medianG = gValues[gValues.Length / 2];
                int medianB = bValues[bValues.Length / 2];

                denoisedImage.SetPixel(x, y, Color.FromArgb(medianR, medianG, medianB));
            }
        }

        denoisedImage.Save("denoised_image.jpg");
        Console.WriteLine("画像のノイズを除去しました。");
    }
}

ガウシアンフィルターの実装

ガウシアンフィルターは、各ピクセルをガウシアンカーネルで畳み込むことでノイズを平滑化します。以下は、ガウシアンフィルターを適用するC#のコードです。

using System;
using System.Drawing;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);
        Bitmap smoothedImage = new Bitmap(image.Width, image.Height);

        double[,] kernel = {
            { 1, 2, 1 },
            { 2, 4, 2 },
            { 1, 2, 1 }
        };

        double kernelSum = 16.0; // カーネルの重みの合計

        for (int y = 1; y < image.Height - 1; y++)
        {
            for (int x = 1; x < image.Width - 1; x++)
            {
                double rSum = 0.0;
                double gSum = 0.0;
                double bSum = 0.0;

                for (int ky = -1; ky <= 1; ky++)
                {
                    for (int kx = -1; kx <= 1; kx++)
                    {
                        Color pixelColor = image.GetPixel(x + kx, y + ky);
                        double kernelValue = kernel[ky + 1, kx + 1];

                        rSum += pixelColor.R * kernelValue;
                        gSum += pixelColor.G * kernelValue;
                        bSum += pixelColor.B * kernelValue;
                    }
                }

                int r = Math.Min(Math.Max((int)(rSum / kernelSum), 0), 255);
                int g = Math.Min(Math.Max((int)(gSum / kernelSum), 0), 255);
                int b = Math.Min(Math.Max((int)(bSum / kernelSum), 0), 255);

                smoothedImage.SetPixel(x, y, Color.FromArgb(r, g, b));
            }
        }

        smoothedImage.Save("smoothed_image.jpg");
        Console.WriteLine("画像にガウシアンフィルターを適用しました。");
    }
}

これで、ノイズ除去の基本を理解し、実際に画像に適用する方法がわかりました。

画像の形式変換

画像形式の変換方法と、その活用例を紹介します。

画像形式の変換方法

C#では、System.Drawing名前空間を使用して、簡単に画像形式を変換することができます。以下は、JPEG形式の画像をPNG形式に変換する例です。

using System;
using System.Drawing;
using System.Drawing.Imaging;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);
        string outputImagePath = "converted_image.png";

        image.Save(outputImagePath, ImageFormat.Png);
        Console.WriteLine("画像をJPEG形式からPNG形式に変換しました。");
    }
}

他の形式への変換

他の形式への変換も同様に行えます。以下は、BMP形式に変換する例です。

using System;
using System.Drawing;
using System.Drawing.Imaging;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);
        string outputImagePath = "converted_image.bmp";

        image.Save(outputImagePath, ImageFormat.Bmp);
        Console.WriteLine("画像をJPEG形式からBMP形式に変換しました。");
    }
}

活用例: サムネイル画像の作成

形式変換は、ウェブ用のサムネイル画像を作成する際にも役立ちます。以下は、サムネイル画像を作成し、JPEG形式で保存する例です。

using System;
using System.Drawing;
using System.Drawing.Imaging;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);
        int thumbnailWidth = 150;
        int thumbnailHeight = (int)(thumbnailWidth * image.Height / image.Width);
        Image thumbnail = image.GetThumbnailImage(thumbnailWidth, thumbnailHeight, null, IntPtr.Zero);

        string outputImagePath = "thumbnail_image.jpg";
        thumbnail.Save(outputImagePath, ImageFormat.Jpeg);
        Console.WriteLine("サムネイル画像を作成し、JPEG形式で保存しました。");
    }
}

これで、画像形式の変換方法とその応用例について理解できました。

演習問題

読者が実際に手を動かして学べる演習問題を提供します。

演習1: グレースケールフィルターの適用

以下のステップに従って、グレースケールフィルターを画像に適用してください。

  1. 任意の画像ファイルを用意してください。
  2. C#コンソールアプリケーションを作成し、以下のコードを実装してください。
  3. 画像をグレースケールに変換し、新しいファイルとして保存してください。
using System;
using System.Drawing;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);

        for (int y = 0; y < image.Height; y++)
        {
            for (int x = 0; x < image.Width; x++)
            {
                Color originalColor = image.GetPixel(x, y);
                int grayScale = (int)((originalColor.R * 0.3) + (originalColor.G * 0.59) + (originalColor.B * 0.11));
                Color grayColor = Color.FromArgb(grayScale, grayScale, grayScale);
                image.SetPixel(x, y, grayColor);
            }
        }
        image.Save("grayscale_exercise.jpg");
        Console.WriteLine("グレースケール変換が完了しました。");
    }
}

演習2: エッジ検出フィルターの実装

以下のステップに従って、Sobelフィルターを使用して画像のエッジを検出してください。

  1. 任意の画像ファイルを用意してください。
  2. C#コンソールアプリケーションを作成し、以下のコードを実装してください。
  3. エッジ検出を行い、新しいファイルとして保存してください。
using System;
using System.Drawing;

class Program
{
    static void Main()
    {
        string imagePath = "path_to_your_image.jpg";
        Bitmap image = new Bitmap(imagePath);
        Bitmap edgeImage = new Bitmap(image.Width, image.Height);

        int[,] gx = {
            { -1, 0, 1 },
            { -2, 0, 2 },
            { -1, 0, 1 }
        };

        int[,] gy = {
            { -1, -2, -1 },
            { 0, 0, 0 },
            { 1, 2, 1 }
        };

        for (int y = 1; y < image.Height - 1; y++)
        {
            for (int x = 1; x < image.Width - 1; x++)
            {
                int pixelX = (
                    (gx[0, 0] * image.GetPixel(x - 1, y - 1).R) +
                    (gx[0, 1] * image.GetPixel(x, y - 1).R) +
                    (gx[0, 2] * image.GetPixel(x + 1, y - 1).R) +
                    (gx[1, 0] * image.GetPixel(x - 1, y).R) +
                    (gx[1, 2] * image.GetPixel(x + 1, y).R) +
                    (gx[2, 0] * image.GetPixel(x - 1, y + 1).R) +
                    (gx[2, 1] * image.GetPixel(x, y + 1).R) +
                    (gx[2, 2] * image.GetPixel(x + 1, y + 1).R)
                );

                int pixelY = (
                    (gy[0, 0] * image.GetPixel(x - 1, y - 1).R) +
                    (gy[0, 1] * image.GetPixel(x, y - 1).R) +
                    (gy[0, 2] * image.GetPixel(x + 1, y - 1).R) +
                    (gy[1, 0] * image.GetPixel(x - 1, y).R) +
                    (gy[1, 2] * image.GetPixel(x + 1, y).R) +
                    (gy[2, 0] * image.GetPixel(x - 1, y + 1).R) +
                    (gy[2, 1] * image.GetPixel(x, y + 1).R) +
                    (gy[2, 2] * image.GetPixel(x + 1, y + 1).R)
                );

                int magnitude = (int)Math.Sqrt((pixelX * pixelX) + (pixelY * pixelY));
                magnitude = Math.Min(255, magnitude);
                magnitude = Math.Max(0, magnitude);

                edgeImage.SetPixel(x, y, Color.FromArgb(magnitude, magnitude, magnitude));
            }
        }

        edgeImage.Save("edge_detected_exercise.jpg");
        Console.WriteLine("エッジ検出が完了しました。");
    }
}

これらの演習問題を通じて、画像処理の基本技術を実践的に学びましょう。

参考資料

さらに学びたい読者のための参考資料やリンクを紹介します。

公式ドキュメント

オンラインチュートリアル

書籍

  • “Programming Windows Presentation Foundation” by Chris Sells and Ian Griffiths: WPFを使った画像処理の基礎と応用について詳しく解説しています。
  • “C# 6.0 and the .NET 4.6 Framework” by Andrew Troelsen and Philip Japikse: C#と.NETフレームワークを使った様々なプログラミング技術を学ぶことができます。

サンプルプロジェクト

  • GitHub: AForge.NET: C#での画像処理ライブラリAForge.NETのサンプルプロジェクトが多数公開されています。
  • GitHub: Emgu.CV: OpenCVのC#ラッパーであるEmgu.CVを使用したサンプルコードやプロジェクトが公開されています。

これらの参考資料を活用して、C#での画像処理技術をさらに深く学びましょう。

コメント

コメントする

目次