原文:Win8 Metro(C#)数字图像处理--2.48Canny边缘检测算法



[算法说明]

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

测和边缘连接。

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

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

        /// <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;
}
}
}
}


Win8 Metro(C#)数字图像处理--2.48Canny边缘检测算法的更多相关文章

  1. Win8 Metro(C#)数字图像处理--2.75灰度图像的形态学算法

    原文:Win8 Metro(C#)数字图像处理--2.75灰度图像的形态学算法 前面章节中介绍了二值图像的形态学算法,这里讲一下灰度图的形态学算法,主要是公式,代码略. 1,膨胀算法 2,腐蚀算法 3 ...

  2. Win8 Metro(C#)数字图像处理--4图像颜色空间描述

    原文:Win8 Metro(C#)数字图像处理--4图像颜色空间描述  图像颜色空间是图像颜色集合的数学表示,本小节将针对几种常见颜色空间做个简单介绍. /// <summary> / ...

  3. Win8 Metro(C#)数字图像处理--3.2图像方差计算

    原文:Win8 Metro(C#)数字图像处理--3.2图像方差计算 /// <summary> /// /// </summary>Variance computing. / ...

  4. Win8 Metro(C#)数字图像处理--3.3图像直方图计算

    原文:Win8 Metro(C#)数字图像处理--3.3图像直方图计算 /// <summary> /// Get the array of histrgram. /// </sum ...

  5. Win8 Metro(C#)数字图像处理--3.4图像信息熵计算

    原文:Win8 Metro(C#)数字图像处理--3.4图像信息熵计算 [函数代码] /// <summary> /// Entropy of one image. /// </su ...

  6. Win8 Metro(C#)数字图像处理--3.5图像形心计算

    原文:Win8 Metro(C#)数字图像处理--3.5图像形心计算 /// <summary> /// Get the center of the object in an image. ...

  7. Win8 Metro(C#)数字图像处理--2.73一种背景图像融合特效

    原文:Win8 Metro(C#)数字图像处理--2.73一种背景图像融合特效 /// <summary> /// Image merge process. /// </summar ...

  8. Win8 Metro(C#)数字图像处理--3.1图像均值计算

    原文:Win8 Metro(C#)数字图像处理--3.1图像均值计算 /// <summary> /// Mean value computing. /// </summary> ...

  9. Win8 Metro(C#)数字图像处理--2.74图像凸包计算

    原文:Win8 Metro(C#)数字图像处理--2.74图像凸包计算 /// <summary> /// Convex Hull compute. /// </summary> ...

随机推荐

  1. [iOS]iOS开发人员账号申请与注冊流程

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意.重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...

  2. C 语言 —— ! 和 ~(感叹号和波浪号)

    ~ 表示按位取反,是位运算符,运算对象是 2 进制. !表示逻辑非,是逻辑运算符,运算对象是真或假.最终的结果也是 0/1 !!:则表示取过一次非之后,再取一次: !!5 ⇒ 1

  3. Java相关思维导图分享

    非常多朋友都给我发私信希望获得一份Java知识的思维导图,我来不及一一答复.原先是给大家一个百度网盘的链接分享,大家能够自己去下载,可是不知道云盘还能用多久.把相关资源转移到了QQ的群共享中.须要的朋 ...

  4. 初始化NSDictionary:(工作经验)两种方法有时候效果不一样

    方法1: NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; [dic setObject:[Hp_KeysArray obj ...

  5. ActivityManagerService的启动过程

    AMS对象随系统进程启动而构建,随着系统进程退出而消亡,可以说,AMS与系统进程共存亡. 先上一张总的启动时序图: 上图分为三个步骤: 初始化系统进程的运行环境; 初始化AMS对象; AMS对象启动的 ...

  6. C++程序员经常问的11个问题

    下面的这些要点是对所有的C++程序员都适用的.我之所以说它们是最重要的,是因为这些要点中提到的是你通常在C++书中或网站上无法找到的.如:指向成员的指针,这是许多资料中都不愿提到的地方,也是经常出错的 ...

  7. Ubuntu下一个python的BeautifulSoup和rsa安装方法---信息检索project2部分:微博爬行要求python包裹

    后果<信息检索>第二project,微博具有抓取数据,再处理.师兄给了代码.让慢慢爬.可是在ubuntu下.少了非常多python软件包.须要安装. 1.首先执行时.说少了python.B ...

  8. [Android]Fragment自定义动画、动画监听以及兼容性包使用

    Fragment是Android在API 11之后加入的一个组件,对提高Android开发中的布局合理性和布局效率都有很大作用,尤其是在Android平板等大屏幕设备的开发中,Fragment的引入能 ...

  9. 读取Jar包外面的配置文件

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/shenxiandashu/article/details/79193705 比较常用的方法是将pro ...

  10. 在IIS上部署.net core的webapi项目 以及502.5错误的两种解决方法

    首先要在服务器上面安装.net core https://github.com/dotnet/core/tree/master/release-notes/download-archives 这里面有 ...