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

不再赘述!


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值