Halcon实例分析——autobahn.hdev快速检测道路标志

这是运行代码的结果,下面我们每条代码过一遍,下面的代码路径为打开halcon,浏览实例程序,方法中的Blob分析,

 

 

有些重点代码会详细讲解,

* autobahn.hdev: Fast detection of lane markers
* 
dev_update_window ('off')
dev_close_window ()
dev_open_window (0, 0, 768, 575, 'black', WindowID)
MinSize := 30
get_system ('init_new_image', Information)
set_system ('init_new_image', 'false')
gen_grid_region (Grid, MinSize, MinSize, 'lines', 512, 512)
clip_region (Grid, StreetGrid, 130, 10, 450, 502)
dev_set_line_width (3)
dev_set_color ('green')
read_image (ActualImage, 'autobahn/scene_00')
dev_display (ActualImage)
stop ()
dev_display (StreetGrid)
stop ()
for i := 0 to 28 by 1
    read_image (ActualImage, 'autobahn/scene_' + (i$'02'))
    reduce_domain (ActualImage, StreetGrid, Mask)
    sobel_amp (Mask, Gradient, 'sum_abs', 3)
    threshold (Gradient, Points, 20, 255)
    dilation_rectangle1 (Points, RegionDilation, MinSize, MinSize)
    reduce_domain (ActualImage, RegionDilation, StripGray)
    threshold (StripGray, Strip, 190, 255)
    fill_up (Strip, RegionFillUp)
    dev_display (ActualImage)
    dev_display (RegionFillUp)
endfor
dev_set_line_width (1)
dev_update_window ('on')
set_system ('init_new_image', Information)

简介,这里还是使用了常规的blob分析法,只不过使用了一个 更高效的网格方法

 * autobahn.hdev: Fast detection of lane markers

autobahn.hdev:道路标志快速检测

dev_update_window ('off')

 dev_update_window — 指定是否每一步都去刷新显示图形到窗口上,单步去执行算子的时候,无论关闭还是打开都没有什么影响;要是连续执行的时候我们需要看连续执行的时间,最好关闭。关闭后,我们若要显示需要显示的图形后者ROI时,需要使用dev_display算子去显示

当然在导出到C#后,是不需要使用这个算子的,仅仅在HALCON中使用,在C#中我们必须使用显示函数去显示图形。

在这个例子中设为off,关闭自动刷新显示图形

dev_close_window ()
dev_open_window (0, 0, 768, 575, 'black', WindowID)

先关闭窗口再从新以新的尺寸打开窗口;

在导出到C#中的时候,因为我们的窗口都是固定,都是使用算子得到图片的大小,然后让图片去适应窗口,一般我写代码就没有使用这两个算子;当然也可以使用,就是在程序第一次打开的时候,使用固定大小打开窗口;

在HALCON中没有去使用图片适应窗口,而是让窗口去适应图片所以很多例子中都是先把窗口关闭再打开。

MinSize := 30

 创建变量并赋值

get_system ('init_new_image', Information)
set_system ('init_new_image', 'false')

 先获取属性值,再设置属性值

get_system获取当前系统参数的当前值

set_system设置当前系统参数的值

系统默认的参数很多,这些参数只是适用于HDevolop这个编程环境,如果导入到C#中使用,很多halcon的设置属性和获取属性是没法使用的,这里我们需要注意。

这里设置的是init_new_Image键盘按F6单步运行get_system我们发现返回的值是true,按键盘F1可以查询到这个算子的部分属性

 有只读的有读写的,感兴趣的可以看一看。

我们查询下set_system

 

 

 找到init_new_image

大致翻译是这样说的,确定在使用过滤器之前是否应将新图像设置为0,从而确保在具有相同配置的系统上重复执行程序时,过滤返回的值是一致的。请注意,如果始终对整个图像进行过滤,或者如果未过滤图像区域的数据不重要,则不需要这样做。

这里提供这样一个思路,如果你对于一个算子有疑问,那就注释掉这段代码,运行程序,看有什么区别,再去理解概念,就会体会深刻。

gen_grid_region (Grid, MinSize, MinSize, 'lines', 512, 512)

生成 网格,网格的类型我们按F1可以查询到,有线类型和点类型,当然点类型也就是横竖线的交点。这里是线类型,网格之间的横竖距离就是MinSize的大小,下面是RowSteps的取值范围

 ColumnSteps同理

 512是网格的最大横纵坐标,取值范围如下,这个例子中也就是从ROW=0到ROW=512,COLUMN=0到COLUMN=512

 clip_region (Grid, StreetGrid, 130, 10, 450, 502)

 剪切区域算子,根据官方文档描述,使用这个算子的原因是这个算子的效率比使用交集的效率要高

 在这个例子中,因为生成网格时是从(0,0)开始生成到(512,512)结束,我们并不需要这么到,需要剪切掉不需要的部分,所以这里使用剪切算子

运行算子到这里,就可以生成一个如下图的网格

 后面的代码就是不断在这个网格的基础上执行blob分析运算,使用了一个for循环,循环读取29张图片

for i := 0 to 28 by 1
    read_image (ActualImage, 'autobahn/scene_' + (i$'02'))
    reduce_domain (ActualImage, StreetGrid, Mask)
    sobel_amp (Mask, Gradient, 'sum_abs', 3)
    threshold (Gradient, Points, 20, 255)
    dilation_rectangle1 (Points, RegionDilation, MinSize, MinSize)
    reduce_domain (ActualImage, RegionDilation, StripGray)
    threshold (StripGray, Strip, 190, 255)
    fill_up (Strip, RegionFillUp)
    dev_display (ActualImage)
    dev_display (RegionFillUp)
endfor

  read_image (ActualImage, 'autobahn/scene_' + (i$'02'))
    reduce_domain (ActualImage, StreetGrid, Mask)

按顺序读取本地图片,我们导出到C#中的时候,如果手上没有相机,也可以使用这种方式,循环读取本地一系列的图片来验证我们的算法。

第二行是剪切函数, 很多检测都会用到剪切函数,因为我们在检测的时候,不是所以的区域都是我们感兴趣和需要去处理的,处理的区域也是越小越好,这样才能保证处理的速度很快。

我们单独显示剪切后的区域如下

 可以看到剪切的结果就是图像和线条的重合部分,镂空部分并没有剪切过来,通过这样单步的去执行算子,然后看结果,我们就能更好的理解算子的作用。

sobel_amp (Mask, Gradient, 'sum_abs', 3)

 这里使用边缘检测算子找到重合的边缘部分,所谓边缘也就是图片上明暗有变化的地方就会有边缘,这里使用的FilterType官方提供了一些值如下

 这些值大家可以找到一张图片,分别使用这些值去测试,就大致会知道在什么样的情况下使用什么方法

 找到边缘之后,再使用阈值算子提取这些点,这里我当时有个疑问为什么不直接使用阈值呢,直接提取亮的点不也可以吗?后来我想了想,这些亮的区域的灰度值是不确定的,我们没办法使用一个固定的范围去提取,即使大部分情况下能提取到,总归会有提取不到的时候,使用边缘,是一个相对提取法,边缘相对于其他地方是亮的,所以更稳定。

可以简单这样理解

阈值是一个绝对提取,

边缘是一个相对提取

提取结果如下

 dilation_rectangle1 (Points, RegionDilation, MinSize, MinSize)

 使用膨胀算子使得提取的点变大

   reduce_domain (ActualImage, RegionDilation, StripGray)

 再次剪切出关注的区域

  threshold (StripGray, Strip, 190, 255)

再次使用阈值算子提取道路标志

 fill_up (Strip, RegionFillUp)
    dev_display (ActualImage)
    dev_display (RegionFillUp)

 填充空洞,在阈值的时候,可能部分地方的灰度值不在我们设定的范围,我们认为填充上

 看到这里,我的总结是,这里只是提供一个思路,就是使用网格去提取检测区域的形式,我们没必要照搬不误的去使用,这里其实我们提前生成三个矩形区域也是没有问题,把三个举行区域合并成一个区域,然后去循环剪切关注区域,再使用阈值计算也是可以的。

我们在看例程的时候,一定要注意,所有例程最核心的都是提供思路,同一中缺陷检测有很多中检测思路,我们要根据实际情况灵活使用

 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无锡伶俐科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值