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