<<一种基于δ函数的图象边缘检测算法>>一文算法的实现。
原始论文下载: 一种基于δ函数的图象边缘检测算法。
这篇论文读起来感觉不像现在的很多论文,废话一大堆,而是直入主题,反倒使人觉得文章的前后跳跃有点大,不过算法的原理已经讲的清晰了。
一、原理
文中提出的边缘检测算法原理也不是特别复杂,使用了一个低通滤波函数以及一个高通滤波函数,其形式分别为:
(1)
(2)
当图像中的噪音比较少时,可以直接使用高通滤波器对图像进行滤波,得到图像的细节信息(即边缘处),论文中称之为D算法,计算公式如下:
式中顶部的横线应该是表示开平方的意思。
而当图像含有噪音时,则采用高通和低通滤波器结合方式,使用低通滤波器平滑图像中的噪音,高通滤波器检测边缘,这个原理则类似于高斯拉普拉斯边缘检测过程,论文中称之为C算法,计算公式如下:
式中w表示的是窗口大小,取值越大,边缘的宽度越大,建议理想取值为2。
上面两个式子都已经是离散化的表达方式了,因此实际上也是一种对图像的模板操作,只是模板中的因子需要随着参数的不同而改变。
注意:D算法仅仅是一维的模板操作,而C算法是二维的。
二、代码
下面贴出D算法的核心代码:
void EdgeDetail(byte* Src, byte* Dest, int Width, int Height, int Stride, int Radius = , double S = , double T = )
{
int X, Y, I, J, XX, YY;
byte* SrcP, DestP;
int SumOne, SumTwo, Power;
byte* SqrValue = (byte*)GlobalAlloc(GPTR, ( * ) * sizeof(byte));
int* SpeedHigh = (int*)GlobalAlloc(GPTR, (Radius * + ) * sizeof(int)); SpeedHigh += Radius; for (Y = ; Y < * ; Y++) SqrValue[Y] = (byte)Math.Sqrt(Y); for (Y = -Radius; Y <= Radius; Y++)
{
if (Y == )
SpeedHigh[Y] = ;
else
SpeedHigh[Y] = (int)((((Math.Cos(S * Y) / Y) - (Math.Sin(S * Y) / S) * (1.0 / (Y * Y) + 1.0 / (T * T))) * Math.Exp(-((double)Y * Y) / ( * T * T))) * );
}
for (Y = ; Y < Height; Y++)
{
DestP = Dest + Y * Stride;
for (X = ; X < Width; X++)
{
SumOne = ; SumTwo = ;
for (J = -Radius; J <= Radius; J++)
{
XX = X + J;
if (XX < ) XX = ; else if (XX >= Width) XX = Width - ;
SrcP = Src + Stride * Y + XX;
SumOne += (SpeedHigh[J] * SrcP[]) >> ;
YY = Y + J;
if (YY < ) YY = ; else if (YY >= Height) YY = Height - ;
SrcP = Src + Stride * YY + X;
SumTwo += (SpeedHigh[J] * SrcP[]) >> ;
}
Power = SumOne * SumOne + SumTwo * SumTwo;
if (Power > ) Power = ;
DestP[] = SqrValue[Power];
DestP++;
}
}
SpeedHigh -= Radius;
GlobalFree((IntPtr)SqrValue);
GlobalFree((IntPtr)SpeedHigh);
}
如上所示,我采用了整数运算代替了浮点运算,主要目的是为了提高速度,当然这样做可能会牺牲一部分精度,由于从算法的必要性上讲,Radius不需要取得很大,因此,对于内部的二重循环来说,压力不是特大,因此没有做特殊的优化。而在超出边界处,直接采用的是使用边界元素值。
上述代码的内部循环里有一些计算式可以提取到外部来的, 只是为了算法的清晰性,未做优化,速度发烧友可以自行提取。
该算法各像素之间的计算式独立的,因此可以很简单的就实现并行计算。
而C算法的代码就稍微复杂一点:
void EdgeCoarse(byte* Src, byte* Dest, int Width, int Height, int Stride, int Radius = , double S0 = 0.3, double T0 = , double S1 = 0.2, double T1 = )
{
int X, Y, I, J, XX, YY;
byte* SrcP, DestP;
int SumOne, SumTwo, Power;
int* SqrValue = (int*)GlobalAlloc(GPTR, ( * ) * sizeof(int));
int* SpeedHigh = (int*)GlobalAlloc(GPTR, (Radius * + ) * sizeof(int));
int* SpeedLow = (int*)GlobalAlloc(GPTR, (Radius * + ) * sizeof(int)); SpeedHigh += Radius;
SpeedLow += Radius; for (Y = ; Y < * ; Y++) SqrValue[Y] = (int)Math.Sqrt(Y); for (Y = -Radius; Y <= Radius; Y++)
{
if (Y == )
{
SpeedHigh[Y] = ;
SpeedLow[Y] = ;
}
else
{
SpeedHigh[Y] = (int)((((Math.Cos(S1 * Y) / Y) - (Math.Sin(S1 * Y) / S1) * (1.0 / (Y * Y) + 1.0 / (T1 * T1))) * Math.Exp(-((double)Y * Y) / ( * T1 * T1))) * );
SpeedLow[Y] = (int)(((Math.Sin(S0 * Y) / (S0 * Y)) * Math.Exp(-((double)Y * Y) / ( * T0 * T0))) * );
}
} for (Y = ; Y < Height; Y++)
{
DestP = Dest + Y * Stride;
for (X = ; X < Width; X++)
{
SumOne = ; SumTwo = ;
for (J = -Radius; J <= Radius; J++)
{
YY = Y + J;
if (YY < ) YY = ; else if (YY >= Height) YY = Height - ;
for (I = -Radius; I <= Radius; I++)
{
XX = X + I;
if (XX < ) XX = ; else if (XX >= Width) XX = Width - ;
SrcP = Src + Stride * YY + XX;
SumOne += (SpeedHigh[I] * SpeedLow[J] * SrcP[]) >>;
SumTwo += (SpeedLow[I] * SpeedHigh[J] * SrcP[]) >>;
}
}
Power = SumOne * SumOne + SumTwo * SumTwo;
if (Power > ) Power = ;
DestP[] = (byte)SqrValue[Power];
DestP++;
}
}
SpeedHigh -= Radius;
SpeedLow -= Radius;
GlobalFree((IntPtr)SqrValue);
GlobalFree((IntPtr)SpeedHigh);
GlobalFree((IntPtr)SpeedLow); }
我个人不怎么喜欢用C#的数组,这也是从性能角度考虑的,我喜欢直接操作指针。这个可以根据每个人自己的习惯修改吧。
相信能看懂原理的朋友对于代码部分的理解也应该很容易,这里不做多解释。
三、效果
c算法的结果
原图 Radius=2,S=3.14,T=1 Radius=2,S=1.57,T=1
D算法:
原图 Radius=2,S0 = 0.3, T0 = 3, S1 = 0.2, T1 = 2 Radius=2,S0 = 3, T0 = 3, S1 = 2, T1 = 2
可见,这个算法要取得比较好的效果,是需要调整S/T这些参数,关于这些参数的取值意向,可以参考原文中的一些描述。
这个工程比较简单,附上C#的程序:http://files.cnblogs.com/Imageshop/EdgeDetectUseDeltaFunction.rar
*********************************作者: laviewpbt 时间: 2013.10.26 联系QQ: 33184777 转载请保留本行信息************************
<<一种基于δ函数的图象边缘检测算法>>一文算法的实现。的更多相关文章
- 一种可实时处理 O(1)复杂度图像去雾算法的实现。
在我博文的一系列的文章,有不少算法都于去雾有关,比如限制对比度自适应直方图均衡化算法原理.实现及效果.局部自适应自动色阶/对比度算法在图像增强上的应用这两个增强算法都有一定的去雾能力,而最直接的就是& ...
- 基于思岚A1激光雷达+OpenGL+VS2017的Ramer-Douglas-Peucker算法的实现
时隔两年 又借到了之前的那个激光雷达,最老版本的思岚A1,甚至不支持新的固件,并且转接板也不见了,看了下淘宝店卖¥80,但是官方提供了一个基于STM32的实现方式,于是我估摸着这个转接板只是一个普通的 ...
- 图中最短路径算法(Dijkstra算法)(转)
1.Dijkstra 1) 适用条件&范围: a) 单源最短路径(从源点s到其它所有顶点v); b) 有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E ...
- 腾讯优图&港科大提出一种基于深度学习的非光流 HDR 成像方法
目前最好的高动态范围(HDR)成像方法通常是先利用光流将输入图像对齐,随后再合成 HDR 图像.然而由于输入图像存在遮挡和较大运动,这种方法生成的图像仍然有很多缺陷.最近,腾讯优图和香港科技大学的研究 ...
- Canny边缘检测算法(基于OpenCV的Java实现)
目录 Canny边缘检测算法(基于OpenCV的Java实现) 绪论 Canny边缘检测算法的发展历史 Canny边缘检测算法的处理流程 用高斯滤波器平滑图像 彩色RGB图像转换为灰度图像 一维,二维 ...
- Hive数据分析——Spark是一种基于rdd(弹性数据集)的内存分布式并行处理框架,比于Hadoop将大量的中间结果写入HDFS,Spark避免了中间结果的持久化
转自:http://blog.csdn.net/wh_springer/article/details/51842496 近十年来,随着Hadoop生态系统的不断完善,Hadoop早已成为大数据事实上 ...
- python_mmdt:一种基于敏感哈希生成特征向量的python库(一)
概述 python_mmdt是一种基于敏感哈希的特征向量生成工具.核心算法使用C实现,提高程序执行效率.同时使用python进行封装,方便研究人员使用. 本篇幅主要介绍涉及的相关基本内容与使用,相关内 ...
- LM-MLC 一种基于完型填空的多标签分类算法
LM-MLC 一种基于完型填空的多标签分类算法 1 前言 本文主要介绍本人在全球人工智能技术创新大赛[赛道一]设计的一种基于完型填空(模板)的多标签分类算法:LM-MLC,该算法拟合能力很强能感知标签 ...
- Qt——信号槽连接:基于字符串与基于函数的连接之间的不同
从Qt5.0开始,Qt提供了两种不同的方式进行信号槽的连接:基于 字符串 的连接语法.基于 函数 的连接语法.这两种语法各有利弊,下面对它们的不同点进行总结. 以下几部分详细解释了它们之间的不同,并说 ...
随机推荐
- node.js操作mysql数据库之增删改查
安装mysql模块 npm install mysql 数据库准备 mysql server所在的机器IP地址是192.168.0.108,登录账户就用root@123456 在mysql中创建tes ...
- [Asp.net 5] Logging-新日志系统目录
楼主有个美好的愿望——把asp.net 5所有能看懂的代码一一呈现给大家(比如C++,楼主就看不懂).现在已经做完了依赖注入.多语言.配置文件三部分,比较基础的日志就成为了楼主的下一个目标.下面是楼主 ...
- [转]C#中的string.Format()的JS版本
String.prototype.format = function (args) { var result = this; if (arguments.length > 0) { var re ...
- 尝试加载 Oracle 客户端库时引发 BadImageFormatException
尝试加载 Oracle 客户端库时引发 BadImageFormatException 工程师给计算机诊断,就像医生给病人诊断一样,很多同样的症状,可能是由多种截然不同的原因导致的. 最近进行C# ...
- python之网络编程
本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用 ...
- java web学习总结(十) -------------------HttpServletRequest对象
一.HttpServletRequest介绍 HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象 ...
- 事件流之事件冒泡与事件捕获<JavaScript高级程序设计>学习笔记
1.事件流 浏览器开发团队遇到一个很有意思问题:页面的那一部分会拥有特定的事件? 对于理解这个问题您可以想象画在一张纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的其实不是一个圆,而是纸上 ...
- 单行文字滚动就用myslider
单行文字滚动就用myslider,myslider是一个小型的内容滚动jquery插件. 首先请看实例:http://keleyi.com/jq/myslider/demo/4.htm 然后来看代码: ...
- Bootstrap栅格布局系统的特点
栅格布局系统的特点: (1)所有的行必须放在容器中: .container或.container-fluid (2)分为多行(row),一行中平均分为12列(col) (3)网页内容只能放在列(col ...
- 网络分析之Pgrouting(转载)
网上关于Pgrouting的使用介绍太简单了,这里想详细的总结一下Pgrouting的使用,其实主要参照官方文档:http://workshop.pgrouting.org/ 第一步:配置环境 关于P ...