影象開閉運算
二值影象腐蝕函式
[演算法說明]
二值影象腐蝕操作屬於影象形態學的範疇,形態學運算是隻針對二值影象進行,並依據數學形態學(Mathermatical Morphogy)集合論方法發展起來的數字影象處理方法,它主要包括腐蝕,膨脹,開,閉,擊中,擊不中等。
影象形態學運算,要使用結構元素,所謂結構元素是指具有某種確定形狀的基本結構,它的選擇一般要求其具有旋轉不變性或者映象不變性,即:結構元素的原點在其幾何中心處,周圍畫素關於原點對稱。
在這裡我們選取如下的結構元素:
我們假設結構元素為S,則腐蝕演算法如下:
其中,F為二值影象原圖,X為結構元素原點所在的二值影象中的連通域。
假設F中目標畫素為255(白色),非目標為0(黑色),當結構元素S原點移動到點(x,y)時,如果S中所有點均包含在X中(X中對應在S中所有點的位置均為255),則在腐蝕後的二值影象中,對應於S原點的位置為255(白色),否則為0(黑色)。
用通俗的話來說就是:用結構元素作為模板在原始二值影象種平滑一遍,掃描影象的每一個畫素,用結構元素中的每一個元素與其覆蓋的二值影象做“與”操作(假設結構元素都為1),如果結果都為1,則二值影象中對應結構元素原點位置的畫素值為1,否則為0。[函式程式碼]
///
/// Corrosion process.
///
///
///
public static WriteableBitmap CorrosionProcess(WriteableBitmap src)////21影象腐蝕運算
{
if (src != null)
{
int w = src.PixelWidth;
int h = src.PixelHeight;
WriteableBitmap
byte[] temp = src.PixelBuffer.ToArray();
byte[] tempMask = (byte[])temp.Clone();
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w ; i ++)
{
if (i == 0 || i == w - 1 || j == 0 || j == h - 1)
{
temp[i * 4 + j * w * 4] = (byte)255;
temp[i * 4 + 1 + j * w * 4] = (byte)255;
temp[i * 4 + 2 + j * w * 4] = (byte)255;
}
else
{
if (tempMask[i * 4 - 4 + j * w * 4] == 255 && tempMask[i * 4 + j * w * 4] == 255 && tempMask[i * 4 + 4 + j * w * 4] == 255
&& tempMask[i * 4 + (j - 1) * w * 4] == 255 && tempMask[i * 4 + (j + 1) * w * 4] == 255)
{
temp[i * 4 + j * w * 4] = (byte)255;
temp[i * 4 + 1 + j * w * 4] = (byte)255;
temp[i * 4 + 2 + j * w * 4] = (byte)255;
}
else
{
temp[i * 4 + j * w * 4] = 0;
temp[i * 4 + 1 + j * w * 4] = 0;
temp[i * 4 + 2 + j * w * 4] = 0;
}
}
}
}
Stream sTemp = corrosionImage.PixelBuffer.AsStream();
sTemp.Seek(0, SeekOrigin.Begin);
sTemp.Write(temp, 0, w * 4 * h);
return corrosionImage;
}
else
{
return null;
}
}
[影象效果]
Fig.1原圖 Fig.2效果圖
二值影象膨脹函式
[演算法說明]
膨脹演算法也是屬於形態學演算法的範疇,前一節已經簡單介紹了形態學,這裡不再累贅。
我們這裡介紹的膨脹演算法依舊採用上一節腐蝕中的結構元素S,則演算法過程如下:
用通俗的話講就是,用結構元素作為模板在原始二值影象種平滑一遍,掃描影象的每一個畫素,用結構元素中的每一個元素與其覆蓋的二值影象做“或”操作(假設結構元素都為1),如果結果為1,則二值影象中對應結構元素原點位置的畫素值為1,否則為0。
[函式程式碼]
///
///Dilation process.
///
///The source image(It should be the binary image).
///
public static WriteableBitmap DilationProcess(WriteableBitmap src)////22影象膨脹運算
{
if (src != null)
{
int w = src.PixelWidth;
int h = src.PixelHeight;
WriteableBitmap dilationImage = new WriteableBitmap(w, h);
byte[] temp = src.PixelBuffer.ToArray();
byte[] tempMask = (byte[])temp.Clone();
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w; i++)
{
if (i == 0 || i == w - 1 || j == 0 || j == h - 1)
{
temp[i * 4 + j * w * 4] = (byte)255;
temp[i * 4 + 1 + j * w * 4] = (byte)255;
temp[i * 4 + 2 + j * w * 4] = (byte)255;
}
else
{
if (tempMask[i * 4 - 4 + j * w * 4] == 255 || tempMask[i * 4 + j * w * 4] == 255 || tempMask[i * 4 + 4 + j * w * 4] == 255
|| tempMask[i * 4 + (j - 1) * w * 4] == 255 || tempMask[i * 4 + (j + 1) * w * 4] == 255)
{
temp[i * 4 + j * w * 4] = (byte)255;
temp[i * 4 + 1 + j * w * 4] = (byte)255;
temp[i * 4 + 2 + j * w * 4] = (byte)255;
}
else
{
temp[i * 4 + j * w * 4] = 0;
temp[i * 4 + 1 + j * w * 4] = 0;
temp[i * 4 + 2 + j * w * 4] = 0;
}
}
}
}
Stream sTemp = dilationImage.PixelBuffer.AsStream();
sTemp.Seek(0, SeekOrigin.Begin);
sTemp.Write(temp, 0, w * 4 * h);
return dilationImage;
}
else
{
return null;
}
}
[影象效果]
Fig.1原圖 Fig.2效果圖
二值影象開運算函式
[演算法說明]
開運算就是先進性一次腐蝕後進行一次膨脹。演算法過程如公式2-(27)。
[函式程式碼]
///
/// Open operate process.
///
///The source image(It should be the binary image).
///
public static WriteableBitmap OpenOperateProcess(WriteableBitmap src)////23影象開運算
{
if (src != null)
{
WriteableBitmap temp = DilationProcess(CorrosionProcess(src));
return temp;
}
else
{
return null;
}
}
[影象效果]
Fig.1原圖 Fig.2效果圖
二值影象閉運算函式
[演算法說明]
閉運算就是先進性一次膨脹後進行一次腐蝕。演算法過程如公式2-(28)。
[函式程式碼]
///
/// Close operate process.
///
///The source image(It should be the binary image).
///
public static WriteableBitmap CloseOperateProcess(WriteableBitmap src)////24影象閉運算
{
if (src != null)
{
WriteableBitmap temp = CorrosionProcess(DilationProcess(src));
return temp;
}
else
{
return null;
}
}
[影象效果]
Fig.1原圖 Fig.2效果圖