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

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

改进代码,红色标出,增加了高斯平滑,以及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;

                    }
                }
            }

        }

果然有效果!