c# 数字图像处理的一些方法
2016-05-20 16:01
633 查看
最近在写小论文,涉及一些图像处理方面的代码,许久没有写过博客了,论文发了没事就来发点。 代码也不全是自己写的,参考了很多网上和书上的,就在此做个整理吧。。。
先弄一个计时的,因为很多时候需要比较算法的计算时间,但是用系统时间一般不太好使,于是有了下文:
弄个类:
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); }
代码主要来自网络,如有问题,请留言我、
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例
- PHP实现克鲁斯卡尔算法实例解析