C#のWinFormsで画像加工アプリ10「ヒストグラムをグラフで表示」

コンピュータ

画像のヒストグラムをグラフで表示します。

パッケージの追加

dotnet add package System.Windows.Forms.DataVisualization --version 1.0.0-prerelease.20110.1
dotnet add package System.Data.SqlClient

ソースコード

ファイル名:Form1.cs(前回の記事のソースコードに追加)

    // ヒストグラム(Form1のメンバーとして追加)
    readonly ToolStripMenuItem histMenuItem = new()
    {
        Text = "ヒストグラム",
    };
        // ヒストグラム(Form1のコンストラクタに追加)
        filterMenuItem.DropDownItems.Add(histMenuItem);
        histMenuItem.Click += (s, e) =>
        {
            if (_buffBmp is null) return;
            HistDialog(_buffBmp);
        };

ファイル名:Form1.Hist.cs(新規追加)

using OpenCvSharp;
using OpenCvSharp.Extensions;
using System.Windows.Forms.DataVisualization.Charting;
using System.Windows.Forms.VisualStyles;

namespace GazouKakou01;
public partial class Form1 : Form
{
    public static void HistDialog(Bitmap src)
    {
        const int BORDER_WIDTH = 3;
        const string filterName = "ヒストグラム";

        Form frm = new Form
        {
            FormBorderStyle = FormBorderStyle.FixedDialog,
            ClientSize = new System.Drawing.Size(640, 480),
            Text = filterName,
        };
        Chart chart = new()
        {
           Dock = DockStyle.Fill,
           Parent = frm,
        };
        // デフォルトグラフをクリア
        chart.Series.Clear();
        chart.ChartAreas.Clear();
        
        // チャートエリアの追加
        chart.ChartAreas.Add(new ChartArea("area1"));
        
        Mat srcMat = BitmapConverter.ToMat(src);

        if (srcMat.Channels() == 1)
        {
            // グレースケール

            // グラフを追加
            chart.Series.Add("grayscale");
            // 縦棒グラフ
            chart.Series["grayscale"].ChartType = SeriesChartType.Line; // 折れ線
            chart.Series["grayscale"].BorderWidth = BORDER_WIDTH;
            chart.Series["grayscale"].Color = Color.Black;

            // ヒストグラム
            Mat hist = new();
            Cv2.CalcHist([srcMat], [0], null, hist, 1, [256], new Rangef[] { new(0, 256) });

            // Chartに配列をセット
            for(int i = 0; i < 255; i++)
            {
                chart.Series["grayscale"].Points.AddY(hist.At<float>(i, 0));
            }        

        }
        if (srcMat.Channels() >= 3)
        {
            // カラー

            // グラフを追加
            chart.Series.Add("blue");
            chart.Series["blue"].ChartType = SeriesChartType.Line;
            chart.Series["blue"].BorderWidth = BORDER_WIDTH;
            chart.Series["blue"].Color = Color.Blue;
            Mat hist_b = new();
            Cv2.CalcHist([srcMat], [0], null, hist_b, 1, [256], new Rangef[] { new(0, 256) });

            chart.Series.Add("green");
            chart.Series["green"].ChartType = SeriesChartType.Line;
            chart.Series["green"].BorderWidth = BORDER_WIDTH;
            chart.Series["green"].Color = Color.Green;
            Mat hist_g = new();
            Cv2.CalcHist([srcMat], [1], null, hist_g, 1, [256], new Rangef[] { new(0, 256) });

            chart.Series.Add("red");
            chart.Series["red"].ChartType = SeriesChartType.Line;
            chart.Series["red"].BorderWidth = BORDER_WIDTH;
            chart.Series["red"].Color = Color.Red;
            Mat hist_r = new();
            Cv2.CalcHist([srcMat], [2], null, hist_r, 1, [256], new Rangef[] { new(0, 256) });

            Mat hist_a = new();
            if (srcMat.Channels() == 4)
            {
                chart.Series.Add("alpha");
                chart.Series["alpha"].ChartType = SeriesChartType.Line;
                chart.Series["alpha"].BorderWidth = BORDER_WIDTH;
                chart.Series["alpha"].Color = Color.Black;
                Cv2.CalcHist([srcMat], [3], null, hist_a, 1, [256], new Rangef[] { new(0, 256) });
            }

            for(int i = 0; i < 255; i++)
            {
                chart.Series["blue"].Points.AddY(hist_b.At<float>(i, 0));
                chart.Series["green"].Points.AddY(hist_g.At<float>(i, 0));
                chart.Series["red"].Points.AddY(hist_r.At<float>(i, 0));
                if (srcMat.Channels() == 4)
                {
                    chart.Series["alpha"].Points.AddY(hist_a.At<float>(i, 0));
                }
            }        

        }
        frm.Load += (s, e) =>
        {
        };

        frm.ShowDialog();
    }
}

実行

画像が表示されている状態でメインメニュー「フィルター」→「ヒストグラム」を選ぶ

カラー画像の場合、各チャンネルが青、緑、赤の折れ線グラフで表示(アルファチャンネルは黒)

グレースケール画像の場合、黒色の折れ線グラフで表示

コメント