先看改进效果,全图和局部放大图:
改进代码,红色标出,增加了高斯平滑,以及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;
}
}
}
}
果然有效果!