Susan边缘检测,方法简单,效率高,具体参照 The SUSAN Edge Detector in Detail, 修改dThreshold值,可以改变检测效果,用参照提供的重心法、力矩法可得到边缘方向;

        /// https://users.fmrib.ox.ac.uk/~steve/susan/susan/node6.html
public unsafe static Bitmap SusanGray(this Bitmap sourceBitmap)
{
int[] rowRadius = new int[] { , , , , , , };
int width = sourceBitmap.Width;
int height = sourceBitmap.Height;
BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(, , width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); int stride = sourceData.Stride;
byte[] pixelBuffer = new byte[stride * sourceData.Height];
byte[] resultBuffer = new byte[stride * sourceData.Height]; Marshal.Copy(sourceData.Scan0, pixelBuffer, , pixelBuffer.Length);
sourceBitmap.UnlockBits(sourceData); float rgb = ; for (int k = ; k < pixelBuffer.Length; k += )
{
rgb = pixelBuffer[k] * 0.11f;
rgb += pixelBuffer[k + ] * 0.59f;
rgb += pixelBuffer[k + ] * 0.3f; pixelBuffer[k] = (byte)rgb;
pixelBuffer[k + ] = pixelBuffer[k];
pixelBuffer[k + ] = pixelBuffer[k];
pixelBuffer[k + ] = ;
} int[] susanMap = new int[height * width]; int offset = stride - width * ; GCHandle srchandle = GCHandle.Alloc(susanMap, GCHandleType.Pinned);
IntPtr susan = srchandle.AddrOfPinnedObject(); int dThreshold = ;
fixed (byte* pbuff = pixelBuffer, rbuff = resultBuffer)
{
byte* src = pbuff + stride * + * ;
int* br = (int*)susan + height * + ;
byte* dst = rbuff + stride * + * ; for (int offsetY = ; offsetY < height - ; offsetY++)
{
for (int offsetX = ; offsetX < width - ; offsetX++, src += ,dst+=, br++)
{
byte nucleusValue = *src;
int usan = ; int cx = , cy = ; for (int i = -; i <= ; i++)
{ int r = rowRadius[i + ]; byte* ptr = (byte*)((int)src + stride * i); for (int j = -r; j <= r; j++)
{
int c = (int)Math.Exp(-Math.Pow((System.Math.Abs(nucleusValue - ptr[j * ]) / dThreshold), ));
usan += c;
cx += j * c;
cy += i * c;
}
}
if (usan < )
usan = -usan;
else
usan = ;
if ((usan < ) && (cx != || cy != ))
{
*dst = ;
dst[] = ;
dst[] = ;
dst[] = ;
}
else
{
*dst = ;
dst[] = ;
dst[] = ;
dst[] = ;
}
*br = usan;
}
src += * + offset;
dst += * + offset;
br += ;
}
} Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height); BitmapData resultData = resultBitmap.LockBits(new Rectangle(, ,
resultBitmap.Width, resultBitmap.Height),
ImageLockMode.WriteOnly,
PixelFormat.Format32bppArgb); Marshal.Copy(resultBuffer, , resultData.Scan0, resultBuffer.Length);
resultBitmap.UnlockBits(resultData); return resultBitmap; }

并行的方法:

        public unsafe static Bitmap ParallelSusan(this Bitmap sourceBitmap)
{
int width = sourceBitmap.Width;
int height = sourceBitmap.Height;
BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(, , width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); int stride = sourceData.Stride;
byte[] pixelBuffer = new byte[stride * sourceData.Height];
byte[] resultBuffer = new byte[stride * sourceData.Height]; Marshal.Copy(sourceData.Scan0, pixelBuffer, , pixelBuffer.Length);
sourceBitmap.UnlockBits(sourceData); float rgb = ; for (int k = ; k < pixelBuffer.Length; k += )
{
rgb = pixelBuffer[k] * 0.11f;
rgb += pixelBuffer[k + ] * 0.59f;
rgb += pixelBuffer[k + ] * 0.3f; pixelBuffer[k] = (byte)rgb;
pixelBuffer[k + ] = pixelBuffer[k];
pixelBuffer[k + ] = pixelBuffer[k];
pixelBuffer[k + ] = ;
} int[] susanMap = new int[height * width]; int offset = stride - width * ;
GCHandle srchandle = GCHandle.Alloc(pixelBuffer, GCHandleType.Pinned);
IntPtr src = srchandle.AddrOfPinnedObject(); GCHandle dsthandle = GCHandle.Alloc(resultBuffer, GCHandleType.Pinned);
IntPtr dst = dsthandle.AddrOfPinnedObject(); GCHandle suhandle = GCHandle.Alloc(susanMap, GCHandleType.Pinned);
IntPtr susan = suhandle.AddrOfPinnedObject(); System.Threading.Tasks.Parallel.For(, height - , (offsetY) =>
{
for (int offsetX = ; offsetX < width - ; offsetX++)
{
OneSusan(offsetY, offsetX, (byte*)src, (byte*)dst, stride);
}
}); Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height); BitmapData resultData = resultBitmap.LockBits(new Rectangle(, ,
resultBitmap.Width, resultBitmap.Height),
ImageLockMode.WriteOnly,
PixelFormat.Format32bppArgb); Marshal.Copy(resultBuffer, , resultData.Scan0, resultBuffer.Length);
resultBitmap.UnlockBits(resultData); return resultBitmap; }
public unsafe static void OneSusan(int offsetY, int offsetX, byte* src, byte* dst, int stride)
{
int[] rowRadius = new int[] { , , , , , , };
int dThreshold = ; src = (byte*)((int)src + stride * offsetY + offsetX * );
dst = (byte*)((int)dst + stride * offsetY + offsetX * );
byte nucleusValue = *src;
int usan = ; int cx = , cy = ;
float vX = , vY = , vXY = ;
for (int i = -; i <= ; i++)
{ int r = rowRadius[i + ]; byte* ptr = (byte*)((int)src + stride * i); for (int j = -r; j <= r; j++)
{
int c = (int)Math.Exp(-Math.Pow((System.Math.Abs(nucleusValue - ptr[j * ]) / dThreshold), ));
usan += c;
cx += j * c;
cy += i * c;
vX += j * j * c;
vY += i * i * c;
vXY += i * j * c;
}
}
if (usan < )
usan = - usan;
else
usan = ;
if ((usan < ) && (cx != || cy != ))
{
*dst = ;
dst[] = ;
dst[] = ;
dst[] = ;
}
else
{
*dst = ;
dst[] = ;
dst[] = ;
dst[] = ;
}
}

示例下载(除Susan 方法之外的代码来自https://softwarebydefault.com/2013/05/11/image-edge-detection/)

C# Susan边缘检测(Susan Edge Detection)的更多相关文章

  1. 计算机视觉中的边缘检测Edge Detection in Computer Vision

    计算机视觉中的边缘检测   边缘检测是计算机视觉中最重要的概念之一.这是一个很直观的概念,在一个图像上运行图像检测应该只输出边缘,与素描比较相似.我的目标不仅是清晰地解释边缘检测是怎样工作的,同时也提 ...

  2. 【数字图像分析】基于Python实现 Canny Edge Detection(Canny 边缘检测算法)

    Canny 边缘检测算法 Steps: 高斯滤波平滑 计算梯度大小和方向 非极大值抑制 双阈值检测和连接 代码结构: Canny Edge Detection | Gaussian_Smoothing ...

  3. Image Processing and Analysis_8_Edge Detection:Edge Detection Revisited ——2004

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  4. Edge detection using LoG

    intensity梯度值分布跟图片的大小有关, 比如将一张小图片放大后会变得很模糊, 原先清晰的edge, 即大的梯度值变得模糊. 但是原有的边缘通常还是肉眼可分辨的. 但用Sobel 算子可能就检测 ...

  5. Image Processing and Analysis_21_Scale Space:Edge Detection and Ridge Detection with Automatic Scale Selection——1998

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  6. Image Processing and Analysis_8_Edge Detection:Local Scale Control for Edge Detection and Blur Estimation——1998

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  7. Image Processing and Analysis_8_Edge Detection: Optimal edge detection in two-dimensional images ——1996

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  8. Image Processing and Analysis_8_Edge Detection:Multiresolution edge detection techniques ——1995

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  9. Image Processing and Analysis_8_Edge Detection:Scale-space and edge detection using anisotropic diffusion——1990

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

随机推荐

  1. 软件工程练习, 模块化,单元测试,回归测试,TDD

    这是<构建之法>实战教学的一部分.适合作为同学们的第二个程序作业. 第一个程序作业: 请看 “概论” 一章的练习,或者老师的题目,例如这个. 作业要求: 软件工程的作业越来越有意思了, 我 ...

  2. 9.7 js进阶总结2

    数组元素添加 将一个或多个新元素添加到数组结尾,并返回数组新长度 var week_len = week.push(‘星期四’,‘星期五’); 将一个或多个新元素添加到数组开始,数组中的元素自动后移, ...

  3. 【工作笔记】BAT批处理学习笔记与示例

    BAT批处理学习笔记 一.批注里定义:批处理文件是将一系列命令按一定的顺序集合为一个可执行的文本文件,其扩展名为BAT或者CMD,这些命令统称批处理命令. 二.常见的批处理指令: 命令清单: 1.RE ...

  4. Comet4J推技术在SSHE三大框架中应用-linux下亲测可用

    Comet4J(Comet for Java)是一个纯粹基于AJAX(XMLHTTPRequest)的服务器推送框架,消息以JSON方式传递,具备长轮询.长连接.自动选择三种工作模式. 下载地址 co ...

  5. 采用css实现流动的边框

    问题起缘一个曾经做过的项目, 类似excel那样, 选中单元格并复制或粘贴时有个边框流动的效果, like this: 在前端要作出这种效果可能方法并不少, 不过我只想到了2种, 真边框与假边框, 真 ...

  6. Python爬虫个人梳理(代码有空写)

    这里多是摘抄的,只是用于个人理解. 1.urlopen().read()是爬取网页的内容,出来可能是一堆的源代码.和我们右击网页查看是一样的. 2.当用到http请求的时候,我们可以使用Request ...

  7. C语言 值传递和地址传递

    不少同学在学到C语言的指针部分时感到很困惑,对经常提到的"值传递"和"地址传递"两个概念弄不 明白.实际上,因为地址本身也可以作为一个特殊的"值&qu ...

  8. scrollview技巧

    一行 CGFloat buttonX = 0; CGFloat buttonY = 25; CGFloat buttonW = 37; CGFloat buttonH = 60; CGFloat ma ...

  9. Xilium.CefGlue CEF Chrome 自动上传文件不弹出对话框 CefDialogHandler

    关键代码如下,如何使用Handler,还不清楚的请继续搜索 internal sealed class WyzCefDialogHandler : CefDialogHandler    {      ...

  10. 通过jQuery Ajax使用FormData对象上传文件

    FormData对象,是可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest发送这个"表单". 在 Mozilla Developer 网站 使用For ...