[算法說明]html
Canny邊緣檢測算法能夠分爲4步:高斯濾波器平滑處理、梯度計算、非極大值抑制、雙閾值邊緣檢算法
測和邊緣鏈接。spa
1,高斯濾波器平滑處理。因爲圖像中常常包含一些高斯噪聲,所以在邊緣檢測前咱們要先用高斯.net
濾波器對其進行濾波,爲了方便,一般是使用一些高斯模板,這裏咱們使用以下的高斯濾波器模板。code
/// <summary> /// Canny edge detect process. /// </summary> /// <param name="src">The source image.</param> /// <param name="highThreshould">The high threshould value. </param> /// <param name="lowThreshould">The low threshould value. </param> /// <returns></returns> public static WriteableBitmap CannyedgedetectProcess(WriteableBitmap src,int highThreshould,int lowThreshould)////圖像油畫效果 { if (src != null) { int w = src.PixelWidth; int h = src.PixelHeight; WriteableBitmap srcImage = new WriteableBitmap(w, h); byte[] temp = src.PixelBuffer.ToArray(); byte[] tempMask = (byte[])temp.Clone(); int[,] srcBytes = new int[w, h]; for (int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { srcBytes[i, j] = (int)(tempMask[i * 4 + j * w * 4] * 0.114 + tempMask[i * 4 + 1 + j * w * 4] * 0.587 + tempMask[i * 4 + 2 + j * w * 4] * 0.299); } } float gradientMax = 0; float[,] gradient = new float[w, h]; byte[,] degree = new byte[w, h]; GaussFilter(ref srcBytes, w, h); GetGradientDegree(srcBytes, ref gradient, ref degree, ref gradientMax, w, h); NonMaxMini(gradient, ref srcBytes, gradientMax, w, h, degree); TwoThreshouldJudge(highThreshould, lowThreshould, ref srcBytes, w, h); for (int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { temp[i * 4 + j * w * 4] = temp[i * 4 + 1 + j * w * 4] = temp[i * 4 + 2 + j * w * 4] = (byte)srcBytes[i, j]; } } Stream sTemp = srcImage.PixelBuffer.AsStream(); sTemp.Seek(0, SeekOrigin.Begin); sTemp.Write(temp, 0, w * 4 * h); return srcImage; } else { return null; } } //高斯濾波 private static void GaussFilter(ref int[,] src, int x, int y) { for (int j = 1; j < y - 1; j++) { for (int i = 1; i < x - 1; i++) { src[i, j] = (4 * src[i, j] + src[i - 1, j - 1] + src[i + 1, j - 1] + src[i - 1, j + 1] + src[i + 1, j + 1] + 2 * src[i, j - 1] + 2 * src[i - 1, j] + 2 * src[i, j + 1] + 2 * src[i + 1, j]) / 16; } } } //梯度相位角獲取 private static void GetGradientDegree(int[,] srcBytes, ref float[,] gradient, ref byte[,] degree, ref float GradientMax, int x, int y) { gradient = new float[x, y]; degree = new byte[x, y]; int gx, gy; int temp; double div; for (int j = 1; j < y - 1; j++) { for (int i = 1; i < x - 1; i++) { gx = srcBytes[i + 1, j - 1] + 2 * srcBytes[i + 1, j] + srcBytes[i + 1, j + 1] - srcBytes[i - 1, j - 1] - 2 * srcBytes[i - 1, j] - srcBytes[i - 1, j + 1]; gy = srcBytes[i - 1, j - 1] + 2 * srcBytes[i, j - 1] + srcBytes[i + 1, j - 1] - srcBytes[i - 1, j + 1] - 2 * srcBytes[i, j + 1] - srcBytes[i + 1, j + 1]; gradient[i, j] = (float)Math.Sqrt((double)(gx * gx + gy * gy)); if (GradientMax < gradient[i, j]) { GradientMax = gradient[i, j]; } if (gx == 0) { temp = (gy == 0) ? 0 : 90; } else { div = (double)gy / (double)gx; if (div < 0) { temp = (int)(180 - Math.Atan(-div) * 180 / Math.PI); } else { temp = (int)(Math.Atan(div) * 180 / Math.PI); } if (temp < 22.5) { temp = 0; } else if (temp < 67.5) { temp = 45; } else if (temp < 112.5) { temp = 90; } else if (temp < 157.5) { temp = 135; } else temp = 0; } degree[i, j] = (byte)temp; } } } //非極大值抑制 private static void NonMaxMini(float[,] gradient, ref int[,] srcBytes, float GradientMax, int x, int y, byte[,] degree) { float leftPixel = 0, rightPixel = 0; for (int j = 1; j < y - 1; j++) { for (int i = 1; i < x - 1; i++) { switch (degree[i, j]) { case 0: leftPixel = gradient[i - 1, j]; rightPixel = gradient[i + 1, j]; break; case 45: leftPixel = gradient[i - 1, j + 1]; rightPixel = gradient[i + 1, j - 1]; break; case 90: leftPixel = gradient[i, j + 1]; rightPixel = gradient[i, j - 1]; break; case 135: leftPixel = gradient[i + 1, j + 1]; rightPixel = gradient[i - 1, j - 1]; break; default: break; } if ((gradient[i, j] < leftPixel) || (gradient[i, j] < rightPixel)) { srcBytes[i, j] = 0; } else { srcBytes[i, j] = (int)(255 * gradient[i, j] / GradientMax); } } } } //雙閾值邊緣判斷 private static void TwoThreshouldJudge(int highThreshold, int lowThreshould, ref int[,] srcBytes, int x, int y) { for (int j = 1; j < y - 1; j++) { for (int i = 1; i < x - 1; i++) { if (srcBytes[i, j] > highThreshold) { srcBytes[i, j] = 255; } else if (srcBytes[i, j] < lowThreshould) { srcBytes[i, j] = 0; } else { if (srcBytes[i - 1, j - 1] < highThreshold && srcBytes[i, j - 1] < highThreshold && srcBytes[i + 1, j - 1] < highThreshold && srcBytes[i - 1, j] < highThreshold && srcBytes[i + 1, j] < highThreshold && srcBytes[i - 1, j + 1] < highThreshold && srcBytes[i, j + 1] < highThreshold && srcBytes[i + 1, j + 1] < highThreshold) { srcBytes[i, j] = 0; } else srcBytes[i, j] = 255; } } } }