还只是个菜鸟,不过想开个博客,记录一下自己的学习过程!
最近在一家医疗软件公司实习,负责的是OCR(光学字符识别)部分!进行OCR之前难免会碰到图像处理,因此写了一个图像处理工具箱(ImageProcessUtilities),看网上有人讲过在进行OCR之前,进行图像二值化,图像锐化,中值滤波,线性灰度变化,转换为黑白灰度图完全就足够了!
这个工具箱大概也是实现这些功能,首先类视图,
下面给出代码,希望大家多批评指下,之后会后续发布OCR检索其他方面的工具,诸如文字后处理的正则表达等!
public class ImageProcessUtility
{
//暂时只对24位图和8位图进行处理
#region 图像扩边函数
/// <summary>
/// 图像扩边函数
/// </summary>
/// <param name="width">扩边后图像的宽度</param>
/// <param name="height">扩边后图像的高度</param>
/// <param name="inputBitmap">需要扩边的图像</param>
/// <returns>完成扩边后的图像</returns>
public static Bitmap ImageExpand(int width, int height, Bitmap inputBitmap)
{
try
{
Bitmap bitmap = new Bitmap(width, height);
Graphics g = Graphics.FromImage(bitmap);
g.Clear(Color.Black);
int start_X = (width - inputBitmap.Width) / 2;
int start_Y = (height - inputBitmap.Height) / 2;
g.DrawImage(inputBitmap, new Point(start_X, start_Y));
g.Dispose();
return bitmap;
}
catch
{
return null;
}
}
#endregion
#region 图像缩放函数
/// <summary>
/// 图像缩放函数
/// </summary>
/// <param name="scale">缩放因子</param>
/// <param name="inputBitmap">需要缩放的图像</param>
/// <returns>缩放后的图像</returns>
public static Bitmap ImageResize(double scale, Bitmap inputBitmap)
{
try
{
int newWidth = Convert.ToInt32(inputBitmap.Width * scale);
int newHeight = Convert.ToInt32(inputBitmap.Height * scale);
Bitmap bitmap = new Bitmap(newWidth, newHeight);
Graphics g = Graphics.FromImage(bitmap);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(inputBitmap, new Rectangle(0, 0, newWidth, newHeight),
new Rectangle(0,0,inputBitmap.Width, inputBitmap.Height), GraphicsUnit.Pixel);
g.Dispose();
return bitmap;
}
catch
{
return null;
}
}
#endregion
#region 转换为8位灰度图像
/// <summary>
/// 将图像转换成8位Bitmap图像函数
/// </summary>
/// <param name="inputBitmap">要转换的图像</param>
/// <returns>转换后的图像</returns>
public static Bitmap ToGray(Bitmap inputBitmap)
{
Bitmap bmp = new Bitmap(inputBitmap.Width, inputBitmap.Height, PixelFormat.Format8bppIndexed);
//设定实例BitmapData相关信息
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData data = inputBitmap.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
//锁定bmp到系统内存中
BitmapData data2 = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
//获取位图中第一个像素数据的地址
IntPtr ptr = data.Scan0;
IntPtr ptr2 = data2.Scan0;
int numBytes = data.Stride * data.Height;
int numBytes2 = data2.Stride * data2.Height;
int n2 = data2.Stride - bmp.Width; 显示宽度与扫描线宽度的间隙
byte[] rgbValues = new byte[numBytes];
byte[] rgbValues2 = new byte[numBytes2];
//将bmp数据Copy到申明的数组中
Marshal.Copy(ptr, rgbValues, 0, numBytes);
Marshal.Copy(ptr2, rgbValues2, 0, numBytes2);
int n = 0;
for (int y = 0; y < bmp.Height; y++)
{
for (int x = 0; x < bmp.Width * 3; x += 3)
{
int i = data.Stride * y + x;
double value = rgbValues[i + 2] * 0.299 + rgbValues[i + 1] * 0.587 + rgbValues[i] * 0.114; //计算灰度
rgbValues2[n] = (byte)value;
n++;
}
n += n2; //跳过差值
}
//将数据Copy到内存指针
Marshal.Copy(rgbValues, 0, ptr, numBytes);
Marshal.Copy(rgbValues2, 0, ptr2, numBytes2);
下面的代码是为了修改生成位图的索引表,从伪彩修改为灰度
ColorPalette tempPalette;
using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
{
tempPalette = tempBmp.Palette;
}
for (int i = 0; i < 256; i++)
{
tempPalette.Entries[i] = Color.FromArgb(i, i, i);
}
bmp.Palette = tempPalette;
//从系统内存解锁bmp
inputBitmap.UnlockBits(data);
bmp.UnlockBits(data2);
return bmp;
}
#endregion
#region 转换为二值图像
/// <summary>
/// 图像二值化函数
/// </summary>
/// <param name="grayValue">需要二值化的图像</param>
/// <param name="inputBitmap">阈值</param>
/// <returns>完成二值化后的图像</returns>
public static Bitmap ToBinary(int grayValue, Bitmap inputBitmap)
{
//获取图像长宽
int w = inputBitmap.Width;
int h = inputBitmap.Height;
//锁定位图信息
Bitmap dstBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
System.Drawing.Imaging.BitmapData srcData = inputBitmap.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
System.Drawing.Imaging.BitmapData dstData = dstBitmap.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
unsafe
{
byte* pIn = (byte*)srcData.Scan0.ToPointer();
byte* pOut = (byte*)dstData.Scan0.ToPointer();
byte* p;
int stride = srcData.Stride;
int r, g, b;
//二值化过程
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
p = pIn;
r = p[2];
g = p[1];
b = p[0];
//灰度值等于V的为黑色,反之为白色
pOut[0] = pOut[1] = pOut[2] = (byte)(((byte)(r << 16 | g << 8 | b) == grayValue)
? 255 : 0);
pIn += 3;
pOut += 3;
}
pIn += srcData.Stride - w * 3;
pOut += srcData.Stride - w * 3;
}
//解除锁定
inputBitmap.UnlockBits(srcData);
dstBitmap.UnlockBits(dstData);
//返回处理后的图像
return dstBitmap;
}
}
#endregion
#region 中值滤波
/// <summary>
/// 图像中值滤波,在进行滤波前,
/// 若是RGB图,需要将其转换为灰度图
/// </summary>
/// <param name="mode">窗口模式:
/// 0:3*3窗口
/// 1:5*5窗口
/// </param>
/// <param name="inputBitmap"></param>
/// <returns></returns>
public static Bitmap ImageMedianFilter(int mode, Bitmap inputBitmap)
{
try
{
if (inputBitmap.PixelFormat == PixelFormat.Format24bppRgb)
inputBitmap = ToGray(inputBitmap);
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
BitmapData bmpData = inputBitmap.LockBits(rect,
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
IntPtr ptr = bmpData.Scan0;
int bytes = bmpData.Stride * bmpData.Height;
byte[] grayValues = new byte[bytes];
Marshal.Copy(ptr, grayValues, 0, bytes);
byte[] tempArray = new byte[bytes];
for (int i = 0; i < bytes; i++)
{
tempArray[i] = 0;
}
switch (mode)
{
case 0:
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
List<byte> sortArray = new List<byte>();
sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j - 1]);
sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j]);
sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j + 1]);
sortArray.Add(grayValues[i * bmpData.Stride + j - 1]);
sortArray.Add(grayValues[i * bmpData.Stride + j]);
sortArray.Add(grayValues[i * bmpData.Stride + j + 1]);
sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j - 1]);
sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j]);
sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j + 1]);
sortArray.Sort();
tempArray[i * bmpData.Stride + j] = sortArray[4];
}
}
break;
case 1:
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
List<byte> sortArray = new List<byte>();
sortArray.Add(grayValues[(i - 2) * bmpData.Stride + j - 2]);
sortArray.Add(grayValues[(i - 2) * bmpData.Stride + j - 1]);
sortArray.Add(grayValues[(i - 2) * bmpData.Stride + j]);
sortArray.Add(grayValues[(i - 2) * bmpData.Stride + j + 1]);
sortArray.Add(grayValues[(i - 2) * bmpData.Stride + j + 2]);
sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j - 2]);
sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j - 1]);
sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j]);
sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j + 1]);
sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j + 2]);
sortArray.Add(grayValues[i * bmpData.Stride + j - 2]);
sortArray.Add(grayValues[i * bmpData.Stride + j - 1]);
sortArray.Add(grayValues[i * bmpData.Stride + j]);
sortArray.Add(grayValues[i * bmpData.Stride + j + 1]);
sortArray.Add(grayValues[i * bmpData.Stride + j + 2]);
sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j - 2]);
sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j - 1]);
sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j]);
sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j + 1]);
sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j + 2]);
sortArray.Add(grayValues[(i + 2) * bmpData.Stride + j - 2]);
sortArray.Add(grayValues[(i + 2) * bmpData.Stride + j - 1]);
sortArray.Add(grayValues[(i + 2) * bmpData.Stride + j]);
sortArray.Add(grayValues[(i + 2) * bmpData.Stride + j + 1]);
sortArray.Add(grayValues[(i + 2) * bmpData.Stride + j + 2]);
sortArray.Sort();
tempArray[i * bmpData.Stride + j] = sortArray[4];
}
}
break;
default:
break;
}
grayValues = (byte[])tempArray.Clone();
Marshal.Copy(grayValues, 0, ptr, bytes);
inputBitmap.UnlockBits(bmpData);
return inputBitmap;
}
catch
{
return null;
}
}
#endregion
#region 图像锐化
/// <summary>
/// 图像锐化
/// </summary>
/// <param name="depth">
/// 锐化的程序,分布在[0,1],值越大锐化程序越高
/// </param>
/// <param name="inputBitmap">需要锐化的图像</param>
/// <returns>锐化的结果图</returns>
public static Bitmap ImageSharpen(double depth, Bitmap inputBitmap)
{
if (inputBitmap == null)
return null;
if (depth < 0.0)
depth = 0.0;
else if (depth > 1.0)
depth = 1.0;
if (inputBitmap.PixelFormat == PixelFormat.Format24bppRgb)
inputBitmap = ToGray(inputBitmap);
BitmapData srcData = inputBitmap.LockBits(new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
IntPtr ptr = srcData.Scan0;
int bytes = srcData.Stride * srcData.Height;
byte[] grayValues = new byte[bytes];
Marshal.Copy(ptr, grayValues, 0, bytes);
//存储周边边缘的差值
double temp;
for (int i = 1; i < srcData.Height - 1; i++)
{
for (int j = 1; j < srcData.Width - 1; j++)
{
temp = grayValues[i * srcData.Stride + j] -
((grayValues[(i - 1) * srcData.Stride + j - 1] +
grayValues[(i - 1) * srcData.Stride + j] +
grayValues[(i - 1) * srcData.Stride + j + 1] +
grayValues[i * srcData.Stride + j - 1] +
grayValues[i * srcData.Stride + j + 1] +
grayValues[(i + 1) * srcData.Stride + j - 1] +
grayValues[(i + 1) * srcData.Stride + j] +
grayValues[(i + 1) * srcData.Stride + j + 1])) / 8;
if (temp < 0.0)
temp = 0.0;
grayValues[i * srcData.Stride + j] -= Convert.ToByte(temp * depth);
}
}
Marshal.Copy(grayValues, 0, ptr, bytes);
inputBitmap.UnlockBits(srcData);
return inputBitmap;
}
#endregion
#region 图像膨胀函数
/// <summary>
/// 图像膨胀函数
/// </summary>
/// <param name="mode">结构元素
/// 0:3位水平方向的结构元素
/// 1:5位水平方向的结构元素
/// 2:3位垂直方向的结构元素
/// 3:5位垂直方向的结构元素
/// 4:3位十字状结构元素
/// 5:5位十字状结构元素
/// 6:3位方形结构元素
/// 7:5位方形结构元素
/// </param>
/// <param name="inputBitmap">需要膨胀的图像</param>
/// <returns>返回膨胀后的图像</returns>
public static Bitmap ImageDilate(int mode, Bitmap inputBitmap)
{
try
{
//先以255作为阈值分割点
inputBitmap = ToGray(inputBitmap);
inputBitmap = ToBinary(255, inputBitmap);
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
//以读写的方式锁定全部位图像素
System.Drawing.Imaging.BitmapData bmpData = inputBitmap.LockBits(rect,
System.Drawing.Imaging.ImageLockMode.ReadWrite,
PixelFormat.Format8bppIndexed);
IntPtr ptr = bmpData.Scan0;
//将图像数据复制到数组中,用于膨胀操作
int bytes = bmpData.Stride * bmpData.Height;
byte[] grayValues = new byte[bytes];
Marshal.Copy(ptr, grayValues, 0, bytes);
//设置临时数组,用来存储膨胀操作的结果
byte[] tempArray = new byte[bytes];
for (int i = 0; i < bytes; i++)
tempArray[i] = 0;
switch (mode)
{
//3位水平方向的结构元素
case 0:
for (int i = 0; i < bmpData.Height; i++)
{
for (int j = 1; j < bmpData.Width-1; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[i * bmpData.Stride + j + 1] == 255 ||
grayValues[i * bmpData.Stride + j - 1] == 255)
tempArray[i * bmpData.Stride + j] = 255;
}
}
break;
//5位水平方向的结构元素
case 1:
for (int i = 0; i < bmpData.Height; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[i * bmpData.Stride + j + 1] == 255 ||
grayValues[i * bmpData.Stride + j + 2] == 255 ||
grayValues[i * bmpData.Stride + j - 1] == 255 ||
grayValues[i * bmpData.Stride + j - 2] == 255)
tempArray[i * bmpData.Stride + j] = 255;
}
}
break;
//3位垂直方向的结构元素
case 2:
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j] == 255)
tempArray[i * bmpData.Stride + j] = 255;
}
}
break;
//5位垂直方向的结构元素
case 3:
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j] == 255)
tempArray[i * bmpData.Stride + j] = 255;
}
}
break;
//3位十字形状结构元素
case 4:
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
grayValues[i * bmpData.Stride + j - 1] == 255 ||
grayValues[i * bmpData.Stride + j + 1] == 255)
tempArray[i * bmpData.Stride + j] = 255;
}
}
break;
//5位十字形状结构元素
case 5:
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
grayValues[i * bmpData.Stride + j - 1] == 255 ||
grayValues[i * bmpData.Stride + j - 2] == 255)
tempArray[i * bmpData.Stride + j] = 255;
}
}
break;
//3位方形结构元素
case 6:
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j + 1] == 255)
tempArray[i * bmpData.Stride + j] = 255;
}
}
break;
//5位方形结构元素
case 7:
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (grayValues[(i - 2) * bmpData.Stride + j - 2] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j + 1] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j + 2] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j - 2] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j + 2] == 255 ||
grayValues[i * bmpData.Stride + j - 2] == 255 ||
grayValues[i * bmpData.Stride + j - 1] == 255 ||
grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[i * bmpData.Stride + j + 1] == 255 ||
grayValues[i * bmpData.Stride + j + 2] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j - 2] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j + 1] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j + 2] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j - 2] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j + 1] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j + 2] == 255)
tempArray[i * bmpData.Stride + j] = 255;
}
}
break;
default:
break;
}
grayValues = (byte[])tempArray.Clone();
Marshal.Copy(grayValues, 0, ptr, bytes);
inputBitmap.UnlockBits(bmpData);
return inputBitmap;
}
catch
{
return null;
}
}
#endregion
#region 图像开运算
/// <summary>
/// 图像开运算
/// </summary>
/// <param name="mode">结构元素
/// 0:3位水平方向的结构元素
/// 1:5位水平方向的结构元素
/// 2:3位垂直方向的结构元素
/// 3:5位垂直方向的结构元素
/// 4:3位十字状结构元素
/// 5:5位十字状结构元素
/// 6:3位方形结构元素
/// 7:5位方形结构元素
/// </param>
/// <param name="inputBitmap">需要开运算的图像</param>
/// <returns>开运算后的图像</returns>
public static Bitmap ImageOpening(int mode, Bitmap inputBitmap)
{
try
{
//先以255作为阈值分割点
inputBitmap = ToGray(inputBitmap);
inputBitmap = ToBinary(255, inputBitmap);
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData = inputBitmap.LockBits(rect,
System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
IntPtr ptr = bmpData.Scan0;
int bytes = bmpData.Stride * bmpData.Height;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
byte[] temp1Array = new byte[bytes];
byte[] tempArray = new byte[bytes];
for (int i = 0; i < bytes; i++)
{
tempArray[i] = temp1Array[i] = 0;
}
switch (mode)
{
case 0:
//3位水平结构元素
//腐蚀运算
for (int i = 0; i < bmpData.Height; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 &&
grayValues[i * bmpData.Stride + j + 1] == 255 &&
grayValues[i * bmpData.Stride + j - 1] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//膨胀运算
for (int i = 0; i < bmpData.Stride; i++)
{
for (int j = 1; j < bmpData.Stride - 1; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 ||
temp1Array[i * bmpData.Stride + j + 1] == 255 ||
temp1Array[i * bmpData.Stride + j - 1] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 1:
//5位水平结构元素
//腐蚀运算
for (int i = 0; i < bmpData.Height; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 &&
grayValues[i * bmpData.Stride + j + 1] == 255 &&
grayValues[i * bmpData.Stride + j - 1] == 255 &&
grayValues[i * bmpData.Stride + j + 2] == 255 &&
grayValues[i * bmpData.Stride + j - 2] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//膨胀运算
for (int i = 0; i < bmpData.Height; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 ||
temp1Array[i * bmpData.Stride + j + 1] == 255 ||
temp1Array[i * bmpData.Stride + j - 1] == 255 ||
temp1Array[i * bmpData.Stride + j + 2] == 255 ||
temp1Array[i * bmpData.Stride + j - 2] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 2:
//3位垂直结构元素
//腐蚀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//膨胀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 3:
//5位垂直结构元素
//腐蚀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
grayValues[(i - 2) * bmpData.Stride + j] == 255 &&
grayValues[(i + 2) * bmpData.Stride + j] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//膨胀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j] == 255 ||
temp1Array[(i - 2) * bmpData.Stride + j] == 255 ||
temp1Array[(i + 2) * bmpData.Stride + j] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 4:
//3位十字形结构元素
//腐蚀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
grayValues[i * bmpData.Stride + j + 1] == 255 &&
grayValues[i * bmpData.Stride + j - 1] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//膨胀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j] == 255 ||
temp1Array[i * bmpData.Stride + j + 1] == 255 ||
temp1Array[i * bmpData.Stride + j - 1] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 5:
//5位十字形结构元素
//腐蚀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
grayValues[(i - 2) * bmpData.Stride + j] == 255 &&
grayValues[(i + 2) * bmpData.Stride + j] == 255 &&
grayValues[i * bmpData.Stride + j + 1] == 255 &&
grayValues[i * bmpData.Stride + j - 1] == 255 &&
grayValues[i * bmpData.Stride + j + 2] == 255 &&
grayValues[i * bmpData.Stride + j - 2] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//膨胀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j] == 255 ||
temp1Array[(i - 2) * bmpData.Stride + j] == 255 ||
temp1Array[(i + 2) * bmpData.Stride + j] == 255 ||
temp1Array[i * bmpData.Stride + j + 1] == 255 ||
temp1Array[i * bmpData.Stride + j - 1] == 255 ||
temp1Array[i * bmpData.Stride + j + 2] == 255 ||
temp1Array[i * bmpData.Stride + j - 2] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 6:
//3位方形结构元素
//腐蚀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
grayValues[i * bmpData.Stride + j + 1] == 255 &&
grayValues[i * bmpData.Stride + j - 1] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j + 1] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//膨胀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j] == 255 ||
temp1Array[i * bmpData.Stride + j + 1] == 255 ||
temp1Array[i * bmpData.Stride + j - 1] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j - 1] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j - 1] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j + 1] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j + 1] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 7:
//5位方形结构元素
//腐蚀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (grayValues[(i - 2) * bmpData.Stride + j - 2] == 255 &&
grayValues[(i - 2) * bmpData.Stride + j - 1] == 255 &&
grayValues[(i - 2) * bmpData.Stride + j] == 255 &&
grayValues[(i - 2) * bmpData.Stride + j + 1] == 255 &&
grayValues[(i - 2) * bmpData.Stride + j + 2] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j - 2] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 &&
grayValues[(i - 1) * bmpData.Stride + j + 2] == 255 &&
grayValues[i * bmpData.Stride + j - 2] == 255 &&
grayValues[i * bmpData.Stride + j - 1] == 255 &&
grayValues[i * bmpData.Stride + j] == 255 &&
grayValues[i * bmpData.Stride + j + 1] == 255 &&
grayValues[i * bmpData.Stride + j + 2] == 255 &&
grayValues[(i + 2) * bmpData.Stride + j - 2] == 255 &&
grayValues[(i + 2) * bmpData.Stride + j - 1] == 255 &&
grayValues[(i + 2) * bmpData.Stride + j] == 255 &&
grayValues[(i + 2) * bmpData.Stride + j + 1] == 255 &&
grayValues[(i + 2) * bmpData.Stride + j + 2] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j - 2] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j + 1] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j + 2] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//膨胀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (temp1Array[(i - 2) * bmpData.Stride + j - 2] == 255 ||
temp1Array[(i - 2) * bmpData.Stride + j - 1] == 255 ||
temp1Array[(i - 2) * bmpData.Stride + j] == 255 ||
temp1Array[(i - 2) * bmpData.Stride + j + 1] == 255 ||
temp1Array[(i - 2) * bmpData.Stride + j + 2] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j - 2] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j - 1] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j + 1] == 255 ||
temp1Array[(i - 1) * bmpData.Stride + j + 2] == 255 ||
temp1Array[i * bmpData.Stride + j - 2] == 255 ||
temp1Array[i * bmpData.Stride + j - 1] == 255 ||
temp1Array[i * bmpData.Stride + j] == 255 ||
temp1Array[i * bmpData.Stride + j + 1] == 255 ||
temp1Array[i * bmpData.Stride + j + 2] == 255 ||
temp1Array[(i + 2) * bmpData.Stride + j - 2] == 255 ||
temp1Array[(i + 2) * bmpData.Stride + j - 1] == 255 ||
temp1Array[(i + 2) * bmpData.Stride + j] == 255 ||
temp1Array[(i + 2) * bmpData.Stride + j + 1] == 25 ||
temp1Array[(i + 2) * bmpData.Stride + j + 2] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j - 2] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j - 1] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j + 1] == 255 ||
temp1Array[(i + 1) * bmpData.Stride + j + 2] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
default:
break;
}
grayValues = (byte[])tempArray.Clone();
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
inputBitmap.UnlockBits(bmpData);
return inputBitmap;
}
catch
{
return null;
}
}
#endregion
#region 图像闭运算
/// <summary>
/// 图像闭运算
/// </summary>
/// <param name="mode">结构元素
/// 0:3位水平方向的结构元素
/// 1:5位水平方向的结构元素
/// 2:3位垂直方向的结构元素
/// 3:5位垂直方向的结构元素
/// 4:3位十字状结构元素
/// 5:5位十字状结构元素
/// 6:3位方形结构元素
/// 7:5位方形结构元素
/// </param>
/// <param name="inputBitmap">需要闭运算的图像</param>
/// <returns>闭运算后的结果</returns>
public static Bitmap ImageClosing(int mode, Bitmap inputBitmap)
{
try
{
//先以255作为阈值分割点
inputBitmap = ToGray(inputBitmap);
inputBitmap = ToBinary(255, inputBitmap);
Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData = inputBitmap.LockBits(rect,
System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
IntPtr ptr = bmpData.Scan0;
int bytes = bmpData.Stride * bmpData.Height;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
byte[] temp1Array = new byte[bytes];
byte[] tempArray = new byte[bytes];
for (int i = 0; i < bytes; i++)
{
tempArray[i] = temp1Array[i] = 0;
}
switch (mode)
{
case 0:
//3位水平结构元素
//膨胀运算
for (int i = 0; i < bmpData.Height; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[i * bmpData.Stride + j + 1] == 255 ||
grayValues[i * bmpData.Stride + j - 1] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//腐蚀运算
for (int i = 0; i < bmpData.Stride; i++)
{
for (int j = 1; j < bmpData.Stride - 1; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 &&
temp1Array[i * bmpData.Stride + j + 1] == 255 &&
temp1Array[i * bmpData.Stride + j - 1] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 1:
//5位水平结构元素
//膨胀运算
for (int i = 0; i < bmpData.Height; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[i * bmpData.Stride + j + 1] == 255 ||
grayValues[i * bmpData.Stride + j - 1] == 255 ||
grayValues[i * bmpData.Stride + j + 2] == 255 ||
grayValues[i * bmpData.Stride + j - 2] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//腐蚀运算
for (int i = 0; i < bmpData.Height; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 &&
temp1Array[i * bmpData.Stride + j + 1] == 255 &&
temp1Array[i * bmpData.Stride + j - 1] == 255 &&
temp1Array[i * bmpData.Stride + j + 2] == 255 &&
temp1Array[i * bmpData.Stride + j - 2] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 2:
//3位垂直结构元素
//膨胀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//腐蚀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 3:
//5位垂直结构元素
//膨胀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//腐蚀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 0; j < bmpData.Width; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j] == 255 &&
temp1Array[(i - 2) * bmpData.Stride + j] == 255 &&
temp1Array[(i + 2) * bmpData.Stride + j] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 4:
//3位十字形结构元素
//膨胀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
grayValues[i * bmpData.Stride + j + 1] == 255 ||
grayValues[i * bmpData.Stride + j - 1] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//腐蚀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j] == 255 &&
temp1Array[i * bmpData.Stride + j + 1] == 255 &&
temp1Array[i * bmpData.Stride + j - 1] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 5:
//5位十字形结构元素
//膨胀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j] == 255 ||
grayValues[i * bmpData.Stride + j + 1] == 255 ||
grayValues[i * bmpData.Stride + j - 1] == 255 ||
grayValues[i * bmpData.Stride + j + 2] == 255 ||
grayValues[i * bmpData.Stride + j - 2] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//腐蚀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j] == 255 &&
temp1Array[(i - 2) * bmpData.Stride + j] == 255 &&
temp1Array[(i + 2) * bmpData.Stride + j] == 255 &&
temp1Array[i * bmpData.Stride + j + 1] == 255 &&
temp1Array[i * bmpData.Stride + j - 1] == 255 &&
temp1Array[i * bmpData.Stride + j + 2] == 255 &&
temp1Array[i * bmpData.Stride + j - 2] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 6:
//3位方形结构元素
//膨胀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
grayValues[i * bmpData.Stride + j + 1] == 255 ||
grayValues[i * bmpData.Stride + j - 1] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j + 1] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//腐蚀运算
for (int i = 1; i < bmpData.Height - 1; i++)
{
for (int j = 1; j < bmpData.Width - 1; j++)
{
if (temp1Array[i * bmpData.Stride + j] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j] == 255 &&
temp1Array[i * bmpData.Stride + j + 1] == 255 &&
temp1Array[i * bmpData.Stride + j - 1] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j - 1] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j - 1] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j + 1] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j + 1] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
case 7:
//5位方形结构元素
//膨胀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (grayValues[(i - 2) * bmpData.Stride + j - 2] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j + 1] == 255 ||
grayValues[(i - 2) * bmpData.Stride + j + 2] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j - 2] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 ||
grayValues[(i - 1) * bmpData.Stride + j + 2] == 255 ||
grayValues[i * bmpData.Stride + j - 2] == 255 ||
grayValues[i * bmpData.Stride + j - 1] == 255 ||
grayValues[i * bmpData.Stride + j] == 255 ||
grayValues[i * bmpData.Stride + j + 1] == 255 ||
grayValues[i * bmpData.Stride + j + 2] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j - 2] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j + 1] == 255 ||
grayValues[(i + 2) * bmpData.Stride + j + 2] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j - 2] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
grayValues[(i + 1) * bmpData.Stride + j + 1] == 255 ||
grayValues[(i + 1) * bmpData.Stride + j + 2] == 255)
{
temp1Array[i * bmpData.Stride + j] = 255;
}
}
}
//腐蚀运算
for (int i = 2; i < bmpData.Height - 2; i++)
{
for (int j = 2; j < bmpData.Width - 2; j++)
{
if (temp1Array[(i - 2) * bmpData.Stride + j - 2] == 255 &&
temp1Array[(i - 2) * bmpData.Stride + j - 1] == 255 &&
temp1Array[(i - 2) * bmpData.Stride + j] == 255 &&
temp1Array[(i - 2) * bmpData.Stride + j + 1] == 255 &&
temp1Array[(i - 2) * bmpData.Stride + j + 2] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j - 2] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j - 1] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j + 1] == 255 &&
temp1Array[(i - 1) * bmpData.Stride + j + 2] == 255 &&
temp1Array[i * bmpData.Stride + j - 2] == 255 &&
temp1Array[i * bmpData.Stride + j - 1] == 255 &&
temp1Array[i * bmpData.Stride + j] == 255 &&
temp1Array[i * bmpData.Stride + j + 1] == 255 &&
temp1Array[i * bmpData.Stride + j + 2] == 255 &&
temp1Array[(i + 2) * bmpData.Stride + j - 2] == 255 &&
temp1Array[(i + 2) * bmpData.Stride + j - 1] == 255 &&
temp1Array[(i + 2) * bmpData.Stride + j] == 255 &&
temp1Array[(i + 2) * bmpData.Stride + j + 1] == 25 &&
temp1Array[(i + 2) * bmpData.Stride + j + 2] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j - 2] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j - 1] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j + 1] == 255 &&
temp1Array[(i + 1) * bmpData.Stride + j + 2] == 255)
{
tempArray[i * bmpData.Stride + j] = 255;
}
}
}
break;
default:
break;
}
grayValues = (byte[])tempArray.Clone();
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
inputBitmap.UnlockBits(bmpData);
return inputBitmap;
}
catch
{
return null;
}
}
#endregion
}