【C#】Chartを使ったヒストグラム表示

Chartコントロールを使いたかった理由の一つに画像処理ではおなじみのヒストグラムをChartコントロールで表示したかったのですが、その簡単なプログラムです。

 

フォームにはChartコントロールを配置し、Chartの名前がchart1とした事を前提として、

// /////////////////////////////////////////////////////
// Chartコントロール内のグラフ、凡例、目盛り領域を削除
chart1.Series.Clear();
chart1.Legends.Clear();
chart1.ChartAreas.Clear();

// /////////////////////////////////////////////////////
// 目盛り領域の設定
var ca = chart1.ChartAreas.Add("Histogram");

// X軸
ca.AxisX.Title = "Brightness";  // タイトル
ca.AxisX.Minimum = 0;           // 最小値
ca.AxisX.Maximum = 256;         // 最大値
ca.AxisX.Interval = 64;         // 目盛りの間隔
// Y軸
ca.AxisY.Title = "Count";
ca.AxisY.Minimum = 0;

// /////////////////////////////////////////////////////
// データの追加
var hist = new Point[] {
    new Point(32, 10),
    new Point(96, 30),
    new Point(160, 50),
    new Point(224, 20)
};

// グラフの系列を追加
var s = chart1.Series.Add("Histogram");
// 棒グラフの隙間を無くす
s.SetCustomProperty("PointWidth", "1.0");
// データ設定
for (int i = 0; i < hist.Length; i++) {
    s.Points.AddXY(hist[i].X, hist[i].Y);
}

と書くだけで、モノクロ画像用のヒストグラムが簡単に作成できます。

 

(実行結果)

 

ここでのポイントとしては、棒グラフ(ChartTypeColumn)の時に、棒グラフの間隔を無くすにはPointWidthプロパティを1.0にすればよい(デフォルトは0.8)のですが、各グラフ特有のプロパティ設定は以下のように設定する必要があります。

(直接プロパティの設定ができません。)

// 棒グラフの隙間を無くす
s.SetCustomProperty("PointWidth", "1.0");

モノクロ画像の時はこれでもよいのですが、カラーだと、R,G,Bの3つのグラフを書かないといけないので、折れ線では表現しにくいので、折れ線(ChartTypeLine)を使ってみたいと思います。

 

要領は同じで、SeriesにR,G,B用の3つを追加することぐらいです。

// /////////////////////////////////////////////////////
// Chartコントロール内のグラフ、凡例、目盛り領域を削除
chart1.Series.Clear();
chart1.Legends.Clear();
chart1.ChartAreas.Clear();

// /////////////////////////////////////////////////////
// 目盛り領域の設定
var ca = chart1.ChartAreas.Add("Histogram");

// X軸
ca.AxisX.Title = "Brightness";  // タイトル
ca.AxisX.Minimum = 0;           // 最小値
ca.AxisX.Maximum = 256;         // 最大値
ca.AxisX.Interval = 64;         // 目盛りの間隔
// Y軸
ca.AxisY.Title = "Count";
ca.AxisY.Minimum = 0;

// /////////////////////////////////////////////////////
// データの追加
var histR = new Point[] {
    new Point(0, 10),
    new Point(63, 30),
    new Point(127, 80),
    new Point(191, 30),
    new Point(255, 15)
};
var histG = new Point[] {
    new Point(0, 70),
    new Point(63, 60),
    new Point(127, 40),
    new Point(191, 20),
    new Point(255, 10)
};
var histB = new Point[] {
    new Point(0, 10),
    new Point(63, 20),
    new Point(127, 30),
    new Point(191, 70),
    new Point(255, 90)
};

// グラフの系列を追加
var sR = chart1.Series.Add("HistogramR");
var sG = chart1.Series.Add("HistogramG");
var sB = chart1.Series.Add("HistogramB");

// グラフの種類を折れ線に設定する
sR.ChartType = sG.ChartType = sB.ChartType 
    = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;

// データ設定
for (int i = 0; i < histR.Length; i++)
{
    sR.Points.AddXY(histR[i].X, histR[i].Y);
    sG.Points.AddXY(histG[i].X, histG[i].Y);
    sB.Points.AddXY(histB[i].X, histB[i].Y);
}

(実行結果)

 

これでカラーのヒストグラムも表示できる事ができます!

とか言っても、見た目があまりにもショボイので、もう少し手を入れます。

 

今度はグラフの種類にスプライン面グラフ(SeriesChartType.SplineArea)を使ってみます。

// /////////////////////////////////////////////////////
// Chartコントロール内のグラフ、凡例、目盛り領域を削除
chart1.Series.Clear();
chart1.Legends.Clear();
chart1.ChartAreas.Clear();

// /////////////////////////////////////////////////////
// 目盛り領域の設定
var ca = chart1.ChartAreas.Add("Histogram");

// X軸
ca.AxisX.Title = "Brightness";  // タイトル
ca.AxisX.Minimum = 0;           // 最小値
ca.AxisX.Maximum = 256;         // 最大値
ca.AxisX.Interval = 64;         // 目盛りの間隔
// Y軸
ca.AxisY.Title = "Count";
ca.AxisY.Minimum = 0;

// /////////////////////////////////////////////////////
// データの追加
var histR = new Point[] {
    new Point(0, 10),
    new Point(63, 30),
    new Point(127, 80),
    new Point(191, 30),
    new Point(255, 15)
};
var histG = new Point[] {
    new Point(0, 70),
    new Point(63, 60),
    new Point(127, 40),
    new Point(191, 20),
    new Point(255, 10)
};
var histB = new Point[] {
    new Point(0, 10),
    new Point(63, 20),
    new Point(127, 30),
    new Point(191, 70),
    new Point(255, 90)
};

// グラフの系列を追加
var sR = chart1.Series.Add("HistogramR");
var sG = chart1.Series.Add("HistogramG");
var sB = chart1.Series.Add("HistogramB");

// グラフの種類をスプライン面グラフに設定する
sR.ChartType = sG.ChartType = sB.ChartType
    = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.SplineArea;

// 輪郭線の太さ
sR.BorderWidth = sG.BorderWidth = sB.BorderWidth = 2;

// 輪郭線の色
sR.BorderColor = Color.Red;
sG.BorderColor = Color.Green;
sB.BorderColor = Color.Blue;

// 塗りつぶしの色の設定(半透明)
sR.Color = Color.FromArgb(150, Color.Red);
sG.Color = Color.FromArgb(150, Color.Green);
sB.Color = Color.FromArgb(150, Color.Blue);

// データ設定
for (int i = 0; i < histR.Length; i++)
{
    sR.Points.AddXY(histR[i].X, histR[i].Y);
    sG.Points.AddXY(histG[i].X, histG[i].Y);
    sB.Points.AddXY(histB[i].X, histB[i].Y);
}

(実行結果)

 

これで、かなりそれっぽくないですか?

プログラム的に書くと、塗りつぶしの色に半透明の色を設定できるところがポイントでしょうかね。

 

Chartコントロールの使用方法へ戻る

【C#】Chartコントロールをとりあえず使ってみる

Chartコントロールは、本当に多くのプロパティがあるため、一つ一つを調べてからプログラムをするよりも、まずはVisual Studioのフォームエディタ上でいろいろ触ってみてから、プロパティの意味するところを覚えて、プログラムを組むようにした方が早そうです。

 

という事で、フォームエディタ上で、いろいろ触ってみました。

 

コントロールの追加

ツールボックスのデータの中にあるChartを選択し、フォームへ追加します。

 

 

グラフデータの追加

グラフのデータはSeriesプロパティで管理されています。

 

Series(コレクション)の部分をクリックし、  をクリックするとエディタが表示されます。

 

 

グラフのデータはデータPointsプロパティの(コレクション)の部分をクリックし、  をクリックすると各データを編集する画面↓が表示されます。

 

 

追加のボタンをクリックするたびにデータが追加されます。

下図は5個のデータを追加した様子

 

 

各データの値はデータのXValueとYValuesの値を設定します。

ここでYの値だけ複数形になっている?!と思えたら、少しChartコントロールに慣れてきている感じでしょうか?

複数形は複数の設定ができます。

 

この状態で5個のデータを表示したのがこちら↓

 

 

グラフの種類の設定

グラフの種類は各系列(Series)ごとに設定ができ(できない組み合わせもあります)、グラフのChartTypeで設定します。

 

 

ここで、縦の棒グラフ(Column)から折れ線グラフ(Line)に変更すると

 

 

上図のようになります。

 

マーカーの追加

マーカーはSeriesプロパティのMakerSyleというプロパティがあります。

 

デフォルトではマーカーなし(None)になっていますが、これをSquareにしてみます。

エクセルっぽい!

 

軸の名前の設定

グラフの軸を管理しているのはChartAreaプロパティになります。

ChartArea(コレクション)の部分をクリックし、  をクリックするとエディタが表示されます。

 

軸を管理しているのがAxesプロパティでさらにエディタを開きます。

 

 

Axisコレクションには最初から

X axis X軸(主軸)
Y(Value) axis Y軸(主軸)
Secondary X axis X軸(第二軸)
Secondary Y axis Y軸(第二軸)

の4つが用意されており、各軸のTitleプロパティで軸の名前を設定します。

 

 

X軸とY軸のTitleを設定した結果↓

 

 

グラフのタイトルの設定

グラフのタイトルはTitleプロパティになります。

Title(コレクション)の部分をクリックし、  をクリックするとエディタが表示されます。

 

 

(Text)の部分を編集するとグラフのタイトルが表示されます。

 

凡例領域の設定

凡例領域の設定はLegendsロパティになります。

Legends(コレクション)の部分をクリックし、  をクリックするとエディタが表示されます。

 

 

Legends1のTitleプロパティに凡例表示と入力してみると

 

 

ん??

Series1の部分が変わるかと思ったら、その上に表示されるだけ?

Legendsプロパティはあくまでも凡例表示全体(各系列の凡例を表示している領域)のプロパティ設定であって、各系列(Series)の設定ではありません。

 

Series1の部分の表示名を変更するにはSeriesプロパティのNameプロパティを設定します。

 

 

凡例の名前が変更されました↓

 

他にも様々なプロパティがあるので、いじりたおすと面白いと思います。

 

これで、この操作をプログラムで表現できれば、何とかなりそうな気がしてきた!

 

Chartコントロールの使用方法へ戻る