Canny边缘检测算法C#源码

[算法说明]

Canny边缘检测算法可以分为4步:高斯滤波器平滑处理、梯度计算、非极大值抑制、双阈值边缘检

测和边缘连接。

  1,高斯滤波器平滑处理。由于图像中经常包含一些高斯噪声,因此在边缘检测前我们要先用高斯

滤波器对其进行滤波,为了方便,通常是使用一些高斯模板,这里我们使用如下的高斯滤波器模板。

 

 
  1. /// <summary>

  2. /// Canny edge detect process.

  3. /// </summary>

  4. /// <param name="src">The source image.</param>

  5. /// <param name="highThreshould">The high threshould value. </param>

  6. /// <param name="lowThreshould">The low threshould value. </param>

  7. /// <returns></returns>

  8. public static WriteableBitmap CannyedgedetectProcess(WriteableBitmap src,int highThreshould,int lowThreshould)图像油画效果

  9. {

  10. if (src != null)

  11. {

  12. int w = src.PixelWidth;

  13. int h = src.PixelHeight;

  14. WriteableBitmap srcImage = new WriteableBitmap(w, h);

  15. byte[] temp = src.PixelBuffer.ToArray();

  16. byte[] tempMask = (byte[])temp.Clone();

  17. int[,] srcBytes = new int[w, h];

  18. for (int j = 0; j < h; j++)

  19. {

  20. for (int i = 0; i < w; i++)

  21. {

  22. 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);

  23. }

  24. }

  25. float gradientMax = 0;

  26. float[,] gradient = new float[w, h];

  27. byte[,] degree = new byte[w, h];

  28. GaussFilter(ref srcBytes, w, h);

  29. GetGradientDegree(srcBytes, ref gradient, ref degree, ref gradientMax, w, h);

  30. NonMaxMini(gradient, ref srcBytes, gradientMax, w, h, degree);

  31. TwoThreshouldJudge(highThreshould, lowThreshould, ref srcBytes, w, h);

  32. for (int j = 0; j < h; j++)

  33. {

  34. for (int i = 0; i < w; i++)

  35. {

  36. temp[i * 4 + j * w * 4] = temp[i * 4 + 1 + j * w * 4] = temp[i * 4 + 2 + j * w * 4] = (byte)srcBytes[i, j];

  37. }

  38. }

  39. Stream sTemp = srcImage.PixelBuffer.AsStream();

  40. sTemp.Seek(0, SeekOrigin.Begin);

  41. sTemp.Write(temp, 0, w * 4 * h);

  42. return srcImage;

  43. }

  44. else

  45. {

  46. return null;

  47. }

  48. }

  49. //高斯滤波

  50. private static void GaussFilter(ref int[,] src, int x, int y)

  51. {

  52. for (int j = 1; j < y - 1; j++)

  53. {

  54. for (int i = 1; i < x - 1; i++)

  55. {

  56. 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;

  57. }

  58. }

  59. }

  60. //梯度相位角获取

  61. private static void GetGradientDegree(int[,] srcBytes, ref float[,] gradient, ref byte[,] degree, ref float GradientMax, int x, int y)

  62. {

  63. gradient = new float[x, y];

  64. degree = new byte[x, y];

  65. int gx, gy;

  66. int temp;

  67. double div;

  68. for (int j = 1; j < y - 1; j++)

  69. {

  70. for (int i = 1; i < x - 1; i++)

  71. {

  72. 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];

  73. 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];

  74. gradient[i, j] = (float)Math.Sqrt((double)(gx * gx + gy * gy));

  75. if (GradientMax < gradient[i, j])

  76. {

  77. GradientMax = gradient[i, j];

  78. }

  79. if (gx == 0)

  80. {

  81. temp = (gy == 0) ? 0 : 90;

  82. }

  83. else

  84. {

  85. div = (double)gy / (double)gx;

  86. if (div < 0)

  87. {

  88. temp = (int)(180 - Math.Atan(-div) * 180 / Math.PI);

  89. }

  90. else

  91. {

  92. temp = (int)(Math.Atan(div) * 180 / Math.PI);

  93. }

  94. if (temp < 22.5)

  95. {

  96. temp = 0;

  97. }

  98. else if (temp < 67.5)

  99. {

  100. temp = 45;

  101. }

  102. else if (temp < 112.5)

  103. {

  104. temp = 90;

  105. }

  106. else if (temp < 157.5)

  107. {

  108. temp = 135;

  109. }

  110. else

  111. temp = 0;

  112. }

  113. degree[i, j] = (byte)temp;

  114. }

  115. }

  116. }

  117. //非极大值抑制

  118. private static void NonMaxMini(float[,] gradient, ref int[,] srcBytes, float GradientMax, int x, int y, byte[,] degree)

  119. {

  120. float leftPixel = 0, rightPixel = 0;

  121. for (int j = 1; j < y - 1; j++)

  122. {

  123. for (int i = 1; i < x - 1; i++)

  124. {

  125. switch (degree[i, j])

  126. {

  127. case 0:

  128. leftPixel = gradient[i - 1, j];

  129. rightPixel = gradient[i + 1, j];

  130. break;

  131. case 45:

  132. leftPixel = gradient[i - 1, j + 1];

  133. rightPixel = gradient[i + 1, j - 1];

  134. break;

  135. case 90:

  136. leftPixel = gradient[i, j + 1];

  137. rightPixel = gradient[i, j - 1];

  138. break;

  139. case 135:

  140. leftPixel = gradient[i + 1, j + 1];

  141. rightPixel = gradient[i - 1, j - 1];

  142. break;

  143. default:

  144. break;

  145. }

  146. if ((gradient[i, j] < leftPixel) || (gradient[i, j] < rightPixel))

  147. {

  148. srcBytes[i, j] = 0;

  149. }

  150. else

  151. {

  152. srcBytes[i, j] = (int)(255 * gradient[i, j] / GradientMax);

  153. }

  154. }

  155. }

  156. }

  157. //双阈值边缘判断

  158. private static void TwoThreshouldJudge(int highThreshold, int lowThreshould, ref int[,] srcBytes, int x, int y)

  159. {

  160. for (int j = 1; j < y - 1; j++)

  161. {

  162. for (int i = 1; i < x - 1; i++)

  163. {

  164. if (srcBytes[i, j] > highThreshold)

  165. {

  166. srcBytes[i, j] = 255;

  167. }

  168. else if (srcBytes[i, j] < lowThreshould)

  169. {

  170. srcBytes[i, j] = 0;

  171. }

  172. else

  173. {

  174. if (srcBytes[i - 1, j - 1] < highThreshold && srcBytes[i, j - 1] < highThreshold && srcBytes[i + 1, j - 1] < highThreshold && srcBytes[i - 1, j] < highThreshold

  175. && srcBytes[i + 1, j] < highThreshold && srcBytes[i - 1, j + 1] < highThreshold && srcBytes[i, j + 1] < highThreshold && srcBytes[i + 1, j + 1] < highThreshold)

  176. {

  177. srcBytes[i, j] = 0;

  178. }

  179. else

  180. srcBytes[i, j] = 255;

  181. }

  182. }

  183. }

  184. }

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值