灰度直方图是灰度的函数,描述的是图像中具有该灰度级的像素的个数。如果用直角坐标系来表示,则它的横坐标是灰度级,纵坐标是该灰度出现的概率(像素的个数)。
灰度直方图的分布函数:
其中,K是指第k个灰度级,
如果是8位灰度图像,k=0、1、……、255。
界面设计如下:
在设计时先定义对象:
#endregion
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.OpenFileDialog openFileDialog1;
private System.Windows.Forms.Button button2;
具体的如下
partial class Form1
{
///
/// 必需的设计器变量。
///
private System.ComponentModel.IContainer components = null;
///
/// 清理所有正在使用的资源。
///
/// 如果应释放托管资源,为 true;否则为 false。
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows 窗体设计器生成的代码
///
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
///
private void InitializeComponent()
{
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.button1 = new System.Windows.Forms.Button();
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.button2 = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.Location = new System.Drawing.Point(93, 12);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(494, 384);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
//
// button1
//
this.button1.Location = new System.Drawing.Point(12, 12);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 1;
this.button1.Text = "打开";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// openFileDialog1
//
this.openFileDialog1.Filter = "JPG文件|*.jpg|PNG文件|*.png|BMP文件|*.bmp";
//
// button2
//
this.button2.Location = new System.Drawing.Point(12, 41);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 2;
this.button2.Text = "直方图";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(599, 408);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.pictureBox1);
this.Name = "Form1";
this.Text = "灰度直方图";
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.OpenFileDialog openFileDialog1;
private System.Windows.Forms.Button button2;
}
窗口设计如下
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Bitmap bitmap;
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
string path = openFileDialog1.FileName;
bitmap = (Bitmap)Image.FromFile(path);
pictureBox1.Image = bitmap.Clone() as Image;
}
}
private void button2_Click(object sender, EventArgs e)
{
if (bitmap != null)
{
Grey_ScaleMapForm fr = new Grey_ScaleMapForm(bitmap);
fr.ShowDialog();
}
}
}
类定义如下
public partial class Grey_ScaleMapForm : Form
{
private System.Drawing.Bitmap bmpHist;//用bitmap做图像处理,可以获取灰度
private int[] countPixel;//将点记录
private int maxPixel;//记录最大的点
public Grey_ScaleMapForm(Bitmap bmp)
{
InitializeComponent();
bmpHist = bmp;
countPixel = new int[256];
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
private void Grey_ScaleMapForm_Paint(object sender, PaintEventArgs e)
{
//画出坐标系
Graphics g = e.Graphics;
Pen curPen = new Pen(Brushes.Black, 1);
g.DrawLine(curPen, 50, 240, 320, 240);//X轴
g.DrawLine(curPen, 50, 240, 50, 30);//Y轴
//绘制并标识坐标刻度
g.DrawLine(curPen, 100, 240, 100, 242);//同上,画长度为2的线
g.DrawLine(curPen, 150, 240, 150, 242);
g.DrawLine(curPen, 200, 240, 200, 242);
g.DrawLine(curPen, 250, 240, 250, 242);
g.DrawLine(curPen, 300, 240, 300, 242);
//在x轴上为刻度标出刻度值
g.DrawString("0", new Font("New Timer", 8), Brushes.Black, new PointF(46, 242));
g.DrawString("50", new Font("New Timer", 8), Brushes.Black, new PointF(92, 242));
g.DrawString("100", new Font("New Timer", 8), Brushes.Black, new PointF(139, 242));
g.DrawString("150", new Font("New Timer", 8), Brushes.Black, new PointF(189, 242));
g.DrawString("200", new Font("New Timer", 8), Brushes.Black, new PointF(239, 242));
g.DrawString("250", new Font("New Timer", 8), Brushes.Black, new PointF(289, 242));
//在y轴上为标刻度及刻度值
g.DrawLine(curPen, 48, 40, 50, 40);
g.DrawString("0", new Font("New Timer", 8), Brushes.Black, new PointF(34, 234));
g.DrawString(maxPixel.ToString(), new Font("New Timer", 8), Brushes.Black, new PointF(18, 34));
//绘制直方图
double temp = 0;
for (int i = 0; i < 256; i++)
{
//纵坐标长度
temp = 200.0 * countPixel[i] / maxPixel;
g.DrawLine(curPen, 50 + i, 240, 50 + i, 240 - (int)temp);
}
//释放对象
curPen.Dispose();
}
private void Grey_ScaleMapForm_Load(object sender, EventArgs e)
{
//将图像数据复制到byte中,锁定8位灰度位图
Rectangle rect = new Rectangle(0, 0, bmpHist.Width, bmpHist.Height);
//以可读写的方式锁定全部位图像素
System.Drawing.Imaging.BitmapData bmpdata = bmpHist.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmpHist.PixelFormat);
//得到首地址
IntPtr ptr = bmpdata.Scan0;
//定义被锁定的数组大小,由位图数据与未用空间组成
int bytes = bmpHist.Width * bmpHist.Height * 3;
byte[] grayValues = new byte[bytes];
//复制被锁定的位图像素值到该数组中
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
//统计直方图信息
byte temp = 0;
maxPixel = 0;
//灰度等级数组清零
Array.Clear(countPixel, 0, 256);
//计算各个灰度级的像素个数
for (int i = 0; i < bytes; i++)
{
temp = grayValues[i]; //灰度级
countPixel[temp]++;
if (countPixel[temp] > maxPixel)
{
maxPixel = countPixel[temp];//找到灰度频率最大的像素数,用于绘制直方图
}
}
//解锁
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
bmpHist.UnlockBits(bmpdata);
}
}