Canny边缘检测高低阈值连接的代码修正

简介: Canny边缘检测高低阈值连接的代码修正

在《Java数字图像处理-编程技巧与应用实践》一书的第九章讲到了Canny边缘检测的代码实现,在求取梯度与角度处理,非最大信号压制之后,有一步是通过两个阈值(高低阈值)实现边缘断线的连接,得到完整的边缘,之前给出的代码是固定阈值,这个有两个改动:


改动一:


改为自动阈值了,高的阈值是梯度的平均值means的两倍,低阈值是平均值的二分之一。


改动二:


高低值连接的时候递归程序改为非递归程序,通过图的深度优先队列实现边缘像素连接。


这两个改动的原因是有读者向我反馈说提供的代码在处理大图片的时候递归的代码导致栈溢出错误,如今改为非递归之后,我测试过1600x1200的图片进行边缘提取,完全没有问题。

先看效果:原图:


处理之后:


源代码改动说明:

不再使用follow(col, row, offset, lowThreshold);方法

直接改为非递归的图的深度优先队列进行处理,对每个像素点构建PixelNode数据结构

package com.book.chapter.nine;
 
public class PixelNode {
  protected int row;
  protected int col;
  protected int index;
  protected boolean high;
}

自动阈值与非递归的代码如下:

// 寻找最大与最小值
    float min = 255;
    float max = 0;
    double sum = 0;
    double count = 0;
    for(int i=0; i<magnitudes.length; i++)
    {
      if(magnitudes[i] == 0) continue;
      min = Math.min(min, magnitudes[i]);
      max = Math.max(max, magnitudes[i]);
      sum += magnitudes[i];
      count++;
    }
    System.out.println("Image Max Gradient = " + max + " Mix Gradient = " + min);
    float means = (float)(sum / count);
    System.out.println("means = " + (sum / count));
    // 通常比值为 TL : TH = 1 : 3, 根据两个阈值完成二值化边缘连接
    // 边缘连接-link edges
    Arrays.fill(data, 0);
    int offset = 0;
    highThreshold =  means * 2;
    lowThreshold = means / 2;
    System.out.println("ddddddddddddddddddddddddd");
    Queue<PixelNode> queue = new LinkedList<PixelNode>();
    for (int row = 0; row < height; row++) {
      for (int col = 0; col < width; col++) {
        if(magnitudes[offset] >= highThreshold && data[offset] == 0)
        {
          PixelNode pn = new PixelNode();
          pn.row = row;
          pn.col = col;
          pn.index = offset;
          pn.high = true;
          queue.add(pn);
          while(!queue.isEmpty()) {
            PixelNode node = queue.poll();
            int x0 = (node.col == 0) ? node.col : node.col - 1;
            int x2 = (node.col == width - 1) ? node.col : node.col + 1;
            int y0 = node.row == 0 ? node.row : node.row - 1;
            int y2 = node.row == height -1 ? node.row : node.row + 1;
            
            data[node.index] = magnitudes[node.index];
            for (int x = x0; x <= x2; x++) {
              for (int y = y0; y <= y2; y++) {
                int i2 = x + y * width;
                if ((y != node.row || x != node.col)
                  && data[i2] == 0 
                  && magnitudes[i2] >= lowThreshold) {
                  PixelNode middleNode = new PixelNode();
                  middleNode.col = x;
                  middleNode.row = y;
                  middleNode.index = i2;
                  middleNode.high = false;
                  queue.offer(middleNode);
                }
              }
            }
          }
        }
        queue.clear();
        offset++;
      }
    }


其它部分的源代码参考这里http://blog.csdn.net/jia20003/article/details/41173767

不再赘述!

相关文章
|
1月前
|
算法 计算机视觉
使用积分图的自适应二值化算法
使用积分图的自适应二值化算法
|
算法 数据可视化
Halcon边缘检测和线条检测(1),文章含自适应/动态二值化等算子
Halcon边缘检测和线条检测(1),文章含自适应/动态二值化等算子
1282 0
|
4天前
|
算法 C++ 计算机视觉
详细解读Canny检测算法与实现
详细解读Canny检测算法与实现
|
1月前
|
API 计算机视觉
【OpenCV】—图像对比度、亮度值调整
【OpenCV】—图像对比度、亮度值调整
|
1月前
|
计算机视觉
OpenCV图像阈值
OpenCV图像阈值
10 0
|
1月前
|
传感器 人工智能 搜索推荐
用 ChatGPT 4.0 实现获取并保存 RealSense 相机的深度图像,处理colorizer,histogram equalization配置,解决深度图像颜色分布异常问题
用 ChatGPT 4.0 实现获取并保存 RealSense 相机的深度图像,处理colorizer,histogram equalization配置,解决深度图像颜色分布异常问题
56 0
用 ChatGPT 4.0 实现获取并保存 RealSense 相机的深度图像,处理colorizer,histogram equalization配置,解决深度图像颜色分布异常问题
|
1月前
|
计算机视觉
[OpenCv] 自适应阀值的二值化处理
[OpenCv] 自适应阀值的二值化处理
26 1
|
8月前
|
算法 计算机视觉
OpenCV-自适应阈值函数cv::adaptiveThreshold
OpenCV-自适应阈值函数cv::adaptiveThreshold
OpenCV-自适应阈值函数cv::adaptiveThreshold
|
8月前
|
机器学习/深度学习 人工智能 算法
OpenCV-差分法实现绿叶识别(图像差分+颜色通道)
OpenCV-差分法实现绿叶识别(图像差分+颜色通道)
108 0
|
11月前
|
算法 计算机视觉
06 OpenCV 阈值处理、自适应处理与ostu方法
CV2中使用阈值的作用是将灰度图像二值化,即将灰度图像的像素值根据一个设定的阈值分成黑白两部分。阈值处理可以用于图像分割、去除噪声、增强图像对比度等多个领域。例如,在物体检测和跟踪中,可以通过对图像进行阈值处理来提取目标区域;在图像增强中,可以使用阈值处理来增强图像的轮廓和细节等。