这里之所以说“浅谈”是因为我这里只是简单的介绍如何使用Visual C#进行图像的读入、保存以及对像素的访问。而不涉及太多的算法。
一、读取图像
在Visual C#中我们可以使用一个Picture Box控件来显示图片,如下:
private void btnOpenImage_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "BMP Files(*.bmp)|*.bmp|JPG Files(*.jpg;*.jpeg)|*.jpg;*.jpeg|All Files(*.*)|*.*"; ofd.CheckFileExists = true; ofd.CheckPathExists = true; if (ofd.ShowDialog() == DialogResult.OK) { //pbxShowImage.ImageLocation = ofd.FileName; bmp = new Bitmap(ofd.FileName); if (bmp==null) { MessageBox.Show("加载图片失败!", "错误"); return; } pbxShowImage.Image = bmp; ofd.Dispose(); } }
其中bmp为类的一个对象:private Bitmap bmp=null;
在使用Bitmap类和BitmapData类之前,需要使用using System.Drawing.Imaging;
二、保存图像
private void btnSaveImage_Click(object sender, EventArgs e) { if (bmp == null) return; SaveFileDialog sfd = new SaveFileDialog(); sfd.Filter = "BMP Files(*.bmp)|*.bmp|JPG Files(*.jpg;*.jpeg)|*.jpg;*.jpeg|All Files(*.*)|*.*"; if (sfd.ShowDialog() == DialogResult.OK) { pbxShowImage.Image.Save(sfd.FileName); MessageBox.Show("保存成功!","提示"); sfd.Dispose(); } }
三、对像素的访问
我们可以来建立一个GrayBitmapData类来做相关的处理。整个类的程序如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; namespace ImageElf { class GrayBitmapData { public byte[,] Data;//保存像素矩阵 public int Width;//图像的宽度 public int Height;//图像的高度 public GrayBitmapData() { this.Width = 0; this.Height = 0; this.Data = null; } public GrayBitmapData(Bitmap bmp) { BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); this.Width = bmpData.Width; this.Height = bmpData.Height; Data = new byte[Height, Width]; unsafe { byte* ptr = (byte*)bmpData.Scan0.ToPointer(); for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { //将24位的RGB彩色图转换为灰度图 int temp = (int)(0.114 * (*ptr++)) + (int)(0.587 * (*ptr++))+(int)(0.299 * (*ptr++)); Data[i, j] = (byte)temp; } ptr += bmpData.Stride - Width * 3;//指针加上填充的空白空间 } } bmp.UnlockBits(bmpData); } public GrayBitmapData(string path) : this(new Bitmap(path)) { } public Bitmap ToBitmap() { Bitmap bmp=new Bitmap(Width,Height,PixelFormat.Format24bppRgb); BitmapData bmpData=bmp.LockBits(new Rectangle(0,0,Width,Height),ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb); unsafe { byte* ptr=(byte*)bmpData.Scan0.ToPointer(); for(int i=0;i<Height;i++) { for(int j=0;j<Width;j++) { *(ptr++)=Data[i,j]; *(ptr++)=Data[i,j]; *(ptr++)=Data[i,j]; } ptr+=bmpData.Stride-Width*3; } } bmp.UnlockBits(bmpData); return bmp; } public void ShowImage(PictureBox pbx) { Bitmap b = this.ToBitmap(); pbx.Image = b; //b.Dispose(); } public void SaveImage(string path) { Bitmap b=ToBitmap(); b.Save(path); //b.Dispose(); } //均值滤波 public void AverageFilter(int windowSize) { if (windowSize % 2 == 0) { return; } for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { int sum = 0; for (int g = -(windowSize - 1) / 2; g <= (windowSize - 1) / 2; g++) { for (int k = -(windowSize - 1) / 2; k <= (windowSize - 1) / 2; k++) { int a = i + g, b = j + k; if (a < 0) a = 0; if (a > Height - 1) a = Height - 1; if (b < 0) b = 0; if (b > Width - 1) b = Width - 1; sum += Data[a, b]; } } Data[i,j]=(byte)(sum/(windowSize*windowSize)); } } } //中值滤波 public void MidFilter(int windowSize) { if (windowSize % 2 == 0) { return; } int[] temp = new int[windowSize * windowSize]; byte[,] newdata = new byte[Height, Width]; for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { int n = 0; for (int g = -(windowSize - 1) / 2; g <= (windowSize - 1) / 2; g++) { for (int k = -(windowSize - 1) / 2; k <= (windowSize - 1) / 2; k++) { int a = i + g, b = j + k; if (a < 0) a = 0; if (a > Height - 1) a = Height - 1; if (b < 0) b = 0; if (b > Width - 1) b = Width - 1; temp[n++]= Data[a, b]; } } newdata[i, j] = GetMidValue(temp,windowSize*windowSize); } } for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { Data[i, j] = newdata[i, j]; } } } //获得一个向量的中值 private byte GetMidValue(int[] t, int length) { int temp = 0; for (int i = 0; i < length - 2; i++) { for (int j = i + 1; j < length - 1; j++) { if (t[i] > t[j]) { temp = t[i]; t[i] = t[j]; t[j] = temp; } } } return (byte)t[(length - 1) / 2]; } //一种新的滤波方法,是亮的更亮、暗的更暗 public void NewFilter(int windowSize) { if (windowSize % 2 == 0) { return; } for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { int sum = 0; for (int g = -(windowSize - 1) / 2; g <= (windowSize - 1) / 2; g++) { for (int k = -(windowSize - 1) / 2; k <= (windowSize - 1) / 2; k++) { int a = i + g, b = j + k; if (a < 0) a = 0; if (a > Height - 1) a = Height - 1; if (b < 0) b = 0; if (b > Width - 1) b = Width - 1; sum += Data[a, b]; } } double avg = (sum+0.0) / (windowSize * windowSize); if (avg / 255 < 0.5) { Data[i, j] = (byte)(2 * avg / 255 * Data[i, j]); } else { Data[i,j]=(byte)((1-2*(1-avg/255.0)*(1-Data[i,j]/255.0))*255); } } } } //直方图均衡 public void HistEqual() { double[] num = new double[256] ; for(int i=0;i<256;i++) num[i]=0; for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { num[Data[i, j]]++; } } double[] newGray = new double[256]; double n = 0; for (int i = 0; i < 256; i++) { n += num[i]; newGray[i] = n * 255 / (Height * Width); } for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { Data[i,j]=(byte)newGray[Data[i,j]]; } } } } }
在GrayBitmapData类中,只要我们对一个二维数组Data进行一系列的操作就是对图片的操作处理。在窗口上,我们可以使用
一个按钮来做各种调用:
//均值滤波 private void btnAvgFilter_Click(object sender, EventArgs e) { if (bmp == null) return; GrayBitmapData gbmp = new GrayBitmapData(bmp); gbmp.AverageFilter(3); gbmp.ShowImage(pbxShowImage); } //转换为灰度图 private void btnToGray_Click(object sender, EventArgs e) { if (bmp == null) return; GrayBitmapData gbmp = new GrayBitmapData(bmp); gbmp.ShowImage(pbxShowImage); }
四、总结
在Visual c#中对图像进行处理或访问,需要先建立一个Bitmap对象,然后通过其LockBits方法来获得一个BitmapData类的对象,然后通过获得其像素数据的首地址来对Bitmap对象的像素数据进行操作。当然,一种简单但是速度慢的方法是用Bitmap类的GetPixel和SetPixel方法。其中BitmapData类的Stride属性为每行像素所占的字节。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:notice#nhooo.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。