using System.Collections.Generic;
using System.Drawing;
namespace WindowsFormsApplication1
{
public class ImageProcess
{
Image m_Source;
public ImageProcess(Image img)
{
m_Source = img;
}
public Image GetSingleColor()
{
Bitmap rT = new Bitmap(m_Source.Width, m_Source.Height);
Bitmap old = (Bitmap)m_Source;
Color pixel;
int Width = old.Width,Height = old.Height,r,g,b,Result;
for (int x = 0; x < Width; x++)
for (int y = 0; y < Height; y++)
{
pixel = old.GetPixel(x, y);
r = pixel.R;
g = pixel.G;
b = pixel.B;
//加權平均值法
Result = ((int)(0.7 * r) + (int)(0.2 * g) + (int)(0.1 * b));
////最大值法
//Result = r > g ? r : g;
//Result = Result > b ? Result : b;
////平均值法
//Result = ((r + g + b) / 3);
rT.SetPixel(x, y, Color.FromArgb(Result, Result, Result));
}
return rT;
}
public Image GetPartCut(int left, int top, int width, int heigh)
{
Bitmap rT = new Bitmap(width, heigh);
using (Graphics g = Graphics.FromImage(rT))
{
g.DrawImage(m_Source, new Point(-left, -top));
}
return rT;
}
/// <summary>
/// 替換連通的顏色,一般用於替換背景色。
/// 低效函數,未優化
/// </summary>
public Image ReplaceColor(Point select,Color newColor,int CheckRange)
{
Bitmap rT = (Bitmap)m_Source;
byte[,] arr = new byte[rT.Width, rT.Height];
int nowX = select.X,nowY = select.Y;
Color targetColor = rT.GetPixel(nowX, nowY);
ResetmatrixPoint(nowX, nowY, arr, rT, newColor);
CheckPoint(nowX, nowY, arr, rT, newColor,targetColor, CheckRange);
return rT;
}
void ResetmatrixPoint(int x, int y, byte[,] state, Bitmap t, Color toSet)
{
t.SetPixel(x, y, toSet);
state[x, y] = 10;
//state 0-未計算 10-已改變顏色 20-需要檢測 30-已檢測並否定
int xsmall = x - 1;
int xbigger = x + 1;
int ysmall = y - 1;
int ybigger = y + 1;
if (xsmall > 0)
{
if (ysmall > 0 && state[xsmall, ysmall] == 0)
state[xsmall, ysmall] = 20;
if (state[xsmall, y] == 0)
state[xsmall, y] = 20;
if (ybigger < t.Height && state[xsmall, ybigger] == 0)
state[xsmall, ybigger] = 20;
}
if (ysmall > 0 && state[x, ysmall] == 0)
state[x, ysmall] = 20;
if (ybigger < t.Height && state[x, ybigger] == 0)
state[x, ybigger] = 20;
if (xbigger < t.Width)
{
if (ysmall > 0 && state[xbigger, ysmall] == 0)
state[xbigger, ysmall] = 20;
if (state[xbigger, y] == 0)
state[xbigger, y] = 20;
if (ybigger < t.Height && state[xbigger, ybigger] == 0)
state[xbigger, ybigger] = 20;
}
}
void CheckPoint(int x,int y,byte[,] state, Bitmap t, Color toSet,Color toCMP,int arrang)
{
int doCount = 1;
while (doCount > 0)
{
doCount = 0;
for (int i = 0; i < t.Width; i++)
for (int j = 0; j < t.Height; j++)
{
if (state[i, j] == 20)
{
Color cmpColor = t.GetPixel(i, j);
if (ColorComp(cmpColor, toCMP) < arrang)
{
doCount++;
int na =toSet.A + (cmpColor.A - toCMP.A);
int nb=toSet.B + (cmpColor.B - toCMP.B);
int ng =toSet.G + (cmpColor.G - toCMP.G);
na = Math.Min(na,255);
na = Math.Max(na,0);
nb = Math.Min(nb,255);
nb = Math.Max(nb,0);
ng = Math.Min(ng,255);
ng = Math.Max(ng,0);
cmpColor = Color.FromArgb(na, nb, ng);
ResetmatrixPoint(i, j, state, t, cmpColor);
}
else
state[i,j] = 30;
}
}
}
}
int ColorComp(Color a,Color b)
{
//通過HSV比較兩個子RGB的色差
//比較兩個RGB的色差
int absR = a.R - b.R;
int absG = a.G - b.G;
int absB = a.B - b.B;
int rT = (int)Math.Sqrt(absR * absR + absG * absG + absB * absB);
return rT;
}
/// <summary>
/// 該函數用於對圖像進行腐蝕運算。結構元素爲水平方向或垂直方向的三個點,
/// 中間點位於原點;或者由用戶自己定義3×3的結構元素。
/// </summary>
/// <param name="dgGrayValue">前後景臨界值</param>
/// <param name="nMode">腐蝕方式:0表示水平方向,1垂直方向,2自定義結構元素。</param>
/// <param name="structure"> 自定義的3×3結構元素</param>
public Image ErosionPic(int dgGrayValue, int nMode, bool[,] structure)
{
Bitmap m_New = (Bitmap)m_Source;
int lWidth = m_New.Width;
int lHeight = m_New.Height;
Bitmap newBmp = new Bitmap(lWidth, lHeight);
int i, j, n, m; //循環變量
if (nMode == 0)
{
//使用水平方向的結構元素進行腐蝕
// 由於使用1×3的結構元素,爲防止越界,所以不處理最左邊和最右邊
// 的兩列像素
for (j = 0; j < lHeight; j++)
{
for (i = 1; i < lWidth - 1; i++)
{
//目標圖像中的當前點先賦成黑色
newBmp.SetPixel(i, j, Color.Black);
//如果源圖像中當前點自身或者左右有一個點不是黑色,
//則將目標圖像中的當前點賦成白色
if (m_New.GetPixel(i - 1, j).R > dgGrayValue ||
m_New.GetPixel(i, j).R > dgGrayValue ||
m_New.GetPixel(i + 1, j).R > dgGrayValue)
newBmp.SetPixel(i, j, Color.White);
}
}
}
else if (nMode == 1)
{
//使用垂真方向的結構元素進行腐蝕
// 由於使用3×1的結構元素,爲防止越界,所以不處理最上邊和最下邊
// 的兩行像素
for (j = 1; j < lHeight - 1; j++)
{
for (i = 0; i < lWidth; i++)
{
//目標圖像中的當前點先賦成黑色
newBmp.SetPixel(i, j, Color.Black);
//如果源圖像中當前點自身或者左右有一個點不是黑色,
//則將目標圖像中的當前點賦成白色
if (m_New.GetPixel(i, j - 1).R > dgGrayValue ||
m_New.GetPixel(i, j).R > dgGrayValue ||
m_New.GetPixel(i, j + 1).R > dgGrayValue)
newBmp.SetPixel(i, j, Color.White);
}
}
}
else
{
if (structure.Length != 9) //檢查自定義結構
return null;
//使用自定義的結構元素進行腐蝕
// 由於使用3×3的結構元素,爲防止越界,所以不處理最左邊和最右邊
// 的兩列像素和最上邊和最下邊的兩列像素
for (j = 1; j < lHeight - 1; j++)
{
for (i = 1; i < lWidth - 1; i++)
{
//目標圖像中的當前點先賦成黑色
newBmp.SetPixel(i, j, Color.Black);
//如果原圖像中對應結構元素中爲黑色的那些點中有一個不是黑色,
//則將目標圖像中的當前點賦成白色
for (m = 0; m < 3; m++)
{
for (n = 0; n < 3; n++)
{
if (!structure[m, n])
continue;
if (m_New.GetPixel(i + m - 1, j + n - 1).R > dgGrayValue)
{
newBmp.SetPixel(i, j, Color.White);
break;
}
}
}
}
}
}
return newBmp;
}
/// <summary>
/// 該函數用於對圖像進行細化運算。要求目標圖像爲灰度圖像
/// </summary>
/// <param name="dgGrayValue"></param>
public Image ThiningPic(int dgGrayValue)
{
Bitmap m_New = (Bitmap)m_Source;
int lWidth = m_New.Width;
int lHeight = m_New.Height;
// Bitmap newBmp = new Bitmap(lWidth, lHeight);
bool bModified; //髒標記
int i, j, n, m; //循環變量
//四個條件
bool bCondition1;
bool bCondition2;
bool bCondition3;
bool bCondition4;
int nCount; //計數器
int[,] neighbour = new int[5, 5]; //5×5相鄰區域像素值
bModified = true;
while (bModified)
{
bModified = false;
//由於使用5×5的結構元素,爲防止越界,所以不處理外圍的幾行和幾列像素
for (j = 2; j < lHeight - 2; j++)
{
for (i = 2; i < lWidth - 2; i++)
{
bCondition1 = false;
bCondition2 = false;
bCondition3 = false;
bCondition4 = false;
if (m_New.GetPixel(i, j).R > dgGrayValue)
{
if(m_New.GetPixel(i, j).R<255)
m_New.SetPixel(i, j, Color.White);
continue;
}
//獲得當前點相鄰的5×5區域內像素值,白色用0代表,黑色用1代表
for (m = 0; m < 5; m++)
{
for (n = 0; n < 5; n++)
{
neighbour[m, n] = m_New.GetPixel(i + m - 2, j + n - 2).R < dgGrayValue ? 1 : 0;
}
}
//逐個判斷條件。
//判斷2<=NZ(P1)<=6
nCount = neighbour[1, 1] + neighbour[1, 2] + neighbour[1, 3]
+ neighbour[2, 1] + neighbour[2, 3] +
+neighbour[3, 1] + neighbour[3, 2] + neighbour[3, 3];
if (nCount >= 2 && nCount <= 6)
{
bCondition1 = true;
}
//判斷Z0(P1)=1
nCount = 0;
if (neighbour[1, 2] == 0 && neighbour[1, 1] == 1)
nCount++;
if (neighbour[1, 1] == 0 && neighbour[2, 1] == 1)
nCount++;
if (neighbour[2, 1] == 0 && neighbour[3, 1] == 1)
nCount++;
if (neighbour[3, 1] == 0 && neighbour[3, 2] == 1)
nCount++;
if (neighbour[3, 2] == 0 && neighbour[3, 3] == 1)
nCount++;
if (neighbour[3, 3] == 0 && neighbour[2, 3] == 1)
nCount++;
if (neighbour[2, 3] == 0 && neighbour[1, 3] == 1)
nCount++;
if (neighbour[1, 3] == 0 && neighbour[1, 2] == 1)
nCount++;
if (nCount == 1)
bCondition2 = true;
//判斷P2*P4*P8=0 or Z0(p2)!=1
if (neighbour[1, 2] * neighbour[2, 1] * neighbour[2, 3] == 0)
{
bCondition3 = true;
}
else
{
nCount = 0;
if (neighbour[0, 2] == 0 && neighbour[0, 1] == 1)
nCount++;
if (neighbour[0, 1] == 0 && neighbour[1, 1] == 1)
nCount++;
if (neighbour[1, 1] == 0 && neighbour[2, 1] == 1)
nCount++;
if (neighbour[2, 1] == 0 && neighbour[2, 2] == 1)
nCount++;
if (neighbour[2, 2] == 0 && neighbour[2, 3] == 1)
nCount++;
if (neighbour[2, 3] == 0 && neighbour[1, 3] == 1)
nCount++;
if (neighbour[1, 3] == 0 && neighbour[0, 3] == 1)
nCount++;
if (neighbour[0, 3] == 0 && neighbour[0, 2] == 1)
nCount++;
if (nCount != 1)
bCondition3 = true;
}
//判斷P2*P4*P6=0 or Z0(p4)!=1
if (neighbour[1, 2] * neighbour[2, 1] * neighbour[3, 2] == 0)
{
bCondition4 = true;
}
else
{
nCount = 0;
if (neighbour[1, 1] == 0 && neighbour[1, 0] == 1)
nCount++;
if (neighbour[1, 0] == 0 && neighbour[2, 0] == 1)
nCount++;
if (neighbour[2, 0] == 0 && neighbour[3, 0] == 1)
nCount++;
if (neighbour[3, 0] == 0 && neighbour[3, 1] == 1)
nCount++;
if (neighbour[3, 1] == 0 && neighbour[3, 2] == 1)
nCount++;
if (neighbour[3, 2] == 0 && neighbour[2, 2] == 1)
nCount++;
if (neighbour[2, 2] == 0 && neighbour[1, 2] == 1)
nCount++;
if (neighbour[1, 2] == 0 && neighbour[1, 1] == 1)
nCount++;
if (nCount != 1)
bCondition4 = true;
}
if (bCondition1 && bCondition2 && bCondition3 && bCondition4)
{
m_New.SetPixel(i, j, Color.White);
bModified = true;
}
else
{
m_New.SetPixel(i, j, Color.Black);
}
}
}
}
return m_New;
}
}
}