<<一种基于δ函数的图象边缘检测算法>>一文算法的实现。

  原始论文下载: 一种基于δ函数的图象边缘检测算法

     这篇论文读起来感觉不像现在的很多论文,废话一大堆,而是直入主题,反倒使人觉得文章的前后跳跃有点大,不过算法的原理已经讲的清晰了。

    一、原理

     文中提出的边缘检测算法原理也不是特别复杂,使用了一个低通滤波函数以及一个高通滤波函数,其形式分别为:

                                            (1)

                  (2)

       当图像中的噪音比较少时,可以直接使用高通滤波器对图像进行滤波,得到图像的细节信息(即边缘处),论文中称之为D算法,计算公式如下:

    式中顶部的横线应该是表示开平方的意思。

       而当图像含有噪音时,则采用高通和低通滤波器结合方式,使用低通滤波器平滑图像中的噪音,高通滤波器检测边缘,这个原理则类似于高斯拉普拉斯边缘检测过程,论文中称之为C算法,计算公式如下:

       式中w表示的是窗口大小,取值越大,边缘的宽度越大,建议理想取值为2。

   上面两个式子都已经是离散化的表达方式了,因此实际上也是一种对图像的模板操作,只是模板中的因子需要随着参数的不同而改变。

       注意:D算法仅仅是一维的模板操作,而C算法是二维的。

二、代码

       下面贴出D算法的核心代码:

void EdgeDetail(byte* Src, byte* Dest, int Width, int Height, int Stride, int Radius = 2, double S = 1, double T = 3)
{
    int X, Y, I, J, XX, YY;
    byte* SrcP, DestP;
    int SumOne, SumTwo, Power;
    byte* SqrValue = (byte*)GlobalAlloc(GPTR, (256 * 256) * sizeof(byte));
    int* SpeedHigh = (int*)GlobalAlloc(GPTR, (Radius * 2 + 1) * sizeof(int));

    SpeedHigh += Radius;

    for (Y = 0; Y < 256 * 256; Y++) SqrValue[Y] = (byte)Math.Sqrt(Y);

    for (Y = -Radius; Y <= Radius; Y++)
    {
        if (Y == 0)
            SpeedHigh[Y] = 0;
        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) / (2 * T * T))) * 1024);
    }
    for (Y = 0; Y < Height; Y++)
    {
        DestP = Dest + Y * Stride;
        for (X = 0; X < Width; X++)
        {
            SumOne = 0; SumTwo = 0;
            for (J = -Radius; J <= Radius; J++)
            {
                XX = X + J;
                if (XX < 0) XX = 0; else if (XX >= Width) XX = Width - 1;
                SrcP = Src + Stride * Y + XX;
                SumOne += (SpeedHigh[J] * SrcP[0]) >> 10;
                YY = Y + J;
                if (YY < 0) YY = 0; else if (YY >= Height) YY = Height - 1;
                SrcP = Src + Stride * YY + X;
                SumTwo += (SpeedHigh[J] * SrcP[0]) >> 10;
            }
            Power = SumOne * SumOne + SumTwo * SumTwo;
            if (Power > 65025) Power = 65025;
            DestP[0] = 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 = 2, double S0 = 0.3, double T0 = 3, double S1 = 0.2, double T1 = 2)
{
    int X, Y, I, J, XX, YY;
    byte* SrcP, DestP;
    int SumOne, SumTwo, Power;
    int* SqrValue = (int*)GlobalAlloc(GPTR, (256 * 256) * sizeof(int));
    int* SpeedHigh = (int*)GlobalAlloc(GPTR, (Radius * 2 + 1) * sizeof(int));
    int* SpeedLow = (int*)GlobalAlloc(GPTR, (Radius * 2 + 1) * sizeof(int));

    SpeedHigh += Radius;
    SpeedLow += Radius;

    for (Y = 0; Y < 256 * 256; Y++) SqrValue[Y] = (int)Math.Sqrt(Y);

    for (Y = -Radius; Y <= Radius; Y++)
    {
        if (Y == 0)
        {
            SpeedHigh[Y] = 0;
            SpeedLow[Y] = 1024;
        }
        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) / (2 * T1 * T1))) * 1024);
            SpeedLow[Y] = (int)(((Math.Sin(S0 * Y) / (S0 * Y)) * Math.Exp(-((double)Y * Y) / (2 * T0 * T0))) * 1024);
        }
    }

    for (Y = 0; Y < Height; Y++)
    {
        DestP = Dest + Y * Stride;
        for (X = 0; X < Width; X++)
        {
            SumOne = 0; SumTwo = 0;
            for (J = -Radius; J <= Radius; J++)
            {
                YY = Y + J;
                if (YY < 0) YY = 0; else if (YY >= Height) YY = Height - 1;
                for (I = -Radius; I <= Radius; I++)
                {
                    XX = X + I;
                    if (XX < 0) XX = 0; else if (XX >= Width) XX = Width - 1;
                    SrcP = Src + Stride * YY + XX;
                    SumOne += (SpeedHigh[I] * SpeedLow[J] * SrcP[0]) >>20;
                    SumTwo += (SpeedLow[I] * SpeedHigh[J] * SrcP[0]) >>20;
                }
            }
            Power = SumOne * SumOne + SumTwo * SumTwo;
            if (Power > 65025) Power = 65025;
            DestP[0] = (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  转载请保留本行信息************************

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏人工智能

深入机器学习系列10-ALS

交换最小二乘 ? 1 什么是ALSALS是交替最小二乘(alternating least squares)的简称。在机器学习中,ALS特指使用交替最小二乘求解...

2136
来自专栏CDA数据分析师

数据挖掘150道试题 敢不敢来自测!

单选题 1. 某超市研究销售纪录数据后发现,买啤酒的人很大概率也会购买尿布,这种属于数据挖掘的哪类问题?(A) A. 关联规则发现 B. 聚类 C. 分类 ...

2019
来自专栏PPV课数据科学社区

【必看工具】可视化图表表达的10个错误。

数据可视化是一个沟通复杂信息的强大武器。通过可视化信息,我们的大脑能够更好地抓取和保存有效信息,增加信息的印象。但如果数据可视化做的较弱,反而会带来负面效果。错...

2746
来自专栏斑斓

初窥Bounded Context

Bounded Context(限界上下文)是DDD中最难解释的原则,但或许也是最重要的原则。可以说,没有Bounded Context,就不能做DDD。 Bo...

3198
来自专栏祝威廉

为什么去开发一个MLSQL

第一个,算法的着眼点是,用最快速的方式清洗一些数据出来,然后接着建模训练,评估预测效果,之后再重复清洗数据,再试验。因为很多算法工程师都是Python系的,对他...

782
来自专栏数据科学与人工智能

【应用】信用评分:第3部分 - 数据准备和探索性数据分析

因此,**数据准备是任何数据挖掘项目的关键方面,包括信用评分卡的开发。 **这是CRISP-DM周期中最具挑战性和耗时的阶段。 项目总时间中至少70%,有时多于...

831
来自专栏PPV课数据科学社区

【学习】用SPSS绘制质量控制图

控制图(Control Chart)又称管理图,它是用来区分是由异常原因引起的波动,还是由过程固有的原因引起的正常波动的一种有效的工具。控制图通过科学的区分正常...

2675
来自专栏腾讯高校合作

异质信息网络:一种新颖的网络建模与分析方法

异质信息网络被定义为一个有向图,它包含有多种类型的对象或者关系,每个对象属于一个特定的对象类型,每条关系属于一个特定的关系类型。

7957
来自专栏AI研习社

FAIR 开源 Tensor Comprehensions,让机器学习与数学运算高性能衔接

AI 研习社消息,Facebook AI 研究院于近日开源了 C++ 库及数学语言 Tensor Comprehensions,它能有效填补研究人员于数学运算领...

2638
来自专栏PPV课数据科学社区

【数据可视化】可视化图表表达的十个错误

数据可视化是一个沟通复杂信息的强大武器。通过可视化信息,我们的大脑能够更好地抓取和保存有效信息,增加信息的印象。但如果数据可视化做的较弱,反而会带来负面效果。错...

2527

扫码关注云+社区