机器视觉入门之路(四一,经典canny边缘检测(改进),c#)

    技术2025-01-06  21

    先看改进效果,全图和局部放大图:

    改进代码,红色标出,增加了高斯平滑,以及sobel处理,你可以看到,sobel会让边缘变厚。 

     private void Cannyimprove(ref byte[] m_image0, int w, int h, ref  byte[,] m_N)         {//增加高斯平滑和sobel处理202007040831             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];                         if(j>=1&&j<h-1&&i>=1&&i<w-1)                         {//gaos平滑                             int temp=(m_image0[n0 - w - 1] + 2 * m_image0[n0 - w] + m_image0[n0 - w + 1] +                                                             2 * m_image0[n0 - 1] + 4 * m_image0[n0] + 2 * m_image0[n0 + 1] +                                                             m_image0[n0 + w - 1] + 2 * m_image0[n0 + w] + m_image0[n0 + w + 1]) /16;                             if (temp>255)temp=255;                             m_N[j, i] = (byte)(temp);                         }                     }             }             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];                     m_Q[i, j] = m_image0[n0] - m_image0[n0 + w];                     //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)                     //{ }                     if(i>=1&&j>=1)                     {                         m_P[i, j] = m_image0[n0 - w - 1] + 2 * m_image0[n0 - w] + m_image0[n0 - w + 1] -           m_image0[n0 + w  - 1] - 2 * m_image0[n0 + w ] - m_image0[n0 + w  + 1];//sobelx处理                         m_Q[i, j] = (-1) * m_image0[n0 - w - 1] - 2 * m_image0[n0 - 1] - m_image0[n0 + w - 1] +           m_image0[n0 - w  + 1] + 2 * m_image0[n0 + 1] + m_image0[n0 + w  + 1];//sobely处理                     }                   

                    }             }

                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;

                        }                     else                     {                         m_N[j, i] = 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;

                        }                 }             }

            }

    果然有效果!

    Processed: 0.010, SQL: 9