您的位置:首页 > 编程语言 > C#

C# (GDI+相关) 图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果) (转)

2014-10-14 20:24 876 查看
[code]C#图像处理
(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
一、各种旋转、改变大小
注意:先要添加画图相关的using引用。
//向右旋转图像90°代码如下:
privatevoidForm1_Paint(objectsender,System.Windows.Forms.PaintEventArgse)
{
Graphicsg=e.Graphics;
Bitmapbmp=newBitmap("rama.jpg");//加载图像
g.FillRectangle(Brushes.White,this.ClientRectangle);//填充窗体背景为白色
Point[]destinationPoints={
newPoint(100,0),//destinationforupper-leftpointoforiginal
newPoint(100,100),//destinationforupper-rightpointoforiginal
newPoint(0,0)};//destinationforlower-leftpointoforiginal
g.DrawImage(bmp,destinationPoints);
}
//旋转图像180°代码如下:
privatevoidForm1_Paint(objectsender,System.Windows.Forms.PaintEventArgse)
{
Graphicsg=e.Graphics;
Bitmapbmp=newBitmap("rama.jpg");
g.FillRectangle(Brushes.White,this.ClientRectangle);
Point[]destinationPoints={
newPoint(0,100),//destinationforupper-leftpointoforiginal
newPoint(100,100),//destinationforupper-rightpointoforiginal
newPoint(0,0)};//destinationforlower-leftpointoforiginal
g.DrawImage(bmp,destinationPoints);
}
//图像切变代码:
privatevoidForm1_Paint(objectsender,System.Windows.Forms.PaintEventArgse)
{
Graphicsg=e.Graphics;
Bitmapbmp=newBitmap("rama.jpg");
g.FillRectangle(Brushes.White,this.ClientRectangle);
Point[]destinationPoints={
newPoint(0,0),//destinationforupper-leftpointoforiginal
newPoint(100,0),//destinationforupper-rightpointoforiginal
newPoint(50,100)};//destinationforlower-leftpointoforiginal
g.DrawImage(bmp,destinationPoints);
}
//图像截取:
privatevoidForm1_Paint(objectsender,System.Windows.Forms.PaintEventArgse)
{
Graphicsg=e.Graphics;
Bitmapbmp=newBitmap("rama.jpg");
g.FillRectangle(Brushes.White,this.ClientRectangle);
Rectanglesr=newRectangle(80,60,400,400);//要截取的矩形区域
Rectangledr=newRectangle(0,0,200,200);//要显示到Form的矩形区域
g.DrawImage(bmp,dr,sr,GraphicsUnit.Pixel);
}
//改变图像大小:
privatevoidForm1_Paint(objectsender,System.Windows.Forms.PaintEventArgse)
{
Graphicsg=e.Graphics;
Bitmapbmp=newBitmap("rama.jpg");
g.FillRectangle(Brushes.White,this.ClientRectangle);
intwidth=bmp.Width;
intheight=bmp.Height;
//改变图像大小使用低质量的模式
g.InterpolationMode=InterpolationMode.NearestNeighbor;
g.DrawImage(bmp,newRectangle(10,10,120,120),//sourcerectangle
newRectangle(0,0,width,height),//destinationrectangle
GraphicsUnit.Pixel);
//使用高质量模式
//g.CompositingQuality=CompositingQuality.HighSpeed;
g.InterpolationMode=InterpolationMode.HighQualityBicubic;
g.DrawImage(
bmp,
newRectangle(130,10,120,120),
newRectangle(0,0,width,height),
GraphicsUnit.Pixel);
}
//设置图像的分辩率:
privatevoidForm1_Paint(objectsender,System.Windows.Forms.PaintEventArgse)
{
Graphicsg=e.Graphics;
Bitmapbmp=newBitmap("rama.jpg");
g.FillRectangle(Brushes.White,this.ClientRectangle);
bmp.SetResolution(300f,300f);
g.DrawImage(bmp,0,0);
bmp.SetResolution(1200f,1200f);
g.DrawImage(bmp,180,0);
}
//用GDI+画图
privatevoidForm1_Paint(objectsender,System.Windows.Forms.PaintEventArgse)
{
GraphicsgForm=e.Graphics;
gForm.FillRectangle(Brushes.White,this.ClientRectangle);
for(inti=1;i<=7;++i)
{
//在窗体上面画出橙色的矩形
Rectangler=newRectangle(i*40-15,0,15,
this.ClientRectangle.Height);
gForm.FillRectangle(Brushes.Orange,r);
}
//在内存中创建一个Bitmap并设置CompositingMode
Bitmapbmp=newBitmap(260,260,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GraphicsgBmp=Graphics.FromImage(bmp);
gBmp.CompositingMode=System.Drawing.Drawing2D.CompositingMode.SourceCopy;
//创建一个带有Alpha的红色区域
//并将其画在内存的位图里面
Colorred=Color.FromArgb(0x60,0xff,0,0);
BrushredBrush=newSolidBrush(red);
gBmp.FillEllipse(redBrush,70,70,160,160);
//创建一个带有Alpha的绿色区域
Colorgreen=Color.FromArgb(0x40,0,0xff,0);
BrushgreenBrush=newSolidBrush(green);
gBmp.FillRectangle(greenBrush,10,10,140,140);
//在窗体上面画出位图nowdrawthebitmaponourwindow
gForm.DrawImage(bmp,20,20,bmp.Width,bmp.Height);
//清理资源
bmp.Dispose();
gBmp.Dispose();
redBrush.Dispose();
greenBrush.Dispose();
}
//在窗体上面绘图并显示图像
privatevoidForm1_Paint(objectsender,System.Windows.Forms.PaintEventArgse)
{
Graphicsg=e.Graphics;
PenblackPen=newPen(Color.Black,1);
if(ClientRectangle.Height/10>0)
{
for(inty=0;y<ClientRectangle.Height;y+=ClientRectangle.Height/10)
{
g.DrawLine(blackPen,newPoint(0,0),newPoint(ClientRectangle.Width,y));
}
}
blackPen.Dispose();
}
C#使用Bitmap类进行图片裁剪
在Mapwin(手机游戏地图编辑器)生成的地图txt文件中添加自己需要处理的数据后转换成可在手机(Ophone)开发环境中使用的字节流地图文件的小工具,其中就涉及到图片的裁剪和生成了。有以下几种方式。
方法一:拷贝像素。
当然这种方法是最笨的,效率也就低了些。
在Bitmap类中我们可以看到这样两个方法:GetPixel(intx,inty)和SetPixel(intx,inty,Colorcolor)方法。从字面的含以上就知道前者是获取图像某点像素值,是用Color对象返回的;后者是将已知像素描画到制定的位置。
下面就来做个实例检验下:
1.首先创建一个WindowsForm窗体程序,往该窗体上拖放7个PictureBox控件,第一个用于放置并显示原始的大图片,其后6个用于放置并显示裁剪后新生成的6个小图;
2.放置原始大图的PictureBox控件name属性命名为pictureBoxBmpRes,其后pictureBox1到pictureBox6依次命名,并放置在合适的位置;
3.双击Form窗体,然后在Form1_Load事件中加入下面的代码即可。
//导入图像资源
BitmapbmpRes=null;
StringstrPath=Application.ExecutablePath;
try{
intnEndIndex=strPath.LastIndexOf('//');
strPath=strPath.Substring(0,nEndIndex)+"//Bmp//BmpResMM.bmp";
bmpRes=newBitmap(strPath);
//窗体上显示加载图片
pictureBoxBmpRes.Width=bmpRes.Width;
pictureBoxBmpRes.Height=bmpRes.Height;
pictureBoxBmpRes.Image=bmpRes;
}
catch(Exceptionex)
{
System.Windows.Forms.MessageBox.Show("图片资源加载失败!/r/n"+ex.ToString());
}
//裁剪图片(裁成2行3列的6张图片)
intnYClipNum=2,nXClipNum=3;
Bitmap[]bmpaClipBmpArr=newBitmap[nYClipNum*nXClipNum];
for(intnYClipNumIndex=0;nYClipNumIndex<nYClipNum;nYClipNumIndex++)
{
for(intnXClipNumIndex=0;nXClipNumIndex<nXClipNum;nXClipNumIndex++)
{
intnClipWidth=bmpRes.Width/nXClipNum;
intnClipHight=bmpRes.Height/nYClipNum;
intnBmpIndex=nXClipNumIndex+nYClipNumIndex*nYClipNum+(nYClipNumIndex>0?1:0);
bmpaClipBmpArr[nBmpIndex]=newBitmap(nClipWidth,nClipHight);
for(intnY=0;nY<nClipHight;nY++)
{
for(intnX=0;nX<nClipWidth;nX++)
{
intnClipX=nX+nClipWidth*nXClipNumIndex;
intnClipY=nY+nClipHight*nYClipNumIndex;
ColorcClipPixel=bmpRes.GetPixel(nClipX,nClipY);
bmpaClipBmpArr[nBmpIndex].SetPixel(nX,nY,cClipPixel);
}
}
}
}
PictureBox[]picbShow=newPictureBox[nYClipNum*nXClipNum];
picbShow[0]=pictureBox1;
picbShow[1]=pictureBox2;
picbShow[2]=pictureBox3;
picbShow[3]=pictureBox4;
picbShow[4]=pictureBox5;
picbShow[5]=pictureBox6;
for(intnLoop=0;nLoop<nYClipNum*nXClipNum;nLoop++)
{
picbShow[nLoop].Width=bmpRes.Width/nXClipNum;
picbShow[nLoop].Height=bmpRes.Height/nYClipNum;
picbShow[nLoop].Image=bmpaClipBmpArr[nLoop];
}
现在看看那些地方需要注意的了。其中
intnBmpIndex=
nXClipNumIndex+nYClipNumIndex*nYClipNum+(nYClipNumIndex>0?1:0);
这句定义了存储裁剪图片对象在数组中的索引,需要注意的就是后面的(nYClipNumIndex>0?1:0)——因为只有当裁剪的对象处于第一行以外的行时需要将索引加1;
另外,因为这种方法的效率不高,程序运行起来还是顿了下。如果有兴趣的话,可以将以上的代码放到一个按钮Click事件函数中,当单击该按钮时就可以感觉到了。
方法二:运用Clone函数局部复制。
同样在Bitmap中可以找到Clone()方法,该方法有三个重载方法。Clone(),Clone(Rectangle,PixelFormat)和Clone(RectangleF,PixelFormat)。第一个方法将创建并返回一个精确的实例对象,后两个就是我们这里需要用的局部裁剪了(其实后两个方法本人觉得用法上差不多)。
将上面的程序稍稍改进下——将裁剪的处理放到一个按钮事件函数中,然后再托一个按钮好窗体上,最后将下面的代码复制到该按钮的事件函数中。
for(intnYClipNumIndex=0;nYClipNumIndex<nYClipNum;nYClipNumIndex++)
{
for(intnXClipNumIndex=0;nXClipNumIndex<nXClipNum;nXClipNumIndex++)
{
intnClipWidth=bmpRes.Width/nXClipNum;
intnClipHight=bmpRes.Height/nYClipNum;
intnBmpIndex=
nXClipNumIndex+nYClipNumIndex*nYClipNum+(nYClipNumIndex>0?1:0);
RectanglerClipRect=newRectangle(nClipWidth*nXClipNumIndex,
nClipHight*nYClipNumIndex,
nClipWidth,
nClipHight);
bmpaClipBmpArr[nBmpIndex]=bmpRes.Clone(rClipRect,bmpRes.PixelFormat);
}
}
运行程序,单击按钮检验下,发现速度明显快可很多。
其实这种方法较第一中方法不同的地方仅只是变换了for循环中的拷贝部分的处理,
RectanglerClipRect=newRectangle(nClipWidth*nXClipNumIndex,
nClipHight*nYClipNumIndex,
nClipWidth,
nClipHight);
bmpaClipBmpArr[nBmpIndex]=bmpRes.Clone(rClipRect,bmpRes.PixelFormat);
一.底片效果
原理:GetPixel方法获得每一点像素的值,然后再使用SetPixel方法将取反后的颜色值设置到对应的点.
效果图:
代码实现:
privatevoidbutton1_Click(objectsender,EventArgse)
{
//以底片效果显示图像
try
{
intHeight=this.pictureBox1.Image.Height;
intWidth=this.pictureBox1.Image.Width;
Bitmapnewbitmap=newBitmap(Width,Height);
Bitmapoldbitmap=(Bitmap)this.pictureBox1.Image;
Colorpixel;
for(intx=1;x<Width;x++)
{
for(inty=1;y<Height;y++)
{
intr,g,b;
pixel=oldbitmap.GetPixel(x,y);
r=255-pixel.R;
g=255-pixel.G;
b=255-pixel.B;
newbitmap.SetPixel(x,y,Color.FromArgb(r,g,b));
}
}
this.pictureBox1.Image=newbitmap;
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message,"信息提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
}
二.浮雕效果
原理:对图像像素点的像素值分别与相邻像素点的像素值相减后加上128,然后将其作为新的像素点的值.
效果图:
代码实现:
privatevoidbutton1_Click(objectsender,EventArgse)
{
//以浮雕效果显示图像
try
{
intHeight=this.pictureBox1.Image.Height;
intWidth=this.pictureBox1.Image.Width;
BitmapnewBitmap=newBitmap(Width,Height);
BitmapoldBitmap=(Bitmap)this.pictureBox1.Image;
Colorpixel1,pixel2;
for(intx=0;x<Width-1;x++)
{
for(inty=0;y<Height-1;y++)
{
intr=0,g=0,b=0;
pixel1=oldBitmap.GetPixel(x,y);
pixel2=oldBitmap.GetPixel(x+1,y+1);
r=Math.Abs(pixel1.R-pixel2.R+128);
g=Math.Abs(pixel1.G-pixel2.G+128);
b=Math.Abs(pixel1.B-pixel2.B+128);
if(r>255)
r=255;
if(r<0)
r=0;
if(g>255)
g=255;
if(g<0)
g=0;
if(b>255)
b=255;
if(b<0)
b=0;
newBitmap.SetPixel(x,y,Color.FromArgb(r,g,b));
}
}
this.pictureBox1.Image=newBitmap;
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message,"信息提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
}
三.黑白效果
原理:彩色图像处理成黑白效果通常有3种算法;
(1).最大值法:使每个像素点的R,G,B值等于原像素点的RGB(颜色值)中最大的一个;
(2).平均值法:使用每个像素点的R,G,B值等于原像素点的RGB值的平均值;
(3).加权平均值法:对每个像素点的R,G,B值进行加权
---自认为第三种方法做出来的黑白效果图像最"真实".
效果图:
代码实现:
privatevoidbutton1_Click(objectsender,EventArgse)
{
//以黑白效果显示图像
try
{
intHeight=this.pictureBox1.Image.Height;
intWidth=this.pictureBox1.Image.Width;
BitmapnewBitmap=newBitmap(Width,Height);
BitmapoldBitmap=(Bitmap)this.pictureBox1.Image;
Colorpixel;
for(intx=0;x<Width;x++)
for(inty=0;y<Height;y++)
{
pixel=oldBitmap.GetPixel(x,y);
intr,g,b,Result=0;
r=pixel.R;
g=pixel.G;
b=pixel.B;
//实例程序以加权平均值法产生黑白图像
intiType=2;
switch(iType)
{
case0://平均值法
Result=((r+g+b)/3);
break;
case1://最大值法
Result=r>g?r:g;
Result=Result>b?Result:b;
break;
case2://加权平均值法
Result=((int)(0.7*r)+(int)(0.2*g)+(int)(0.1*b));
break;
}
newBitmap.SetPixel(x,y,Color.FromArgb(Result,Result,Result));
}
this.pictureBox1.Image=newBitmap;
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message,"信息提示");
}
}
四.柔化效果
原理:当前像素点与周围像素点的颜色差距较大时取其平均值.
效果图:
代码实现:
privatevoidbutton1_Click(objectsender,EventArgse)
{
//以柔化效果显示图像
try
{
intHeight=this.pictureBox1.Image.Height;
intWidth=this.pictureBox1.Image.Width;
Bitmapbitmap=newBitmap(Width,Height);
BitmapMyBitmap=(Bitmap)this.pictureBox1.Image;
Colorpixel;
//高斯模板
int[]Gauss={1,2,1,2,4,2,1,2,1};
for(intx=1;x<Width-1;x++)
for(inty=1;y<Height-1;y++)
{
intr=0,g=0,b=0;
intIndex=0;
for(intcol=-1;col<=1;col++)
for(introw=-1;row<=1;row++)
{
pixel=MyBitmap.GetPixel(x+row,y+col);
r+=pixel.R*Gauss[Index];
g+=pixel.G*Gauss[Index];
b+=pixel.B*Gauss[Index];
Index++;
}
r/=16;
g/=16;
b/=16;
//处理颜色值溢出
r=r>255?255:r;
r=r<0?0:r;
g=g>255?255:g;
g=g<0?0:g;
b=b>255?255:b;
b=b<0?0:b;
bitmap.SetPixel(x-1,y-1,Color.FromArgb(r,g,b));
}
this.pictureBox1.Image=bitmap;
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message,"信息提示");
}
}
五.锐化效果
原理:突出显示颜色值大(即形成形体边缘)的像素点.
效果图:
实现代码:
privatevoidbutton1_Click(objectsender,EventArgse)
{
//以锐化效果显示图像
try
{
intHeight=this.pictureBox1.Image.Height;
intWidth=this.pictureBox1.Image.Width;
BitmapnewBitmap=newBitmap(Width,Height);
BitmapoldBitmap=(Bitmap)this.pictureBox1.Image;
Colorpixel;
//拉普拉斯模板
int[]Laplacian={-1,-1,-1,-1,9,-1,-1,-1,-1};
for(intx=1;x<Width-1;x++)
for(inty=1;y<Height-1;y++)
{
intr=0,g=0,b=0;
intIndex=0;
for(intcol=-1;col<=1;col++)
for(introw=-1;row<=1;row++)
{
pixel=oldBitmap.GetPixel(x+row,y+col);r+=pixel.R*Laplacian[Index];
g+=pixel.G*Laplacian[Index];
b+=pixel.B*Laplacian[Index];
Index++;
}
//处理颜色值溢出
r=r>255?255:r;
r=r<0?0:r;
g=g>255?255:g;
g=g<0?0:g;
b=b>255?255:b;
b=b<0?0:b;
newBitmap.SetPixel(x-1,y-1,Color.FromArgb(r,g,b));
}
this.pictureBox1.Image=newBitmap;
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message,"信息提示");
}
}
六.雾化效果
原理:在图像中引入一定的随机值,打乱图像中的像素值
效果图:
实现代码:
privatevoidbutton1_Click(objectsender,EventArgse)
{
//以雾化效果显示图像
try
{
intHeight=this.pictureBox1.Image.Height;
intWidth=this.pictureBox1.Image.Width;
BitmapnewBitmap=newBitmap(Width,Height);
BitmapoldBitmap=(Bitmap)this.pictureBox1.Image;
Colorpixel;
for(intx=1;x<Width-1;x++)
for(inty=1;y<Height-1;y++)
{
System.RandomMyRandom=newRandom();
intk=MyRandom.Next(123456);
//像素块大小
intdx=x+k%19;
intdy=y+k%19;
if(dx>=Width)
dx=Width-1;
if(dy>=Height)
dy=Height-1;
pixel=oldBitmap.GetPixel(dx,dy);
newBitmap.SetPixel(x,y,pixel);
}
this.pictureBox1.Image=newBitmap;
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message,"信息提示");
}
}
浅谈VisualC#进行图像处理
作者:彭军
'target='_blank'>http://pengjun.org.cn
这里之所以说“浅谈”是因为我这里只是简单的介绍如何使用VisualC#进行图像的读入、保存以及对像素的访问。而不涉及太多的算法。
一、读入图像
在VisualC#中我们可以使用一个PictureBox控件来显示图片,如下:
privatevoidbtnOpenImage_Click(objectsender,EventArgse)
{
OpenFileDialogofd=newOpenFileDialog();
ofd.Filter="BMPFiles(*.bmp)|*.bmp|JPGFiles(*.jpg;*.jpeg)|*.jpg;*.jpeg|AllFiles(*.*)|*.*";
ofd.CheckFileExists=true;
ofd.CheckPathExists=true;
if(ofd.ShowDialog()==DialogResult.OK)
{
//pbxShowImage.ImageLocation=ofd.FileName;
bmp=newBitmap(ofd.FileName);
if(bmp==null)
{
MessageBox.Show("加载图片失败!","错误");
return;
}
pbxShowImage.Image=bmp;
ofd.Dispose();
}
}
其中bmp为类的一个对象:privateBitmapbmp=null;
在使用Bitmap类和BitmapData类之前,需要使用usingSystem.Drawing.Imaging;
二、保存图像
privatevoidbtnSaveImage_Click(objectsender,EventArgse)
{
if(bmp==null)return;
SaveFileDialogsfd=newSaveFileDialog();
sfd.Filter="BMPFiles(*.bmp)|*.bmp|JPGFiles(*.jpg;*.jpeg)|*.jpg;*.jpeg|AllFiles(*.*)|*.*";
if(sfd.ShowDialog()==DialogResult.OK)
{
pbxShowImage.Image.Save(sfd.FileName);
MessageBox.Show("保存成功!","提示");
sfd.Dispose();
}
}
三、对像素的访问
我们可以来建立一个GrayBitmapData类来做相关的处理。整个类的程序如下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Drawing;
usingSystem.Drawing.Imaging;
usingSystem.Windows.Forms;
namespaceImageElf
{
classGrayBitmapData
{
publicbyte[,]Data;//保存像素矩阵
publicintWidth;//图像的宽度
publicintHeight;//图像的高度
publicGrayBitmapData()
{
this.Width=0;
this.Height=0;
this.Data=null;
}
publicGrayBitmapData(Bitmapbmp)
{
BitmapDatabmpData=bmp.LockBits(newRectangle(0,0,bmp.Width,bmp.Height),ImageLockMode.ReadOnly,PixelFormat.Format24bppRgb);
this.Width=bmpData.Width;
this.Height=bmpData.Height;
Data=newbyte[Height,Width];
unsafe
{
byte*ptr=(byte*)bmpData.Scan0.ToPointer();
for(inti=0;i<Height;i++)
{
for(intj=0;j<Width;j++)
{
//将24位的RGB彩色图转换为灰度图
inttemp=(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);
}
publicGrayBitmapData(stringpath)
:this(newBitmap(path))
{
}
publicBitmapToBitmap()
{
Bitmapbmp=newBitmap(Width,Height,PixelFormat.Format24bppRgb);
BitmapDatabmpData=bmp.LockBits(newRectangle(0,0,Width,Height),ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb);
unsafe
{
byte*ptr=(byte*)bmpData.Scan0.ToPointer();
for(inti=0;i<Height;i++)
{
for(intj=0;j<Width;j++)
{
*(ptr++)=Data[i,j];
*(ptr++)=Data[i,j];
*(ptr++)=Data[i,j];
}
ptr+=bmpData.Stride-Width*3;
}
}
bmp.UnlockBits(bmpData);
returnbmp;
}
publicvoidShowImage(PictureBoxpbx)
{
Bitmapb=this.ToBitmap();
pbx.Image=b;
//b.Dispose();
}
publicvoidSaveImage(stringpath)
{
Bitmapb=ToBitmap();
b.Save(path);
//b.Dispose();
}
//均值滤波
publicvoidAverageFilter(intwindowSize)
{
if(windowSize%2==0)
{
return;
}
for(inti=0;i<Height;i++)
{
for(intj=0;j<Width;j++)
{
intsum=0;
for(intg=-(windowSize-1)/2;g<=(windowSize-1)/2;g++)
{
for(intk=-(windowSize-1)/2;k<=(windowSize-1)/2;k++)
{
inta=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));
}
}
}
//中值滤波
publicvoidMidFilter(intwindowSize)
{
if(windowSize%2==0)
{
return;
}
int[]temp=newint[windowSize*windowSize];
byte[,]newdata=newbyte[Height,Width];
for(inti=0;i<Height;i++)
{
for(intj=0;j<Width;j++)
{
intn=0;
for(intg=-(windowSize-1)/2;g<=(windowSize-1)/2;g++)
{
for(intk=-(windowSize-1)/2;k<=(windowSize-1)/2;k++)
{
inta=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(inti=0;i<Height;i++)
{
for(intj=0;j<Width;j++)
{
Data[i,j]=newdata[i,j];
}
}
}
//获得一个向量的中值
privatebyteGetMidValue(int[]t,intlength)
{
inttemp=0;
for(inti=0;i<length-2;i++)
{
for(intj=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];
}
//一种新的滤波方法,是亮的更亮、暗的更暗
publicvoidNewFilter(intwindowSize)
{
if(windowSize%2==0)
{
return;
}
for(inti=0;i<Height;i++)
{
for(intj=0;j<Width;j++)
{
intsum=0;
for(intg=-(windowSize-1)/2;g<=(windowSize-1)/2;g++)
{
for(intk=-(windowSize-1)/2;k<=(windowSize-1)/2;k++)
{
inta=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];
}
}
doubleavg=(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);
}
}
}
}
//直方图均衡
publicvoidHistEqual()
{
double[]num=newdouble[256];
for(inti=0;i<256;i++)num[i]=0;
for(inti=0;i<Height;i++)
{
for(intj=0;j<Width;j++)
{
num[Data[i,j]]++;
}
}
double[]newGray=newdouble[256];
doublen=0;
for(inti=0;i<256;i++)
{
n+=num[i];
newGray[i]=n*255/(Height*Width);
}
for(inti=0;i<Height;i++)
{
for(intj=0;j<Width;j++)
{
Data[i,j]=(byte)newGray[Data[i,j]];
}
}
}
}
}
在GrayBitmapData类中,只要我们对一个二维数组Data进行一系列的操作就是对图片的操作处理。在窗口上,我们可以使用
一个按钮来做各种调用:
//均值滤波
privatevoidbtnAvgFilter_Click(objectsender,EventArgse)
{
if(bmp==null)return;
GrayBitmapDatagbmp=newGrayBitmapData(bmp);
gbmp.AverageFilter(3);
gbmp.ShowImage(pbxShowImage);
}
//转换为灰度图
privatevoidbtnToGray_Click(objectsender,EventArgse)
{
if(bmp==null)return;
GrayBitmapDatagbmp=newGrayBitmapData(bmp);
gbmp.ShowImage(pbxShowImage);
}
四、总结
在Visualc#中对图像进行处理或访问,需要先建立一个Bitmap对象,然后通过其LockBits方法来获得一个BitmapData类的对象,然后通过获得其像素数据的首地址来对Bitmap对象的像素数据进行操作。当然,一种简单但是速度慢的方法是用Bitmap类的GetPixel和SetPixel方法。其中BitmapData类的Stride属性为每行像素所占的字节。

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐