基于c#圖像灰度化、灰度反轉(zhuǎn)、二值化的實(shí)現(xiàn)方法詳解
更新時(shí)間:2013年05月20日 10:02:03 作者:
本篇文章是對(duì)c#圖像灰度化、灰度反轉(zhuǎn)、二值化的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
圖像灰度化:
將彩色圖像轉(zhuǎn)化成為灰度圖像的過程成為圖像的灰度化處理。彩色圖像中的每個(gè)像素的顏色有R、G、B三個(gè)分量決定,而每個(gè)分量有255中值可取,這樣一個(gè)像素點(diǎn)可以有1600多萬(255*255*255)的顏色的變化范圍。而灰度圖像是R、G、B三個(gè)分量相同的一種特殊的彩色圖像,其一個(gè)像素點(diǎn)的變化范圍為255種,所以在數(shù)字圖像處理種一般先將各種格式的圖像轉(zhuǎn)變成灰度圖像以使后續(xù)的圖像的計(jì)算量變得少一些?;叶葓D像的描述與彩色圖像一樣仍然反映了整幅圖像的整體和局部的色度和亮度等級(jí)的分布和特征。圖像的灰度化處理可用兩種方法來實(shí)現(xiàn)。
第一種方法使求出每個(gè)像素點(diǎn)的R、G、B三個(gè)分量的平均值,然后將這個(gè)平均值賦予給這個(gè)像素的三個(gè)分量。
第二種方法是根據(jù)YUV的顏色空間中,Y的分量的物理意義是點(diǎn)的亮度,由該值反映亮度等級(jí),根據(jù)RGB和YUV顏色空間的變化關(guān)系可建立亮度Y與R、G、B三個(gè)顏色分量的對(duì)應(yīng):Y=0.3R+0.59G+0.11B,以這個(gè)亮度值表達(dá)圖像的灰度值。
/// <summary>
/// 圖像灰度化
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
public static Bitmap ToGray(Bitmap bmp)
{
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
//獲取該點(diǎn)的像素的RGB的顏色
Color color = bmp.GetPixel(i, j);
//利用公式計(jì)算灰度值
int gray = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
Color newColor = Color.FromArgb(gray, gray, gray);
bmp.SetPixel(i, j, newColor);
}
}
return bmp;
}
灰度反轉(zhuǎn):
把每個(gè)像素點(diǎn)的R、G、B三個(gè)分量的值0的設(shè)為255,255的設(shè)為0。
/// <summary>
/// 圖像灰度反轉(zhuǎn)
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
public static Bitmap GrayReverse(Bitmap bmp)
{
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
//獲取該點(diǎn)的像素的RGB的顏色
Color color = bmp.GetPixel(i, j);
Color newColor = Color.FromArgb(255 - color.R, 255 - color.G, 255 - color.B);
bmp.SetPixel(i, j, newColor);
}
}
return bmp;
}
灰度圖像二值化:
在進(jìn)行了灰度化處理之后,圖像中的每個(gè)象素只有一個(gè)值,那就是象素的灰度值。它的大小決定了象素的亮暗程度。為了更加便利的開展下面的圖像處理操作,還需要對(duì)已經(jīng)得到的灰度圖像做一個(gè)二值化處理。圖像的二值化就是把圖像中的象素根據(jù)一定的標(biāo)準(zhǔn)分化成兩種顏色。在系統(tǒng)中是根據(jù)象素的灰度值處理成黑白兩種顏色。和灰度化相似的,圖像的二值化也有很多成熟的算法。它可以采用自適應(yīng)閥值法,也可以采用給定閥值法。
/// <summary>
/// 圖像二值化1:取圖片的平均灰度作為閾值,低于該值的全都為0,高于該值的全都為255
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
public static Bitmap ConvertTo1Bpp1(Bitmap bmp)
{
int average = 0;
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
Color color = bmp.GetPixel(i, j);
average += color.B;
}
}
average = (int)average / (bmp.Width * bmp.Height);
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
//獲取該點(diǎn)的像素的RGB的顏色
Color color = bmp.GetPixel(i, j);
int value = 255 - color.B;
Color newColor = value > average ? Color.FromArgb(0, 0, 0): Color.FromArgb(255,
255, 255);
bmp.SetPixel(i, j, newColor);
}
}
return bmp;
}
/// <summary>
/// 圖像二值化2
/// </summary>
/// <param name="img"></param>
/// <returns></returns>
public static Bitmap ConvertTo1Bpp2(Bitmap img)
{
int w = img.Width;
int h = img.Height;
Bitmap bmp = new Bitmap(w, h, PixelFormat.Format1bppIndexed);
BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite,
PixelFormat.Format1bppIndexed);
for (int y = 0; y < h; y++)
{
byte[] scan = new byte[(w + 7) / 8];
for (int x = 0; x < w; x++)
{
Color c = img.GetPixel(x, y);
if (c.GetBrightness() >= 0.5) scan[x / 8] |= (byte)(0x80 >> (x % 8));
}
Marshal.Copy(scan, 0, (IntPtr)((int)data.Scan0 + data.Stride * y), scan.Length);
}
return bmp;
}
將彩色圖像轉(zhuǎn)化成為灰度圖像的過程成為圖像的灰度化處理。彩色圖像中的每個(gè)像素的顏色有R、G、B三個(gè)分量決定,而每個(gè)分量有255中值可取,這樣一個(gè)像素點(diǎn)可以有1600多萬(255*255*255)的顏色的變化范圍。而灰度圖像是R、G、B三個(gè)分量相同的一種特殊的彩色圖像,其一個(gè)像素點(diǎn)的變化范圍為255種,所以在數(shù)字圖像處理種一般先將各種格式的圖像轉(zhuǎn)變成灰度圖像以使后續(xù)的圖像的計(jì)算量變得少一些?;叶葓D像的描述與彩色圖像一樣仍然反映了整幅圖像的整體和局部的色度和亮度等級(jí)的分布和特征。圖像的灰度化處理可用兩種方法來實(shí)現(xiàn)。
第一種方法使求出每個(gè)像素點(diǎn)的R、G、B三個(gè)分量的平均值,然后將這個(gè)平均值賦予給這個(gè)像素的三個(gè)分量。
第二種方法是根據(jù)YUV的顏色空間中,Y的分量的物理意義是點(diǎn)的亮度,由該值反映亮度等級(jí),根據(jù)RGB和YUV顏色空間的變化關(guān)系可建立亮度Y與R、G、B三個(gè)顏色分量的對(duì)應(yīng):Y=0.3R+0.59G+0.11B,以這個(gè)亮度值表達(dá)圖像的灰度值。
復(fù)制代碼 代碼如下:
/// <summary>
/// 圖像灰度化
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
public static Bitmap ToGray(Bitmap bmp)
{
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
//獲取該點(diǎn)的像素的RGB的顏色
Color color = bmp.GetPixel(i, j);
//利用公式計(jì)算灰度值
int gray = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
Color newColor = Color.FromArgb(gray, gray, gray);
bmp.SetPixel(i, j, newColor);
}
}
return bmp;
}
灰度反轉(zhuǎn):
把每個(gè)像素點(diǎn)的R、G、B三個(gè)分量的值0的設(shè)為255,255的設(shè)為0。
復(fù)制代碼 代碼如下:
/// <summary>
/// 圖像灰度反轉(zhuǎn)
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
public static Bitmap GrayReverse(Bitmap bmp)
{
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
//獲取該點(diǎn)的像素的RGB的顏色
Color color = bmp.GetPixel(i, j);
Color newColor = Color.FromArgb(255 - color.R, 255 - color.G, 255 - color.B);
bmp.SetPixel(i, j, newColor);
}
}
return bmp;
}
灰度圖像二值化:
在進(jìn)行了灰度化處理之后,圖像中的每個(gè)象素只有一個(gè)值,那就是象素的灰度值。它的大小決定了象素的亮暗程度。為了更加便利的開展下面的圖像處理操作,還需要對(duì)已經(jīng)得到的灰度圖像做一個(gè)二值化處理。圖像的二值化就是把圖像中的象素根據(jù)一定的標(biāo)準(zhǔn)分化成兩種顏色。在系統(tǒng)中是根據(jù)象素的灰度值處理成黑白兩種顏色。和灰度化相似的,圖像的二值化也有很多成熟的算法。它可以采用自適應(yīng)閥值法,也可以采用給定閥值法。
復(fù)制代碼 代碼如下:
/// <summary>
/// 圖像二值化1:取圖片的平均灰度作為閾值,低于該值的全都為0,高于該值的全都為255
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
public static Bitmap ConvertTo1Bpp1(Bitmap bmp)
{
int average = 0;
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
Color color = bmp.GetPixel(i, j);
average += color.B;
}
}
average = (int)average / (bmp.Width * bmp.Height);
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
//獲取該點(diǎn)的像素的RGB的顏色
Color color = bmp.GetPixel(i, j);
int value = 255 - color.B;
Color newColor = value > average ? Color.FromArgb(0, 0, 0): Color.FromArgb(255,
255, 255);
bmp.SetPixel(i, j, newColor);
}
}
return bmp;
}
/// <summary>
/// 圖像二值化2
/// </summary>
/// <param name="img"></param>
/// <returns></returns>
public static Bitmap ConvertTo1Bpp2(Bitmap img)
{
int w = img.Width;
int h = img.Height;
Bitmap bmp = new Bitmap(w, h, PixelFormat.Format1bppIndexed);
BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite,
PixelFormat.Format1bppIndexed);
for (int y = 0; y < h; y++)
{
byte[] scan = new byte[(w + 7) / 8];
for (int x = 0; x < w; x++)
{
Color c = img.GetPixel(x, y);
if (c.GetBrightness() >= 0.5) scan[x / 8] |= (byte)(0x80 >> (x % 8));
}
Marshal.Copy(scan, 0, (IntPtr)((int)data.Scan0 + data.Stride * y), scan.Length);
}
return bmp;
}
相關(guān)文章
C#實(shí)現(xiàn)主窗體最小化后出現(xiàn)懸浮框及雙擊懸浮框恢復(fù)原窗體的方法
這篇文章主要介紹了C#實(shí)現(xiàn)主窗體最小化后出現(xiàn)懸浮框及雙擊懸浮框恢復(fù)原窗體的方法,涉及C#窗體及鼠標(biāo)事件響應(yīng)的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08C#字符串如何提取數(shù)值(帶小數(shù)點(diǎn))
這篇文章主要介紹了C#字符串如何提取數(shù)值問題(帶小數(shù)點(diǎn)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05C#關(guān)于System.Collections空間詳解
這篇文章主要介紹了C#關(guān)于System.Collections空間,需要的朋友可以參考下2014-07-07Winform中Treeview實(shí)現(xiàn)按需加載的方法
這篇文章主要介紹了Winform中Treeview實(shí)現(xiàn)按需加載的方法,針對(duì)大數(shù)據(jù)量的情況下非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-10-10C# BeginInvoke實(shí)現(xiàn)異步編程方式
這篇文章主要介紹了C# BeginInvoke實(shí)現(xiàn)異步編程方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01.net中前臺(tái)javascript與后臺(tái)c#函數(shù)相互調(diào)用問題
.net中前臺(tái)javascript與后臺(tái)c#函數(shù)相互調(diào)用問題...2007-12-12