for(int x = -fi; x <=fi; x++) for(int y = -fi; y <= fi; y++) { int sqrtFi = fi * fi; double ex = Math.Pow(Math.E, (-(x * x + y * y)/(2 * sqrtFi))); double result = ex / (2 * Math.PI * sqrtFi); GAUSS[x + fi, y + fi] = result; } }
//事先计算好每个像素在卷积中要用到的值,避免重复运算, WeightedColor是自定义struct, 只有3个字段, //分别是double R; double G; double B; private WeightedColor[,,] GetWeightedColor(Bitmap source, int fi) { WeightedColor[,,] retVal = new WeightedColor[fi + 1 + fi, source.Width, source.Height]; double r = 0, g = 0, b = 0;
for(int i = 0; i < source.Width; i++) for(int j = 0; j <source.Height; j++) { //Calculate weighted color Color c = source.GetPixel(i, j);
for(int k = 0; k < fi + 1 + fi; k++) { //From center to edge double weight; if( k < fi + 1) weight = GAUSS[fi, fi + k]; else //对角 weight = GAUSS[k, k]; r = c.R * weight; g = c.G * weight; b = c.B * weight; r = r > 255 ? 255 : r; g = g > 255 ? 255 : g; b = b > 255 ? 255 : b; retVal[k, i, j] = WeightedColor.FromRGB(r, g, b); } }
//计算一个点的卷积值 private Color GetFilteredColor(Bitmap source, int x, int y, int fi, WeightedColor[,,] colorMap) { int w = source.Width, h = source.Height; double r = 0, g = 0, b = 0;
for(int u = x - fi; u <= x + fi; u++) for(int v = y - fi; v <= y + fi; v++) { if(u > = 0 && u < w && v > = 0 && v < h) { //wx, wy is the distance between x and u, y and v int wx = Math.Abs(u - x), wy = Math.Abs(v - y); //Use which version of colorMap int wVersion; if(wx == wy && wx != 0)//对角 wVersion = fi + wx; else wVersion = wx > wy ? wx : wy; WeightedColor tmpC = colorMap[wVersion, u, v]; r += tmpC.R; g += tmpC.G; b += tmpC.B; } } r = r > 255 ? 255 : r; g = g > 255 ? 255 : g; b = b > 255 ? 255 : b; return Color.FromArgb((int)r, (int)g, (int)b); } return retVal; }
//使用这个函数对图像进行过滤 private Bitmap GaussianFilt(Bitmap source, int fi) { Bitmap retVal = new Bitmap(source.Width, source.Height); WeightedColor[,,] colorMap = GetWeightedColor(source, fi); for(int i = 0; i < source.Width; i++) for(int j = 0; j <source.Height; j++) { Color fColor = GetFilteredColor(source, i, j, fi, colorMap); retVal.SetPixel(i, j, fColor); } return retVal; }
int Height = this.pictureBox1.Image.Height; int Width = this.pictureBox1.Image.Width; Bitmap bitmap = new Bitmap(Width, Height); Bitmap Mybitmap = (Bitmap)this.pictureBox1.Image; Color pixel; for (int y = 0; y < Height; y++) { pixel = Mybitmap.GetPixel(x, y); int r, g, b, Result = 0; r = pixel.R; g = pixel.G; b = pixel.B; int iType = 1; switch (iType) { case 0://平均值法 Result = ((r + g + b) / 3); break; case 1://最大值法 Result = r > g ? r : g; Result = Result > b ? Result : b; break; case 2://加权平均值 Result = ((int)(0.7 * r) + (int)(0.2 * g) + (int)(0.1 * b)); break; } bitmap.SetPixel(x, y, Color.FromArgb(Result, Result, Result)); }3种方式自己选一中就行了
private void button2_Click(object sender, EventArgs e) { Graphics myGraphics = this.CreateGraphics(); Bitmap myBitmap = new Bitmap(this.BackgroundImage); int myWidth, myHeight, i, j, iAvg, iPixel; Color myColor, myNewColor; RectangleF myRect; myWidth = myBitmap.Width; myHeight = myBitmap.Height; myRect = new RectangleF(0, 0, myWidth, myHeight); Bitmap bitmap = myBitmap.Clone(myRect, System.Drawing.Imaging.PixelFormat.DontCare); i = 0; while (i < myWidth - 1) { j = 0; while (j < myHeight - 1) { myColor = bitmap.GetPixel(i, j); iAvg = (myColor.R + myColor.G + myColor.B) / 3; iPixel = 0; if (iAvg >= 128) iPixel = 255; else iPixel = 0; myNewColor = Color.FromArgb(255, iPixel, iPixel, iPixel); bitmap.SetPixel(i, j, myNewColor); j = j + 1; } i = i + 1; } myGraphics.Clear(Color.WhiteSmoke); myGraphics.DrawImage(bitmap, new Rectangle(0, 0, myWidth, myHeight)); } 积木效果 //
高斯模糊的.net实现
选择.net来做图像处理唯一的好处就是避免了烦琐的编程细节,可以全部精力投入在算法上.
在图像结构分析之前,我使用了高斯模糊来去粗取精, 将细节部分的去掉,将边缘强化.
高斯模糊的算法很简单了, 使用高斯函数和图像做卷积, 不过复杂度真是不错, 宽度=2的高斯模糊要做 24*n(n是图像像素)次浮点运算
不过如果把重复计算的除外,就只有4*n次了, 而且宽度约大, 重复计算的越多. 我最早实现的不加任何优化的算法真是奇满无比,在被
acdsee的高斯模糊速度bs后,我开始优化,最后终于在速度上比较能够接受(还是要被acdsee鄙视)不过,这个慢速度,vm也多少要负点责任吧...(我又不能使用pointer,所有的数值在使用时都是copy的,这个就比用c实现慢多了...)
private double[,] GAUSS; //高斯函数的值, 每次都计算高斯函数太夸张了吧...事先计算好,放这里备用
private const int FI = 2; //高斯函数宽度
//初试化高斯函数
private void IniGauss(int fi) {
GAUSS = new double[fi * 2 + 1, fi * 2 + 1];
for(int x = -fi; x <=fi; x++)
for(int y = -fi; y <= fi; y++) {
int sqrtFi = fi * fi;
double ex = Math.Pow(Math.E, (-(x * x + y * y)/(2 * sqrtFi)));
double result = ex / (2 * Math.PI * sqrtFi);
GAUSS[x + fi, y + fi] = result;
}
}
//事先计算好每个像素在卷积中要用到的值,避免重复运算, WeightedColor是自定义struct, 只有3个字段,
//分别是double R; double G; double B;
private WeightedColor[,,] GetWeightedColor(Bitmap source, int fi) {
WeightedColor[,,] retVal = new WeightedColor[fi + 1 + fi, source.Width, source.Height];
double r = 0, g = 0, b = 0;
for(int i = 0; i < source.Width; i++)
for(int j = 0; j <source.Height; j++) {
//Calculate weighted color
Color c = source.GetPixel(i, j);
for(int k = 0; k < fi + 1 + fi; k++) {
//From center to edge
double weight;
if( k < fi + 1)
weight = GAUSS[fi, fi + k];
else
//对角
weight = GAUSS[k, k];
r = c.R * weight;
g = c.G * weight;
b = c.B * weight;
r = r > 255 ? 255 : r;
g = g > 255 ? 255 : g;
b = b > 255 ? 255 : b;
retVal[k, i, j] = WeightedColor.FromRGB(r, g, b);
}
}
//计算一个点的卷积值
private Color GetFilteredColor(Bitmap source, int x, int y, int fi, WeightedColor[,,] colorMap) {
int w = source.Width, h = source.Height;
double r = 0, g = 0, b = 0;
for(int u = x - fi; u <= x + fi; u++)
for(int v = y - fi; v <= y + fi; v++) {
if(u > = 0 && u < w && v > = 0 && v < h) {
//wx, wy is the distance between x and u, y and v
int wx = Math.Abs(u - x), wy = Math.Abs(v - y);
//Use which version of colorMap
int wVersion;
if(wx == wy && wx != 0)//对角
wVersion = fi + wx;
else
wVersion = wx > wy ? wx : wy;
WeightedColor tmpC = colorMap[wVersion, u, v];
r += tmpC.R;
g += tmpC.G;
b += tmpC.B;
}
}
r = r > 255 ? 255 : r;
g = g > 255 ? 255 : g;
b = b > 255 ? 255 : b;
return Color.FromArgb((int)r, (int)g, (int)b);
}
return retVal;
}
//使用这个函数对图像进行过滤
private Bitmap GaussianFilt(Bitmap source, int fi) {
Bitmap retVal = new Bitmap(source.Width, source.Height);
WeightedColor[,,] colorMap = GetWeightedColor(source, fi);
for(int i = 0; i < source.Width; i++)
for(int j = 0; j <source.Height; j++) {
Color fColor = GetFilteredColor(source, i, j, fi, colorMap);
retVal.SetPixel(i, j, fColor);
}
return retVal;
}
//使用范例
Bitmap fbmp = GaussianFilt(bmp, FI);
pictureBox1.Image = fbmp;
int Height = this.pictureBox1.Image.Height;
int Width = this.pictureBox1.Image.Width;
Bitmap bitmap = new Bitmap(Width, Height);
Bitmap Mybitmap = (Bitmap)this.pictureBox1.Image;
Color pixel;
for (int y = 0; y < Height; y++)
{
pixel = Mybitmap.GetPixel(x, y);
int r, g, b, Result = 0;
r = pixel.R;
g = pixel.G;
b = pixel.B; int iType = 1;
switch (iType)
{
case 0://平均值法
Result = ((r + g + b) / 3);
break;
case 1://最大值法
Result = r > g ? r : g;
Result = Result > b ? Result : b;
break;
case 2://加权平均值
Result = ((int)(0.7 * r) + (int)(0.2 * g) + (int)(0.1 * b));
break;
}
bitmap.SetPixel(x, y, Color.FromArgb(Result, Result, Result));
}3种方式自己选一中就行了
{
Graphics myGraphics = this.CreateGraphics();
Bitmap myBitmap = new Bitmap(this.BackgroundImage);
int myWidth, myHeight, i, j, iAvg, iPixel;
Color myColor, myNewColor;
RectangleF myRect;
myWidth = myBitmap.Width;
myHeight = myBitmap.Height;
myRect = new RectangleF(0, 0, myWidth, myHeight);
Bitmap bitmap = myBitmap.Clone(myRect, System.Drawing.Imaging.PixelFormat.DontCare);
i = 0;
while (i < myWidth - 1)
{
j = 0;
while (j < myHeight - 1)
{
myColor = bitmap.GetPixel(i, j);
iAvg = (myColor.R + myColor.G + myColor.B) / 3;
iPixel = 0;
if (iAvg >= 128)
iPixel = 255;
else
iPixel = 0;
myNewColor = Color.FromArgb(255, iPixel, iPixel, iPixel);
bitmap.SetPixel(i, j, myNewColor);
j = j + 1;
}
i = i + 1;
}
myGraphics.Clear(Color.WhiteSmoke);
myGraphics.DrawImage(bitmap, new Rectangle(0, 0, myWidth, myHeight));
}
积木效果
//