c# 数字图像处理的一些方法

最近在写小论文,涉及一些图像处理方面的代码,许久没有写过博客了,论文发了没事就来发点。
代码也不全是自己写的,参考了很多网上和书上的,就在此做个整理吧。。。

先弄一个计时的,因为很多时候需要比较算法的计算时间,但是用系统时间一般不太好使,于是有了下文:
弄个类:

 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);
            }

代码主要来自网络,如有问题,请留言我、

你可能感兴趣的:(桌面应用)