机器视觉入门之路(三七,经典canny边缘检测(计算机视觉里程碑),c#)

    技术2022-07-12  63

    先看原图,canny图,和canny局部放大图(看来需要改进的地方很多啊!):

    以下是我canny算子的完整代码,虽然他能运行,可能没有想象的那么好,没有的请你补充完整,可以随意改进,直到你想要的完美结果。(比如,增加高斯平滑,不用行吗?比如,增加sobel,不用行吗?,比如,这个算法太费时间,如何高效运行?)

    以前用繁体中文注释,代码中有乱码,请见谅,不是日文版!哈哈!(从c++翻译过来)

          private void CannySideGrandiant(ref byte[] m_image0, int w, int h,  ref  byte[,] m_N)         {             int[,] m_P = new int[h, w]; int[,] m_Q = new int[h, w];             int[,] m_M = new int[h, w]; double[,] m_Theta = new double[h, w];                      //  unsafe             {                 for (int j = 0; j < h; j++)                     for (int i = 0; i < w; i++)                     {                         int n0 = j * w + i;                         m_N[j, i] = m_image0[n0];///初始化输出图像?                     }             }             for (int i = 0; i < (h - 1); i++)             {                 for (int j = 0; j < (w - 1); j++)                 {                     int n0 = (i * w + j);

                        //m_P[i, j] = Math.Abs(m_image0[n0] - m_image0[n0 + 1]);                     //m_Q[i, j] = Math.Abs(m_image0[n0] - m_image0[n0 + w]);                     m_P[i, j] = m_image0[n0] - m_image0[n0 + 1];//x方向梯度图像                     m_Q[i, j] = m_image0[n0] - m_image0[n0 + w];//y方向梯度图像                     //try                     //{                     //    m_P[i, j] = m_image0[n0 - 1] + m_image0[n0 + 1] - 2 * m_image0[n0];                     //    m_Q[i, j] = m_image0[n0 - w] + m_image0[n0 + w] - 2 * m_image0[n0];                     //}                     //catch (Exception ex)                     //{ }                 }             }

                for (int i = 0; i < h - 1; i++)             {                 for (int j = 0; j < w - 1; j++)                 {                   //  m_M[i, j] = m_P[i, j] + m_Q[i, j];                    m_M[i, j] = Math.Abs(m_P[i, j]) + Math.Abs(m_Q[i, j]);//梯度图像                     m_M[i, j] = m_M[i, j] > 255 ? 255 : m_M[i, j];

                        //m_Theta[i, j] = Math.Atan(m_Q[i, j] / (m_P[i, j] * 1.0)) * 57.3;                     //if (m_Theta[i, j] < 0)                     //    m_Theta[i, j] += 360;                     m_Theta[i, j] = jiaoduAndxiangxian(m_P[i, j], m_Q[i, j]) * 57.3;//梯度角图像                 }//角度和象限函数,前面博文经常看到,去找找看?             }

                for (int i = 0; i < w; i++)             {                 m_N[0, i] = 0;                 m_N[h - 1, i] = 0;//边界置零             }             for (int j = 0; j < h; j++)             {                 m_N[j, 0] = 0;                 m_N[j, w - 1] = 0;//边界置零             }

                int g1 = 0, g2 = 0, g3 = 0, g4 = 0;                        double dTmp1 = 0.0, dTmp2 = 0.0;                        double dWeight = 0.0;

                           for (int i = 1; i < (w - 1); i++)                        {                            for (int j = 1; j < (h - 1); j++)                            {                                //辫0獶娩翴                                   if (m_M[j, i] == 0)                                {                                    m_N[j, i] = 0;                                }                                else                                {

                                       材///                                       /       g1  g2                  /                                       /           C                   /                                       /           g4  g3              /                                       /                                       if (((m_Theta[j, i] >= 90) && (m_Theta[j, i] < 135)) ||                                        ((m_Theta[j, i] >= 270) && (m_Theta[j, i] < 315)))                                    {//寻找梯度方向上的亚像素点

                                           g1 = m_M[j - 1, i - 1];                                        g2 = m_M[j - 1, i];                                        g4 = m_M[j + 1, i];                                        g3 = m_M[j + 1, i + 1];                                        dWeight = Math.Abs(m_P[j, i] / (m_Q[j, i] * 1.0));                                        dTmp1 = g1 * dWeight + g2 * (1 - dWeight);                                        dTmp2 = g3 * dWeight + g4 * (1 - dWeight);                                    }                                    材///                                       /               g1                      /                                       /       g4  C   g2              /                                       /       g3              /                                       /                                     else if (((m_Theta[j, i] >= 0) && (m_Theta[j, i] < 45)) ||                                        ((m_Theta[j, i] >= 180) && (m_Theta[j, i] < 225)))//寻找梯度方向上的亚像素点                                    {   //int nPointIdx = i+j*w;                                        g3 = m_M[j + 1, i - 1];                                        g2 = m_M[j, i + 1];                                        g1 = m_M[j - 1, i + 1];                                        g4 = m_M[j, i - 1];                                        dWeight = Math.Abs(m_Q[j, i] / (m_P[j, i] * 1.0));   //  

                                           dTmp1 = g1 * dWeight + g2 * (1 - dWeight);                                        dTmp2 = g3 * dWeight + g4 * (1 - dWeight);

                                       }                                    材///                                       /           g2  g1              /                                       /           C                   /                                       /       g3  g4                  /                                       ///                                       else if (((m_Theta[j, i] >= 45) && (m_Theta[j, i] < 90)) ||                                        ((m_Theta[j, i] >= 225) && (m_Theta[j, i] < 270)))//寻找梯度方向上的亚像素点                                    {  //int nPointIdx = i+j*w;                                        g2 = m_M[j - 1, i];                                        g1 = m_M[j - 1, i + 1];                                        g4 = m_M[j + 1, i];                                        g3 = m_M[j + 1, i - 1];                                        dWeight = Math.Abs(m_P[j, i] / (m_Q[j, i] * 1.0));   //はタち   

                                           dTmp1 = g1 * dWeight + g2 * (1 - dWeight);                                        dTmp2 = g3 * dWeight + g4 * (1 - dWeight);                                    }                                    材///                                       /       g3              /                                       /       g4  C   g2              /                                       /               g1                      /                                       /                                     else if (((m_Theta[j, i] >= 135) && (m_Theta[j, i] < 180)) ||                                        ((m_Theta[j, i] >= 315) && (m_Theta[j, i] < 360)))//寻找梯度方向上的亚像素点                                    {  //int nPointIdx = i+j*w;                                        g1 = m_M[j + 1, i + 1];                                        g2 = m_M[j, i + 1];                                        g3 = m_M[j - 1, i - 1];                                        g4 = m_M[j, i - 1];                                        dWeight = Math.Abs(m_Q[j, i] / (m_P[j, i] * 1.0));   //タち                                           dTmp1 = g1 * dWeight + g2 * (1 - dWeight);                                        dTmp2 = g3 * dWeight + g4 * (1 - dWeight);                                    }

                                   }

                                   if ((m_M[j, i] >= dTmp1) && (m_M[j, i] >= dTmp2))                                {                                    m_N[j, i] = 128;    //极大值不抑制 置128                                                             }                                else                                {                                    m_N[j, i] =0;    //非极大值抑制置0                          

                                   }                            }                        }                        //N is 0 or 128 gray bitmap                        //蔼耬砞﹚                        int[] nHist = new int[361];                        int nEdgeNum;                        int nMaxMag = 0;                        int nHighCount;

                           for (int i = 0; i < h; i++)                        {                            for (int j = 0; j < w; j++)                            {                                if (m_N[i, j] == 128)                                    nHist[m_M[i, j]]++;//直方图统计                            }                        }

                           nEdgeNum = nHist[0];                        nMaxMag = 0;                        for (int i = 1; i < 361; i++)                        {                            if (nHist[i] != 0)                            {                                nMaxMag = i;                            }                            nEdgeNum += nHist[i];                        }

                           //double dRatHigh = m_twoThres; ノㄓ絋﹚蔼耬                        double dRatHigh = 0.9; ノㄓ絋﹚蔼耬                        double dThrHigh;                        int dThrLow;                        double dRatLow = 0.5;                        nHighCount = (int)(dRatHigh * nEdgeNum + 0.5);                        int jj = 1;                        nEdgeNum = nHist[1];                        while ((jj < (nMaxMag - 1)) && (nEdgeNum < nHighCount))                        {                            jj++;                            nEdgeNum += nHist[jj];                        }                        dThrHigh = jj;//根据直方图统计结果,计算高门槛值                        dThrLow = (int)((dThrHigh) * dRatLow + 0.5);//根据直方图统计结果,计算低门槛值

                           for (int i = 0; i < h; i++)                        {                            for (int j = 0; j < w; j++)                            {                                if ((m_N[i, j] == 128) && (m_M[i, j] >= dThrHigh))                                {                                    m_N[i, j] = 255;

                                       TraceEdge(i, j, dThrLow, ref m_N, ref m_M);  //染色算法,强边缘和弱边缘连接                                }                            }                        }                        for (int i = 0; i < h; i++)                        {                            for (int j = 0; j < w; j++)                            {                                if (m_N[i, j] != 255)                                {                                    m_N[i, j] = 0;//最后返回图像,使用0和255,增强图像对比度

                                   }                            }                        }

            }

    Processed: 0.014, SQL: 9