Canny边缘检测算法的兑现。Canny边缘检测算法的贯彻。

图像边缘信息主要集中在胜频段,通常说图像锐化或检测边缘,实质就是是强频滤波。我们清楚微分运算是求信号的变化率,具有增强高频分量的意。在空白运算被的话,对图像的锐化就是计算微分。由于数字图像的离散信号,微分运算就成计算差分或梯度。图像处理面临生出多边缘检测(梯度)算子,常用的席卷一般一阶差分,Robert算子(交叉差分),Sobel算子等等,是根据寻找梯度强度。拉普拉斯算子(二阶差细分)是基于过零点检测。通过测算梯度,设置阀值,得到边缘图像。

图像边缘信息主要集中在高频段,通常说图像锐化或检测边缘,实质就是是强频滤波。我们解微分运算是请信号的变化率,具有增强高频分量的图。在空运算被的话,对图像的锐化就是计算微分。由于数字图像的离散信号,微分运算就成计算差分或梯度。图像处理面临起多种边缘检测(梯度)算子,常用的不外乎普通一阶差分,Robert算子(交叉差分),Sobel算子等等,是依据寻找梯度强度。拉普拉斯算子(二阶差区划)是基于过零点检测。通过计算梯度,设置阀值,得到边缘图像。

Canny边缘检测算子是均等种多级检测算法。1986年由John
F. Canny提出,同时提出了边缘检测的老三很则:

Canny边缘检测算子是同一栽多级检测算法。1986年出于John
F. Canny提出,同时提出了边缘检测的老三老则:

  1. 亚错误率的边缘检测:检测算法应该规范地找到图像中之尽心多之边缘,尽可能的减少漏检和误检。
  2. 顶良好定位:检测的边缘点应该规范地稳住于边缘之中心。
  3. 图像中的妄动边缘应该只是于记一坏,同时图像噪声不应允发伪边缘。
  1. 没有错误率的边缘检测:检测算法应该规范地找到图像中的玩命多的边缘,尽可能的削减漏检和误检。
  2. 最美妙定位:检测的边缘点应该规范地稳住于边缘的主干。
  3. 图像被之随机边缘应该只被记一不善,同时图像噪声不应允发伪边缘。

Canny算法出现以后一直是用作同一种标准的边缘检测算法,此后也油然而生了各种基于Canny算法的改进算法。时至今日,Canny算法及其各种变种依旧是平等栽优质的边缘检测算法。而且只有前提条件很抱,你老麻烦找到平种边缘检测算子能一目了然地于Canny算子做的重好。

Canny算法出现之后一直是作为同一种标准的边缘检测算法,此后吗出现了各种基于Canny算法的改善算法。时至今日,Canny算法及其各种变种依旧是一致栽名特新优精的边缘检测算法。而且只有前提条件很吻合,你很麻烦找到平种边缘检测算子能显地于Canny算子做的更好。

至于各种差分算子,还有Canny算子的简练介绍,这里就是非罗嗦了,网上还好找得及。直接入Canny算法的落实。Canny算法分为几步。

有关各种差分算子,还有Canny算子的简短介绍,这里虽未罗嗦了,网上都得搜寻得及。直接入Canny算法的实现。Canny算法分为几步。

  1. 高斯模糊。
  1. 高斯模糊。

即无异步很简短,类似于LoG算子(Laplacian of
Gaussian)作高斯歪曲一样,主要意图就是是去除噪声。因为噪音也集中为数信号,很爱为识别为非官方边缘。应用高斯歪曲去除噪声,降低伪边缘的甄别。但是由图像边缘信息吗是累信号,高斯模糊的半径选择大重点,过怪的半径很轻让有些毙命边缘检测不交。

旋即同步很简单,类似于LoG算子(Laplacian of
Gaussian)作高斯歪曲一样,主要意图就是是剔除噪声。因为噪音也集中让数信号,很轻给识别为暗边缘。应用高斯歪曲去除噪声,降低伪边缘的鉴别。但是由于图像边缘信息为是多次信号,高斯模糊的半径选择十分重大,过十分的半径很易吃部分闭眼边缘检测不顶。

图片 1  
图片 2

图片 3  
图片 4

            
Lena原图                                      
Lena高斯歪曲,半径2

            
Lena原图                                      
Lena高斯歪曲,半径2

  1. 测算梯度幅值和大势。
  1. 算算梯度幅值和样子。

图像的边缘可以针对不同方向,因此经典Canny算法用了季独梯度算子来分别计水平,垂直和对角线方向的梯度。但是平常还毫无四个梯度算子来分别计算四只样子。常用的边缘差分算子(如Rober,Prewitt,Sobel)计算水平和直方向的不比分Gx和Gy。这样即便得如下计算梯度模和大势:

图像的边缘可以针对不同方向,因此经典Canny算法用了季单梯度算子来分别计水平,垂直和对角线方向的梯度。但是平常还休想四个梯度算子来分别计四单样子。常用的边缘差分算子(如Rober,Prewitt,Sobel)计算水平以及直方向的不比分Gx和Gy。这样虽足以如下计算梯度模以及趋势:

图片 5

图片 6

梯度角度θ范围由弧度-π到π,然后将它相仿到四只样子,分别代表水平,垂直和片独针对角线方向(0°,45°,90°,135°)。可以坐±iπ/8(i=1,3,5,7)分割,落于每个区域之梯度角给一个特定值,代表四独方向之一。

梯度角度θ范围从弧度-π到π,然后把它们仿佛到四单方向,分别表示水平,垂直和少只对角线方向(0°,45°,90°,135°)。可以坐±iπ/8(i=1,3,5,7)分割,落于每个区域的梯度角给一个一定值,代表四只趋势有。

此自己选择Sobel算子计算梯度。Sobel算法很简短,到处都得以找到,就无排有代码来了。相对于任何边缘算子,Sobel算子得出去的边缘粗大明亮。

这里自己选择Sobel算子计算梯度。Sobel算法很简短,到处都得以找到,就不排有代码来了。相对于其它边缘算子,Sobel算子得出去的边缘粗大明亮。

图片 7

图片 8

 

 

 

 

 

 

下图是针对上面半径2之高斯模糊图像L通道(HSL)应用Sobel算子的梯度模图,没有施加任何阀值。

下图是针对性上面半径2之高斯模糊图像L通道(HSL)应用Sobel算子的梯度模图,没有施加任何阀值。

图片 9

图片 10

           Sobel算子,无阀值

           Sobel算子,无阀值

  1. 莫最深价值抑制。
  1. 切莫最酷价值抑制。

未最老价值抑制是如出一辙栽边缘细化措施。通常得出来的梯度边缘不止一个如素宽,而是多只像素宽。就像咱所说Sobel算子得出来的边缘粗大而知,从者Lena图的Sobel结果可以看得出来。因此这样的梯度图还是异常“模糊”。而轨道3渴求,边缘就发生一个可靠的触发小幅。非最充分价值抑制能协助保留部分最要命梯度而杀有所其他梯度值。这意味着只有保留了梯度转移中最为尖锐的位置。算法如下:

莫最老价值抑制是一样种边缘细化措施。通常得下的梯度边缘不止一个诸如素宽,而是多只像素宽。就如咱所说Sobel算子得下的边缘粗大而解,从者Lena图的Sobel结果可以看得出来。因此这样的梯度图还是怪“模糊”。而轨道3要求,边缘就生一个纯正的触发小幅。非最特别价值抑制能帮助保留有最充分梯度而杀有所其他梯度值。这意味着只有保留了梯度转移备受极其尖锐的位置。算法如下:

  1. 较时触及的梯度强度和初梯度方向点之梯度强度。
  2. 假定手上点的梯度强度和同方向的别接触之梯度强度相较是极致深,保留其值。否则抑制,即设为0。比如当前接触的趋向指向正上方90°方向,那它们用与垂直方向,它的正上方和正下方的像素比较。
  1. 正如时触及的梯度强度和冠梯度方向点之梯度强度。
  2. 倘手上点的梯度强度及同方向的另外接触的梯度强度相较是最好老,保留其值。否则抑制,即设为0。比如当前接触的取向指向正上方90°方向,那它们用以及垂直方向,它的正上方和正下方的像素比较。

瞩目,方向的冠是不起作用的,比如东南方向及西北方向是同等的,都以为是对角线的一个样子。前面我们将梯度方向近似到水平,垂直和个别独针对角线四独方向,所以每个像素根据自家方向在当时四单趋势有进行比,决定是否保留。这同样有些的代码也大粗略,列有如下。pModule,pDirection分别记录了达标等同步梯度模值和梯度方向。

小心,方向的头是不起作用的,比如东南方向以及西北方向是一模一样的,都认为是针对角线的一个势。前面我们将梯度方向近似到水平,垂直和简单个对角线四个趋势,所以每个像素根据本人方向在马上四只样子之一进行比,决定是否保留。这同有的代码也颇简短,列有如下。pModule,pDirection分别记录了达标等同步梯度模值和梯度方向。

图片 11图片 12

图片 13图片 14

pmoddrow = pModule + Width + 1; 
pdirdrow = pDirection + Width + 1;
pstrongdrow = pStrong + Width + 1;
for (i = 1; i < Hend - 1; i++)
{
  pstrongd = pstrongdrow;
  pmodd = pmoddrow;
  pdird = pdirdrow;
  for (j = 1; j < Wend - 1; j++)
    {
            switch (*pdird)
            {
            case 0:        // x direction
            case 4:
                if (*pmodd > *(pmodd - 1) && *pmodd > *(pmodd + 1))
                    *pstrongd = 255;
                break;
            case 1:        // northeast-southwest direction. Notice the data order on y direction of bmp data
            case 5:
                if (*pmodd > *(pmodd + Width + 1) && *pmodd > *(pmodd - Width - 1))
                    *pstrongd = 255;
                break;
            case 2:        // y direction
            case 6:
                if (*pmodd > *(pmodd - Width) && *pmodd > *(pmodd + Width))
                    *pstrongd = 255;
                break;
            case 3:        // northwest-southeast direction. Notice the data order on y direction of bmp data
            case 7:
                if (*pmodd > *(pmodd + Width - 1) && *pmodd > *(pmodd - Width + 1))
                    *pstrongd = 255;
                break;
            default:
                ASSERT(0);
                break;
            }
            pstrongd++;
            pmodd++;
            pdird++;
    }
    pstrongdrow += Width;
    pmoddrow += Width;
    pdirdrow += Width;
}
pmoddrow = pModule + Width + 1; 
pdirdrow = pDirection + Width + 1;
pstrongdrow = pStrong + Width + 1;
for (i = 1; i < Hend - 1; i++)
{
  pstrongd = pstrongdrow;
  pmodd = pmoddrow;
  pdird = pdirdrow;
  for (j = 1; j < Wend - 1; j++)
    {
            switch (*pdird)
            {
            case 0:        // x direction
            case 4:
                if (*pmodd > *(pmodd - 1) && *pmodd > *(pmodd + 1))
                    *pstrongd = 255;
                break;
            case 1:        // northeast-southwest direction. Notice the data order on y direction of bmp data
            case 5:
                if (*pmodd > *(pmodd + Width + 1) && *pmodd > *(pmodd - Width - 1))
                    *pstrongd = 255;
                break;
            case 2:        // y direction
            case 6:
                if (*pmodd > *(pmodd - Width) && *pmodd > *(pmodd + Width))
                    *pstrongd = 255;
                break;
            case 3:        // northwest-southeast direction. Notice the data order on y direction of bmp data
            case 7:
                if (*pmodd > *(pmodd + Width - 1) && *pmodd > *(pmodd - Width + 1))
                    *pstrongd = 255;
                break;
            default:
                ASSERT(0);
                break;
            }
            pstrongd++;
            pmodd++;
            pdird++;
    }
    pstrongdrow += Width;
    pmoddrow += Width;
    pdirdrow += Width;
}

View
Code

View
Code

下图是无最要命价值抑制的结果。可见边缘宽度已经大大压缩。但是这个图像被以没应用任何阀值,还含有大量有点梯度模值的接触,也就算是祈求被酷糊涂的地方。下面,阀值要登台了。

生图是休最深价值抑制的结果。可见边缘宽度已经大大减缩。但是这个图像中坐无使用任何阀值,还富含大量稍稍梯度模值的触及,也就是图中老糊涂的地方。下面,阀值要出场了。

图片 15

图片 16

             非极其要命价值抑制结果

             非极端老价值抑制结果

  1. 双阀值。
  1. 双阀值。

相似的边缘检测算法用一个阀值来滤除噪声或颜料变化引起的多少之梯度值,而保留生之梯度值。Canny算法应用对阀门值,即一个高阀值和一个低阀值来分别边缘像素。如果边缘像素点梯度值大于高阀值,则为当是强边缘点。如果边缘梯度值仅次于高阀值,大于低阀值,则标记为弱边缘点。小于没有阀值的触及则受压掉。这等同步算法很简短。

相似的边缘检测算法用一个阀值来滤除噪声或颜料变化引起的有点的梯度值,而保留生之梯度值。Canny算法应用对阀门值,即一个高阀值和一个低阀值来分别边缘像素。如果边缘像素点梯度值大于高阀值,则为看是强边缘点。如果边缘梯度值小于高阀值,大于低阀值,则标记为弱边缘点。小于没有阀值的触发则受制止掉。这同一步算法很粗略。

  1. 落后边界跟踪。
  1. 落后边界跟踪。

至今,强边缘点可以认为是确实边缘。弱边缘点则可能是的确边缘,也或是噪声或颜色变化引起的。为获取规范的结果,后者引起的弱边缘点应该去丢。通常认为实际边缘引起的弱边缘点和强边缘点是属的,而与此同时噪声引起的弱边缘点则无会见。所谓的向下边界跟踪算法检查一个弱边缘点的8并通领域像素,只要有强边缘点存在,那么是弱边缘点被当是真是边缘保留下去。

由来,强边缘点可以当是真正边缘。弱边缘点则恐是真边缘,也恐怕是噪音或颜料变化引起的。为取得可靠的结果,后者引起的弱边缘点应该去丢。通常认为实际边缘引起的弱边缘点和强边缘点是接的,而以噪声引起的弱边缘点则免见面。所谓的落伍边界跟踪算法检查一个弱边缘点的8连通领域像素,只要来强边缘点存在,那么这弱边缘点被看是确实是边缘保留下。

夫算法搜索所有连接的弱边缘,如果相同长长的连接的弱边缘的别一个接触及强边缘点连通,则保留这长长的死亡边缘,否则抑制这漫长死亡边缘。搜索时可用广度优先或深优先算法,我于这里实现了应该是太轻之纵深优先算法。一差并过渡同样久边缘的深度优先算法如下:

这个算法搜索所有接的弱边缘,如果同漫长连接的弱边缘的外一个沾及强边缘点连通,则保留这条死亡边缘,否则抑制这长达死亡边缘。搜索时方可据此广度优先或深优先算法,我当这边实现了应当是极轻的吃水优先算法。一蹩脚并过渡同样长边缘之深浅优先算法如下:

  1. 未雨绸缪一个栈s,一个排q,设联通指示变量connected为假。从图像的率先只点起,进入2。
  2. 假如这点是弱边界点并且没有给标记,把其标志,并将它们作为第一个要素放入栈s中,同时把它放入记录连通曲线之行q,进入3。如果此点不是去世边界或都深受记了,到图像的下一个接触,重复2。
  3. 自栈s中取出一个要素,查找它的8像素领域。如果一个领域像素是死边界又没有为记了,把此领域如从标记,并进入栈s中,同时加入队列q。同时搜寻领域对应的强边界图,如果出一个像素是青出于蓝边界,表示这漫长死亡边界曲线和赛边界联通,设置connected为确实。重复3直到栈中没有元素了。如果connected为假,则相继从队列q中取出每个元素,清空标记。如果connected为确实,保留标记。
  4. 清空队列q,设置connected为假,移动至图像的生一个接触,到2。
  1. 预备一个栈s,一个行q,设联通指示变量connected为假。从图像的第一个点开始,进入2。
  2. 万一是点是弱边界点并且没有被标记,把它标志,并拿她当作第一只元素放入栈s中,同时把其放入记录连通曲线之班q,进入3。如果这个点不是物化边界或曾于记了,到图像的生一个点,重复2。
  3. 从栈s中取出一个素,查找它的8像素领域。如果一个天地像素是已故边界又没有给标记了,把这个世界如从标记,并加入栈s中,同时加入队列q。同时招来领域对应的强边界图,如果产生一个像素是大边界,表示即长长的死亡边界曲线以及大边界联通,设置connected为真。重复3简直到栈中没有元素了。如果connected为假,则相继从队列q中取出每个元素,清空标记。如果connected为实在,保留标记。
  4. 清空队列q,设置connected为假,移动到图像的生一个接触,到2。

图片 17图片 18

图片 19图片 20

// 5. Edge tracking by hysteresis
    stack<CPoint> s;
    queue<CPoint> q;
    BOOL connected = FALSE;
    long row_idx = Width;
    for (i = 1; i < Height - 1; i++, row_idx += Width)
    {
        for (j = 1; j < Width - 1; j++)
        {
            pweakd = pWeak + row_idx + j;
            if (*pweakd == 255)
            {
                s.push(CPoint(j, i));
                q.push(CPoint(j, i));
                *pweakd = 1;        // Label it

                while (!s.empty())
                {
                    CPoint p = s.top();
                    s.pop();
                    // Search weak edge 8-point neighborhood
                    pweakd = pWeak + p.y*Width + p.x;
                    if (*(pweakd - Width - 1) == 255)
                    {
                        CPoint np = CPoint(p.x - 1, p.y - 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd - Width - 1) = 1;        // Label it
                    }
                    if (*(pweakd - Width) == 255)
                    {
                        CPoint np = CPoint(p.x, p.y - 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd - Width) = 1;        // Label it
                    }
                    if (*(pweakd - Width + 1) == 255)
                    {
                        CPoint np = CPoint(p.x + 1, p.y - 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd - Width + 1) = 1;        // Label it
                    }
                    if (*(pweakd - 1) == 255)
                    {
                        CPoint np = CPoint(p.x - 1, p.y);
                        s.push(np);
                        q.push(np);
                        *(pweakd - 1) = 1;        // Label it
                    }
                    if (*(pweakd + 1) == 255)
                    {
                        CPoint np = CPoint(p.x + 1, p.y);
                        s.push(np);
                        q.push(np);
                        *(pweakd + 1) = 1;        // Label it
                    }
                    if (*(pweakd + Width - 1) == 255)
                    {
                        CPoint np = CPoint(p.x - 1, p.y + 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd + Width - 1) = 1;        // Label it
                    }
                    if (*(pweakd + Width) == 255)
                    {
                        CPoint np = CPoint(p.x, p.y + 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd + Width) = 1;        // Label it
                    }
                    if (*(pweakd + Width + 1) == 255)
                    {
                        CPoint np = CPoint(p.x + 1, p.y + 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd + Width + 1) = 1;        // Label it
                    }
                    // Search strong edge 8-point neighborhood
                    if (connected == FALSE)
                    {
                        pstrongd = pStrong + p.y*Width + p.x;
                        for (int m = -1; m <= 1; m++)
                        {
                            for (int n = -1; n <= 1; n++)
                            {
                                if (*(pstrongd + m*Width + n) == 255)
                                {
                                    connected = TRUE;
                                    goto next;
                                }
                            }
                        }
                    }
                next:
                    continue;
                }
                // No more element in the stack
                if (connected == FALSE)
                {
                    // The weak edge is not connected to any strong edge. Suppress it.
                    while (!q.empty())
                    {
                        CPoint p = q.front();
                        q.pop();
                        pWeak[p.y*Width + p.x] = 0;
                    }
                }
                else
                {
                    // Clean the queue
                    while (!q.empty()) q.pop();
                    connected = FALSE;
                }
            }
        }
    }
    // Add the connected weak edges (labeled) into strong edge image.
    // All strong edge pixels are labeled 255, otherwise 0.
    for (i = 0; i < len; i++)
    {
        if (pWeak[i] == 1) pStrong[i] = 255;
    }
// 5. Edge tracking by hysteresis
    stack<CPoint> s;
    queue<CPoint> q;
    BOOL connected = FALSE;
    long row_idx = Width;
    for (i = 1; i < Height - 1; i++, row_idx += Width)
    {
        for (j = 1; j < Width - 1; j++)
        {
            pweakd = pWeak + row_idx + j;
            if (*pweakd == 255)
            {
                s.push(CPoint(j, i));
                q.push(CPoint(j, i));
                *pweakd = 1;        // Label it

                while (!s.empty())
                {
                    CPoint p = s.top();
                    s.pop();
                    // Search weak edge 8-point neighborhood
                    pweakd = pWeak + p.y*Width + p.x;
                    if (*(pweakd - Width - 1) == 255)
                    {
                        CPoint np = CPoint(p.x - 1, p.y - 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd - Width - 1) = 1;        // Label it
                    }
                    if (*(pweakd - Width) == 255)
                    {
                        CPoint np = CPoint(p.x, p.y - 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd - Width) = 1;        // Label it
                    }
                    if (*(pweakd - Width + 1) == 255)
                    {
                        CPoint np = CPoint(p.x + 1, p.y - 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd - Width + 1) = 1;        // Label it
                    }
                    if (*(pweakd - 1) == 255)
                    {
                        CPoint np = CPoint(p.x - 1, p.y);
                        s.push(np);
                        q.push(np);
                        *(pweakd - 1) = 1;        // Label it
                    }
                    if (*(pweakd + 1) == 255)
                    {
                        CPoint np = CPoint(p.x + 1, p.y);
                        s.push(np);
                        q.push(np);
                        *(pweakd + 1) = 1;        // Label it
                    }
                    if (*(pweakd + Width - 1) == 255)
                    {
                        CPoint np = CPoint(p.x - 1, p.y + 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd + Width - 1) = 1;        // Label it
                    }
                    if (*(pweakd + Width) == 255)
                    {
                        CPoint np = CPoint(p.x, p.y + 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd + Width) = 1;        // Label it
                    }
                    if (*(pweakd + Width + 1) == 255)
                    {
                        CPoint np = CPoint(p.x + 1, p.y + 1);
                        s.push(np);
                        q.push(np);
                        *(pweakd + Width + 1) = 1;        // Label it
                    }
                    // Search strong edge 8-point neighborhood
                    if (connected == FALSE)
                    {
                        pstrongd = pStrong + p.y*Width + p.x;
                        for (int m = -1; m <= 1; m++)
                        {
                            for (int n = -1; n <= 1; n++)
                            {
                                if (*(pstrongd + m*Width + n) == 255)
                                {
                                    connected = TRUE;
                                    goto next;
                                }
                            }
                        }
                    }
                next:
                    continue;
                }
                // No more element in the stack
                if (connected == FALSE)
                {
                    // The weak edge is not connected to any strong edge. Suppress it.
                    while (!q.empty())
                    {
                        CPoint p = q.front();
                        q.pop();
                        pWeak[p.y*Width + p.x] = 0;
                    }
                }
                else
                {
                    // Clean the queue
                    while (!q.empty()) q.pop();
                    connected = FALSE;
                }
            }
        }
    }
    // Add the connected weak edges (labeled) into strong edge image.
    // All strong edge pixels are labeled 255, otherwise 0.
    for (i = 0; i < len; i++)
    {
        if (pWeak[i] == 1) pStrong[i] = 255;
    }

View
Code

View
Code

脚是本着Lena图计算Canny边缘检测的梯度模图和二值化图,高斯半径2,高阀值100,低阀值50。

下是对准Lena图计算Canny边缘检测的梯度模图和二值化图,高斯半径2,高阀值100,低阀值50。

图片 21  
图片 22

图片 23  
图片 24

            
Canny检测梯度模图                        Canny检测梯度二价值图

            
Canny检测梯度模图                        Canny检测梯度二价值图

用作对比,下面是因此相同阶差分与Sobel算子对原来图计算的结果,阀值100。由于一阶差分的梯度值相对比小,我对一阶差分之梯度值放大了迟早倍数,使得其同Sobel的梯度值保持同的水准。

当对比,下面是故相同阶差分与Sobel算子对本来图计算的结果,阀值100。由于一阶差分底梯度值相对比小,我本着一阶差分底梯度值放大了肯定倍数,使得它跟Sobel的梯度值保持同等的水准。

图片 25  
图片 26

图片 27  
图片 28

               一阶差分梯度模图         
              一阶差分梯度二值图

               一阶差分梯度模图         
              一阶差分梯度二价值图

图片 29  
图片 30

图片 31  
图片 32

                 Sobel梯度模图            
             Sobel梯度二价值图

                 Sobel梯度模图            
             Sobel梯度二价值图

不行醒目,Canny边缘检测的效用是老扎眼的。相比日常的梯度算法大大抑制了噪声引起的伪边缘,而且是边缘细化,易于后续处理。对于对比度较逊色之图像,通过调试参数,Canny算法也能够有好好之功力。

大显,Canny边缘检测的效果是坏明朗的。相比普通的梯度算法大大抑制了噪声引起的伪边缘,而且是边缘细化,易于后续处理。对于针对比度较逊色之图像,通过调试参数,Canny算法也克来十分好的功用。

图片 33  
图片 34  
图片 35

图片 36  
图片 37  
图片 38

                       原图               
            Canny梯度模,高斯半径2,低阀值30,高阀值100      
Canny梯度二值化图,高斯半径2,低阀值30,高阀值100

                       原图               
            Canny梯度模,高斯半径2,低阀值30,高阀值100      
Canny梯度二值化图,高斯半径2,低阀值30,高阀值100

图片 39  
图片 40  
图片 41

图片 42  
图片 43  
图片 44

                      原图               
         Canny梯度模,高斯半径1,低阀值40,高阀值80 
Canny梯度二值化图,高斯半径1,低阀值40,高阀值80

                      原图               
         Canny梯度模,高斯半径1,低阀值40,高阀值80 
Canny梯度二值化图,高斯半径1,低阀值40,高阀值80

参考

参考

Canny edge
detector

Canny edge
detector

canny
算法

canny
算法

 

 

相关文章

admin

网站地图xml地图