最近在写小论文,涉及一些图像处理方面的代码,许久没有写过博客了,论文发了没事就来发点。
代码也不全是自己写的,参考了很多网上和书上的,就在此做个整理吧。。。
先弄一个计时的,因为很多时候需要比较算法的计算时间,但是用系统时间一般不太好使,于是有了下文:
弄个类:
internal class HiPerfTimer
{
[DllImport("Kernel32.dll")]
private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
[DllImport("Kernel32.dll")]
private static extern bool QueryPerformanceFrequency(out long lpFrequency);
private long startTime, stopTime;
private long freq;
// Constructor
public HiPerfTimer()
{
startTime = 0;
stopTime = 0;
if (QueryPerformanceFrequency(out freq) == false)
{
// high-performance counter not supported
throw new Win32Exception();
}
}
// Start the timer
public void Start()
{
// lets do the waiting threads there work
Thread.Sleep(0);
QueryPerformanceCounter(out startTime);
}
// Stop the timer
public void Stop()
{
QueryPerformanceCounter(out stopTime);
}
// Returns the duration of the timer (in milliseconds)
public double Duration
{
get
{
return (double)(stopTime - startTime) * 1000 / (double)freq;
}
}
public void ClearTimer()
{
startTime = 0;
stopTime = 0;
}
}
要用时候直接new一个就好:
HiPerfTimer myTimer=new HiPerfTimer();
myTimer.Start();
。。。。
myTimer.Stop();
string time=myTimer.Duration.ToString("####.##") + " 毫秒";
开始正题:
首先读取一个图像:
OpenFileDialog opnDlg = new OpenFileDialog();
opnDlg.Filter = "所有图像文件 | *.bmp; *.pcx; *.png; *.jpg; *.gif;" +
"*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf|" +
"位图( *.bmp; *.jpg; *.png;...) | *.bmp; *.pcx; *.png; *.jpg; *.gif; *.tif; *.ico|"
+"矢量图( *.wmf; *.eps; *.emf;...) | *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf";
opnDlg.Title = "打开图像文件";
opnDlg.ShowHelp = true;
if (opnDlg.ShowDialog() == DialogResult.OK)
{
curFileName = opnDlg.FileName;
try
{
curBitmap = (Bitmap)Image.FromFile(curFileName);
pictureBox1.Image = curBitmap;
pictureBox1.Width = this.curBitmap.Width;
pictureBox1.Height = this.curBitmap.Height;
}
catch (Exception exp)
{
MessageBox.Show(exp.Message);
}
}
Invalidate();
灰度化:
if (curBitmap != null)
{
Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = curBitmap.Width * curBitmap.Height * 3;
byte[] rgbValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
double colorTemp = 0;
for (int i = 0; i < rgbValues.Length; i += 3)
{
colorTemp = rgbValues[i + 2] * 0.299 + rgbValues[i + 1] * 0.587 + rgbValues[i] * 0.114;
rgbValues[i] = rgbValues[i + 1] = rgbValues[i + 2] = (byte)colorTemp;
}
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
curBitmap.UnlockBits(bmpData);
}
二值化图像,就是黑白,可选三种方法:
if (curBitmap != null)
{
Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = curBitmap.Width * curBitmap.Height*3;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
byte T = 0;
byte[] neighb = new byte[bytes];
byte temp = 0;
byte maxGray = 0;
byte minGray = 255;
int[] countPixel = new int[256];
for (int i = 0; i < grayValues.Length; i++)
{
temp = grayValues[i];
countPixel[temp]++;
if (temp > maxGray)
{
maxGray = temp;
}
if (temp < minGray)
{
minGray = temp;
}
}
double mu1, mu2;
int numerator, denominator;
double sigma;
double tempMax = 0;
int method = 0;//修改method,用不阈值法二值化图像
switch (method)
{
case 0://迭代法
byte oldT;
T = oldT = Convert.ToByte((maxGray + minGray) / 2);
do
{
oldT = T;
numerator = denominator = 0;
for (int i = minGray; i < T; i++)
{
numerator += i * countPixel[i];
denominator += countPixel[i];
}
if (denominator == 0)
{
mu1 = 1;
}
else
{
mu1 = numerator / denominator;
}
numerator = denominator = 0;
for (int i = T; i <= maxGray; i++)
{
numerator += i * countPixel[i];
denominator += countPixel[i];
}
mu2 = numerator / denominator;
T = Convert.ToByte((mu1 + mu2) / 2);
}
while (T != oldT);
break;
case 1://Otsu法
double w1 = 0, w2 = 0;
double sum = 0;
numerator = 0;
for (int i = minGray; i <= maxGray; i++)
{
sum += i * countPixel[i];
}
for (int i = minGray; i < maxGray; i++)
{
w1 += countPixel[i];
numerator += i * countPixel[i];
mu1 = numerator / w1;
w2 = grayValues.Length - w1;
mu2 = (sum - numerator) / w2;
sigma = w1 * w2 * (mu1 - mu2) * (mu1 - mu2);
if (sigma > tempMax)
{
tempMax = sigma;
T = Convert.ToByte(i);
}
}
break;
case 2://一维最大熵法
double Ht = 0.0, Hl = 0.0, p = 0.0, pt = 0.0;
for (int i = minGray; i <= maxGray; i++)
{
p = (double)countPixel[i] / grayValues.Length;
if (p < 0.00000000000000001)
continue;
Hl += -p * Math.Log10(p);
}
for (int i = minGray; i <= maxGray; i++)
{
p = (double)countPixel[i] / grayValues.Length;
pt += p;
if (p < 0.00000000000000001)
continue;
Ht += -p * Math.Log10(p);
sigma = Math.Log10(pt * (1 - pt)) + Ht / pt + (Hl - Ht) / (1 - pt);
if (sigma > tempMax)
{
tempMax = sigma;
T = Convert.ToByte(i);
}
}
break;
default:
break;
}
for (int i = 0; i < bytes; i++)
{
if (grayValues[i] < T)
{
grayValues[i] = 0;
}
else
{
grayValues[i] = 255;
}
}
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
curBitmap.UnlockBits(bmpData);
}
图像加强,两种方法,自己验证效果:
Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = curBitmap.Width * curBitmap.Height;
byte[] rgbValues = new byte[bytes * 3];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes * 3);
bool method = false;
if (method == false)//RGB空间分量均衡法
{
byte[] rValues = new byte[bytes];
byte[] gValues = new byte[bytes];
byte[] bValues = new byte[bytes];
for (int i = 0; i < bytes; i++)
{
rValues[i] = rgbValues[i * 3 + 2];
gValues[i] = rgbValues[i * 3 + 1];
bValues[i] = rgbValues[i * 3];
}
rValues = equalization(rValues);
gValues = equalization(gValues);
bValues = equalization(bValues);
for (int i = 0; i < bytes; i++)
{
rgbValues[i * 3 + 2] = rValues[i];
rgbValues[i * 3 + 1] = gValues[i];
rgbValues[i * 3] = bValues[i];
}
}
else//HSI空间亮度均衡化
{
double[] hue = new double[bytes];
double[] sat = new double[bytes];
byte[] inten = new byte[bytes];
double r, g, b;
for (int i = 0; i < bytes; i++)
{
r = rgbValues[i * 3 + 2];
g = rgbValues[i * 3 + 1];
b = rgbValues[i * 3];
double theta = Math.Acos(0.5 * ((r - g) + (r - b)) / Math.Sqrt((r - g) * (r - g) + (r - b) * (g - b) + 1)) / (2 * Math.PI);
hue[i] = ((b <= g) ? theta : (1 - theta));
sat[i] = 1.0 - 3.0 * Math.Min(Math.Min(r, g), b) / (r + g + b + 1);
inten[i] = (byte)((r + g + b) / 3);
}
inten = equalization(inten);
for (int i = 0; i < bytes; i++)
{
r = rgbValues[i * 3 + 2];
g = rgbValues[i * 3 + 1];
b = rgbValues[i * 3];
hue[i] = hue[i] * 2 * Math.PI;
if (hue[i] >= 0 && hue[i] < 2 * Math.PI / 3)
{
b = inten[i] * (1 - sat[i]);
r = inten[i] * (1 + sat[i] * Math.Cos(hue[i]) / Math.Cos(Math.PI / 3 - hue[i]));
g = 3 * inten[i] - (r + b);
}
else if (hue[i] >= 2 * Math.PI / 3 && hue[i] < 4 * Math.PI / 3)
{
r = inten[i] * (1 - sat[i]);
g = inten[i] * (1 + sat[i] * Math.Cos(hue[i] - 2 * Math.PI / 3) / Math.Cos(Math.PI - hue[i]));
b = 3 * inten[i] - (r + g);
}
else //if (h >= 4 * Math.PI / 3 && h <= 2 * Math.PI)
{
g = inten[i] * (1 - sat[i]);
b = inten[i] * (1 + sat[i] * Math.Cos(hue[i] - 4 * Math.PI / 3) / Math.Cos(5 * Math.PI / 3 - hue[i]));
r = 3 * inten[i] - (g + b);
}
if (r > 255)
r = 255;
if (g > 255)
g = 255;
if (b > 255)
b = 255;
rgbValues[i * 3 + 2] = (byte)r;
rgbValues[i * 3 + 1] = (byte)g;
rgbValues[i * 3] = (byte)b;
}
}
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes * 3);
curBitmap.UnlockBits(bmpData);
图像分割,K-均值聚类,注意修改预期聚类数目:
if (curBitmap != null)
{
myTimer.ClearTimer();
myTimer.Start();
Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = curBitmap.Width * curBitmap.Height;
byte[] rgbValues = new byte[bytes * 3];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes * 3);
byte numbers = 2; //预期聚类数目,需要分几类就是几
int[] kNum = new int[numbers];
int[] kAver = new int[numbers * 3];
int[] kOldAver = new int[numbers * 3];
int[] kSum = new int[numbers * 3];
double[] kTemp = new double[numbers];
byte[] segmentMap = new byte[bytes * 3];
//初始化聚类均值
for (int i = 0; i < numbers; i++)
{
kAver[i * 3 + 2] = kOldAver[i * 3 + 2] = Convert.ToInt16(i * 255 / (numbers - 1));
kAver[i * 3 + 1] = kOldAver[i * 3 + 1] = Convert.ToInt16(i * 255 / (numbers - 1));
kAver[i * 3] = kOldAver[i * 3] = Convert.ToInt16(i * 255 / (numbers - 1));
}
int count = 0;
while (true)
{
int order = 0;
for (int i = 0; i < numbers; i++)
{
kNum[i] = 0;
kSum[i * 3 + 2] = kSum[i * 3 + 1] = kSum[i * 3] = 0;
kAver[i * 3 + 2] = kOldAver[i * 3 + 2];
kAver[i * 3 + 1] = kOldAver[i * 3 + 1];
kAver[i * 3] = kOldAver[i * 3];
}
//归属聚类
for (int i = 0; i < bytes; i++)
{
for (int j = 0; j < numbers; j++)
{
kTemp[j] = Math.Pow(rgbValues[i * 3 + 2] - kAver[j * 3 + 2], 2) + Math.Pow(rgbValues[i * 3 + 1] - kAver[j * 3 + 1], 2) + Math.Pow(rgbValues[i * 3] - kAver[j * 3], 2);
}
double temp = 100000;
for (int j = 0; j < numbers; j++)
{
if (kTemp[j] < temp)
{
temp = kTemp[j];
order = j;
}
}
kNum[order]++;
kSum[order * 3 + 2] += rgbValues[i * 3 + 2];
kSum[order * 3 + 1] += rgbValues[i * 3 + 1];
kSum[order * 3] += rgbValues[i * 3];
segmentMap[i] = Convert.ToByte(order);
}
for (int i = 0; i < numbers; i++)
{
if (kNum[i] != 0)
{
kOldAver[i * 3 + 2] = Convert.ToInt16(kSum[i * 3 + 2] / kNum[i]);
kOldAver[i * 3 + 1] = Convert.ToInt16(kSum[i * 3 + 1] / kNum[i]);
kOldAver[i * 3] = Convert.ToInt16(kSum[i * 3] / kNum[i]);
}
}
int kkk = 0;
count++;
for (int i = 0; i < numbers; i++)
{
if (kAver[i * 3 + 2] == kOldAver[i * 3 + 2] && kAver[i * 3 + 1] == kOldAver[i * 3 + 1] && kAver[i * 3] == kOldAver[i * 3])
kkk++;
}
if (kkk == numbers || count == 100)
break;
}
for (int i = 0; i < bytes; i++)
{
for (int j = 0; j < numbers; j++)
{
if (segmentMap[i] == j)
{
rgbValues[i * 3 + 2] = Convert.ToByte(kAver[j * 3 + 2]);
rgbValues[i * 3 + 1] = Convert.ToByte(kAver[j * 3 + 1]);
rgbValues[i * 3] = Convert.ToByte(kAver[j * 3]);
}
}
}
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes * 3);
curBitmap.UnlockBits(bmpData);
}
ISODATA 非监督聚类,同样的聚类数目:
if (curBitmap != null)
{
myTimer.ClearTimer();
myTimer.Start();
Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = curBitmap.Width * curBitmap.Height*3;
byte[] grayValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
int numbers = 2;//预期聚类数目,需要分几类就是几
int k = 2 * numbers;
byte[] segmentMap = new byte[bytes];
List<int> kTemp = new List<int>();
List<int> kNum = new List<int>();
List<int> kAver = new List<int>();
List<int> kSum = new List<int>();
kAver.Clear();
kNum.Clear();
kTemp.Clear();
kSum.Clear();
for (int i = 0; i < k; i++)
{
kAver.Add(Convert.ToInt16(i * 255 / (k - 1)));
kNum.Add(0);
kTemp.Add(0);
kSum.Add(0);
}
while (true)
{
int temp;
for (int i = 0; i < bytes; i++)
{
kTemp.Clear();
int order = 0;
for (int j = 0; j < k; j++)
{
kTemp.Add(Math.Abs(grayValues[i] - kAver[j]));
}
temp = 255;
for (int j = 0; j < k; j++)
{
if (kTemp[j] < temp)
{
temp = kTemp[j];
order = j;
}
}
int num = kNum[order] + 1;
kNum.RemoveAt(order);
kNum.Insert(order, num);
int sum = kSum[order] + grayValues[i];
kSum.RemoveAt(order);
kSum.Insert(order, sum);
segmentMap[i] = Convert.ToByte(order);
}
for (int i = 0; i < k; i++)
{
if (kNum[i] == 0)
{
kNum.RemoveAt(i);
kAver.RemoveAt(i);
kSum.RemoveAt(i);
i--;
k--;
}
}
kAver.Clear();
for (int i = 0; i < k; i++)
{
kAver.Add(Convert.ToInt16(kSum[i] / kNum[i]));
}
if (k <= numbers)
break;
temp = 255;
int removeI = 0, removeJ = 0;
for (int i = 0; i < k; i++)
{
for (int j = i + 1; j < k; j++)
{
int distanceIJ = Math.Abs(kAver[i] - kAver[j]);
if (distanceIJ < temp)
{
temp = distanceIJ;
removeI = i;
removeJ = j;
}
}
}
k--;
kNum.Add(kNum[removeI] + kNum[removeJ]);
kAver.Add(Convert.ToInt16((kNum[removeI] * kAver[removeI] + kNum[removeJ] * kAver[removeJ]) / (kNum[removeI] + kNum[removeJ])));
kSum.Add(kNum[removeI] * kAver[removeI] + kNum[removeJ] * kAver[removeJ]);
kNum.RemoveAt(removeI);
kNum.RemoveAt(removeJ);
kAver.RemoveAt(removeI);
kAver.RemoveAt(removeJ);
kSum.RemoveAt(removeI);
kSum.RemoveAt(removeJ);
}
for (int i = 0; i < bytes; i++)
{
for (int j = 0; j < numbers; j++)
{
if (segmentMap[i] == j)
{
grayValues[i] = Convert.ToByte(kAver[j]);
}
}
}
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
curBitmap.UnlockBits(bmpData);
}
代码主要来自网络,如有问题,请留言我、