灰度直方图是灰度的函数,描述的是图像中具有该灰度级的像素的个数。如果用直角坐标系来表示,则它的横坐标是灰度级,纵坐标是该灰度出现的概率(像素的个数)。
灰度直方图的分布函数:
其中,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 ??? { ??????? /// <summary> ??????? /// 必需的设计器变量。 ??????? /// </summary> ??????? private System.ComponentModel.IContainer components = null;
??????? /// <summary> ??????? /// 清理所有正在使用的资源。 ??????? /// </summary> ??????? /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> ??????? protected override void Dispose(bool disposing) ??????? { ??????????? if (disposing && (components != null)) ??????????? { ??????????????? components.Dispose(); ??????????? } ??????????? base.Dispose(disposing); ??????? }
??????? #region Windows 窗体设计器生成的代码
??????? /// <summary> ??????? /// 设计器支持所需的方法 - 不要 ??????? /// 使用代码编辑器修改此方法的内容。 ??????? /// </summary> ??????? 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);
??????? } ??? }
?
|