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

先看原图,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,增强图像对比度

                               }
                           }
                       }

        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值