使用 C# 实现膨胀算法






4.17/5 (9投票s)
此代码有助于使用 C# 实现膨胀算法。

引言
我是一名 C# 开发者,我的领域是图像处理。在 C# 中,执行膨胀操作非常困难。膨胀算法是一种数学形态学,在医学成像项目中是必需的。这篇文章将帮助那些尝试膨胀图像的人。代码中使用了指针,因此速度更快。
什么是膨胀?
膨胀是数学形态学领域中的两个基本算子之一。膨胀是对图像进行单次处理。在通过图像的过程中,结构元素应用于图像的每个像素,使得结构元素的原点应用于该特定像素。在这种情况下,输出图像的相应像素包含其周围像素的最大值。在这种情况下,只有结构元素包含的像素才相互比较。
Using the Code
此函数接受源位图并返回膨胀后的位图。GetPixel
和 SetPixel
函数存在一些缺点,因此我们使用指针。我们使用指针访问和修改像素值。下一个示例利用 C# 中的“unsafe”块。在 unsafe 块内部,我们可以访问 C# 中的指针。结论是,unsafe 块中的指针比 GetPixel
和 SetPixel
函数更快。
public Bitmap Dilate(Bitmap SrcImage)
{
// Create Destination bitmap.
Bitmap tempbmp = new Bitmap(SrcImage.Width,SrcImage.Height);
// Take source bitmap data.
BitmapData SrcData = SrcImage.LockBits(new Rectangle(0, 0,
SrcImage.Width, SrcImage.Height), ImageLockMode.ReadOnly,
PixelFormat.Format24bppRgb);
// Take destination bitmap data.
BitmapData DestData = tempbmp.LockBits(new Rectangle(0, 0, tempbmp.Width,
tempbmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
// Element array to used to dilate.
byte[,] sElement = new byte[5, 5] {
{0,0,1,0,0},
{0,1,1,1,0},
{1,1,1,1,1},
{0,1,1,1,0},
{0,0,1,0,0}
};
// Element array size.
int size = 5;
byte max, clrValue;
int radius = size / 2;
int ir, jr;
unsafe
{
// Loop for Columns.
for (int colm = radius; colm < DestData.Height - radius; colm++)
{
// Initialise pointers to at row start.
byte* ptr = (byte*)SrcData.Scan0 + (colm * SrcData.Stride);
byte* dstPtr = (byte*)DestData.Scan0 + (colm * SrcData.Stride);
// Loop for Row item.
for (int row = radius; row < DestData.Width - radius; row++)
{
max = 0;
clrValue = 0;
// Loops for element array.
for (int eleColm = 0; eleColm < 5; eleColm++)
{
ir = eleColm - radius;
byte* tempPtr = (byte*)SrcData.Scan0 +
((colm + ir) * SrcData.Stride);
for (int eleRow = 0; eleRow < 5; eleRow++)
{
jr = eleRow - radius;
// Get neightbour element color value.
clrValue = (byte)((tempPtr[row * 3 + jr] +
tempPtr[row * 3 + jr + 1] + tempPtr[row * 3 + jr + 2]) / 3);
if (max < clrValue)
{
if (sElement[eleColm, eleRow] != 0)
max = clrValue;
}
}
}
dstPtr[0] = dstPtr[1] = dstPtr[2] = max;
ptr += 3;
dstPtr += 3;
}
}
}
// Dispose all Bitmap data.
SrcImage.UnlockBits(SrcData);
tempbmp.UnlockBits(DestData);
// return dilated bitmap.
return tempbmp;
}
在这个函数中,我们将图像结构的起始和结束地址计算出来,认为它是一个一维线性数组。我们从起始地址到结束地址递增指针,并获取中间的值。计算周围像素的最大值,并将最大像素值赋给膨胀图像指针。
关注点
像素与其相邻像素的膨胀效果非常好。该算法还帮助我使用 C# 实现腐蚀算法。
历史
- 2009 年 3 月 4 日:初始发布