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