一、halcon算子讲解
1.
1.1 dev_update_off/on算子
在Halcon机器视觉软件中,dev_update_off和dev_update_on算子用来控制图像和图形对象的显示更新。这些算子通常在处理图像或执行视觉任务时使用,以提高程序的运行效率。
dev_update_off: 此算子用于关闭图形窗口的更新。当你在处理大量的数据或在循环中处理图像时,关闭更新可以避免频繁的界面重绘,从而加快程序的执行速度。使用此算子后,窗口不会显示处理的中间结果,只有当再次启用更新(使用dev_update_on)或者显式调用显示函数(如disp_image)时,处理结果才会显示出来。
dev_update_on: 此算子用于开启图形窗口的更新。当需要观察处理过程中的中间结果,或在程序执行完毕后显示最终结果时使用。启用更新后,所有的图形和图像操作都会即时反映在图形窗口上。
使用这些算子可以有效控制程序的显示逻辑,尤其在需要高效处理大量数据时,适当地关闭和开启更新可以显著提升处理性能。在编写Halcon程序时,通常在数据处理的开始使用dev_update_off,在数据处理结束后使用dev_update_on来恢复显示更新,以便查看结果。
1.2 halcon基本语法
重点:等号、不等号、if条件判断中的等于比较、for循环格式
//等号: :=
//不等号: !=
//注释符 *
//字符串赋值:str:='halcon'
//等于比较符:if(x==10)
//与 and
//或 or
//求反 if(not(a==10))
//for循环
for i:=0 to 5 by 1
endfor
//while循环
a:=1
while (a<10)
endwhile
//异常获取
try
catch (Exception)
endtry
//switch 多分支
switch (GenParamValue)
case 1:
break
case 2:
break
endswitch
1.3 创建图像窗口方法
dev_open_window、dev_open_window_fit_image、dev_open_window_fit_size

1.4 霍夫直线变换
定义:霍夫变换是一种广泛用于图像分析中的特征提取技术,最初由Paul Hough在1962年提出。这种方法特别适用于从图像中检测简单的几何形状,如直线、圆形和椭圆。这里主要介绍霍夫变换中最常用的形式——直线检测的霍夫变换。
1.4.1. 霍夫变换的基本原理
-
图像空间到参数空间映射
霍夫变换的核心是将图像空间(像素坐标系)中的特征点映射到一个参数空间,并在这个空间中寻找可能的形状参数。对于直线检测,通常使用极坐标方程来表示直线: 𝑟=𝑥cos(𝜃)+𝑦sin(𝜃)r=xcos(θ)+ysin(θ) 其中,𝑟r 是直线到原点的垂直距离,𝜃θ 是直线的角度(相对于x轴的逆时针角度)。 -
累加器数组
使用一个二维数组(称为累加器)来记录每一对 (𝑟,𝜃)(r,θ) 参数的出现频率。对图像中的每个边缘点,计算它通过所有可能角度 𝜃θ 的直线,每条直线对应一个特定的 𝑟r 值。对于每个 (𝑟,𝜃)(r,θ) 对,累加器中相应的元素增加一(这一过程也被称为“投票”)。 -
峰值检测
经过投票过程后,累加器中的高值(峰值)表示图像中存在直线的强烈证据。每个峰值对应一个 (𝑟,𝜃)(r,θ) 对,即对应图像空间中的一条直线。 -
从参数空间到图像空间映射
最后,根据累加器中识别的峰值,可以在原始图像中重建直线。这些直线由峰值中的 𝑟r 和 𝜃θ 参数定义。
1.4.2. 实际halcon操作
1 halcon练习代码
read_image (Image, 'F:/halcon学习/根据霍夫变换在图像中寻找直线/矩形.png')
*打开窗口
dev_close_window ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
*显示图像
dev_display (Image)
*对图像进行灰度化处理
rgb1_to_gray (Image, GrayImage)
*绘制矩形框
draw_rectangle1 (WindowHandle, Row1, Column1, Row2, Column2)
gen_rectangle1 (Rectangle, Row1, Column1, Row2, Column2)
*对图像进行抠图
reduce_domain (GrayImage, Rectangle, ImageReduced)
*显示抠图图像
dev_display (ImageReduced)
*对图像进行边缘处理
sobel_amp (ImageReduced, EdgeAmplitude, 'sum_abs', 3)
*对图像进行阈值分割
threshold (EdgeAmplitude, Region, 128, 255)
*设置连通域
connection (Region, ConnectedRegions)
*通过选择外部的矩形框
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and',2500, 99999)
*对选择的区域进行霍夫直线变换
hough_lines (SelectedRegions, 4, 50, 5, 5, Angle, Dist)
*蒋直线转换成区域
gen_region_hline (Regions, Angle, Dist)
*对霍夫结果进行选择
*对水平直线选择
select_shape (Regions, SelectedRegions1, 'orientation', 'and', 0, 0.1)
*对竖直直线进行选择
select_shape (Regions, SelectedRegions2, 'orientation', 'and', 1.5, 1.6)
*显示选择的水平线和竖直线
dev_set_window (WindowHandle)
dev_display (Image)
dev_display (SelectedRegions1)
dev_display(SelectedRegions2)
1.5 读写区域和xld
1.5.1 读写区域
read_image (Image, ‘fabrik’)
read_region (Region, ‘ReadRegion.hobj’)
write_region (Region, ‘WriteRegion.hobj’)
1.5.2 读写xld(输入轮廓)
read_image (Image, ‘fabrik’)
edges_sub_pix (Image, Edges, ‘canny’, 1, 20, 40)
write_contour_xld_dxf (Edges, ‘Coutour.dxf’)
read_contour_xld_dxf (Contours, ‘Coutour.dxf’, [], [], DxfStatus)
1.6 对区域进行交集、补集、合集和反集
注意:
① 补集:difference 以第一个区域为基准,在其区域减去第二个区域
*打开窗口
dev_close_window ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
*绘制圆形区域1
draw_circle (WindowHandle, Row, Column, Radius)
gen_circle (Circle, Row, Column, Radius)
*绘制圆形区域2
draw_circle (WindowHandle, Row1, Column1, Radius1)
gen_circle (Circle1, Row1, Column1, Radius1)
*测试different
difference (Circle, Circle1, RegionDifference)
*清空窗口内容
dev_clear_window ()
dev_display (RegionDifference)
*测试symn_difference
symm_difference (Circle, Circle1, RegionDifference1)
dev_clear_window ()
dev_display (RegionDifference1)
*测试反选
complement (Circle, RegionComplement)
dev_clear_window ()
dev_display (RegionComplement)
*测试交集
intersection (Circle, Circle1, RegionIntersection)
dev_clear_window ()
dev_display (RegionIntersection)
*测试合并union1(将全部区域进行合并)
*union1 (Circle, Circle1)
*测试合并union2(将两个区域进行合并)
union2 (Circle1, Circle, RegionUnion)
dev_clear_window ()
dev_display (RegionUnion)
1.7 对区域进行填充
注意:
① fill_up_shape 对指定特征的空洞进行填充
② fill_up 对全区域进行填充
*对选择的区域进行填充处理
*第一种进行全部填充
fill_up (Regions, RegionFillUp)
dev_clear_window ()
dev_display (RegionFillUp)
*读取图片
read_image (Image, 'egypt1')
*获取图片尺寸
get_image_size (Image, Width, Height)
*打开窗口进行显示图片
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
*显示图片
dev_display (Image)
*进行阈值分割
threshold (Image, Regions, 53, 149)
*对选中的区域进行填充处理
fill_up (Regions, RegionFillUp)
fill_up_shape (Regions, RegionFillUp, 'area', 1, 100)
1.8 根据特征过滤区域
方法① 基于select_shape算子:使用面积、坐标、角度等特征对区域进行筛选
方法② 基于select_shape_std: 根据特征,例如长方形相似性等特征进行筛选
方法③ 基于select_shape_proto: 在基于基准区域对待处理区域中进行筛选
*打开窗口
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
*读取图片
read_image (Image, 'fabrik')
*进行阈值筛选
threshold (Image, Regions, 118, 239)
*进行连通域的操作
connection (Regions, ConnectedRegions)
*进行特征选择
select_shape (ConnectedRegions, SelectedRegions1, 'area', 'and', 6990.83, 9743.12)
*进行特征选择select_shape_std
select_shape_std (ConnectedRegions, SelectedRegions, 'rectangle1', 90)
*利用select_shape_proto
select_shape_proto (ConnectedRegions, SelectedRegions, SelectedRegions2, 'covers', 0, 100)
1.9 绘制ROI区域方法汇总
方法:
① draw_circle 绘制圆形roi区域
② draw_ellipse绘制椭圆roi区域
③ draw_rectangle1 绘制长方形区域
④ draw_rectangle2 绘制仿射矩形(相比于③多了角度参数)
⑤ draw_ploygon 绘制不规则区域(不需要gen算法进行生成区域)
⑥ draw_region 绘制封闭区域(同样不要gen算子进行生成区域)
⑦ draw_lines 绘制直线(需要跟disp_lines配套使用,显示出绘制的曲线)
*创建一个窗口
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
*绘制圆形
draw_circle (WindowHandle, Row, Column, Radius)
gen_circle (Circle, Row, Column, Radius)
*绘制椭圆ROI
draw_ellipse (WindowHandle, Row4, Column4, Phi1, Radius1, Radius2)
gen_ellipse (Ellipse, Row4, Column4, Phi1, Radius1, Radius2)
*绘制矩形
draw_rectangle1 (WindowHandle, Row1, Column1, Row2, Column2)
gen_rectangle1 (Rectangle, Row1, Column1, Row2, Column2)
*绘制仿射矩阵
draw_rectangle2 (WindowHandle, Row3, Column3, Phi, Length1, Length2)
gen_rectangle2 (Rectangle1, Row3, Column3, Phi, Length1, Length2)
*绘制不规则曲线
draw_polygon (PolygonRegion, WindowHandle)
*绘制封闭区域
draw_region (Region1, WindowHandle)
*绘制直线
draw_line (WindowHandle, Row11, Column11, Row21, Column21)
disp_line (WindowHandle, Row11, Column11, Row21, Column21)
2.0 计算算子运算时间方法
方法:count_second算子(单位ms)
*计算算子运行时间
dev_update_off ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
*计算程序开始时间
count_seconds (T)
*读取一张图片
read_image (Image1, 'printer_chip/printer_chip_01')
*获取图像尺寸
get_image_size (Image1, Width1, Height1)
*显示图像
dev_update_on ()
dev_display (Image1)
*计算程序结束时间
count_seconds (T2)
*设置显示位置
set_tposition (WindowHandle, 24, 12)
*设置显示字体
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
*显示字符
write_string (WindowHandle, '算子运行时间: '+ (T2-T)*1000 + 's')
2.1 将bayer图像转换成rgb图像
2.1.1. bayer图像格式定义
bayer格式图片是伊士曼·柯达公司科学家Bryce Bayer发明的,Bryce Bayer所发明的拜耳阵列被广泛运用数字图像。
2.1.2. Bayer图像排列形式:

Bayer图像如何转换为RGB:
R22=(R11+R13+R31+R33)/4
B22=B22
G22=(G12+G21+G32+G23)/4
2.1.3. halcon将bayer转rgb练习
注意:出现的新算子gen_empty_obj,产生一个空对象
*读取图片
read_image (Image, 'patras')
*打开窗口
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
*显示图片
dev_display (Image)
*模拟bayer图像生成
simulate_bayer_image (Image, ImageCFA)
*产生一个空的对象
gen_empty_obj (EmptyObject)
*将bayer图像转换为frb图像
cfa_to_rgb (ImageCFA, EmptyObject, 'bayer_gr', 'bilinear')
*进行显示转换后的RGB图片
dev_display (EmptyObject)
2.2. 将图像转换成矩阵
注:四个关键算子
① get_region_point 获取指定区域内的坐标点
② get_grayval 获取指定区域内各坐标点对应的灰度值
③ create_matrix 产生一个空矩阵
④ set_value_matrix 对矩阵进行赋值
2.2.1. halcon将图像转换成矩阵练习
*读取图像
read_image (Image1, 'printer_chip/printer_chip_01')
*将图像转化成灰度图
rgb1_to_gray (Image1, GrayImage)
*获取图像的尺寸
get_image_size (GrayImage, Width1, Height1)
*获取图像区域的坐标点
get_region_points (GrayImage, Rows1, Columns1)
*获取区域的灰度值
get_grayval (GrayImage, Rows1, Columns1, Grayval1)
*创建空矩阵
create_matrix (Height1, Width1, 0, MatrixID1)
*将图像灰度值复制到矩阵中
set_value_matrix (MatrixID1, Rows1, Columns1, Grayval1)
2.3. 实现窗口自适应显示图像
注:关键算子dev_set_part

2.3.1 与使用窗口显示函数显示图像对比
*读取图像
read_image (Image1, 'printer_chip/printer_chip_01')
*获取图像尺寸
get_image_size (Image1, Width1, Height1)
*关闭已打开的窗口
dev_close_window ()
*打开窗口
dev_open_window (0, 0, Width1, Height1, 'black', WindowHandle1)
*对图像进行自适应显示
dev_set_part (0, 0, Height1, Width1)
*显示图像
dev_display (Image1)
*使用dev_open_fit_image显示图像进行对比
dev_open_window_fit_image (Image1, 0, 0, -1, -1, WindowHandle2)
*设置需要显示的窗口句柄
dev_set_window (WindowHandle2)
*显示图像
dev_display (Image1)
*使用dev_open_window_fit_size算子显示图像进行对比
dev_open_window_fit_size (0, 0, Width1, Width1, -1, -1, WindowHandle3)
dev_set_window (WindowHandle3)
dev_display (Image1)
这里面dev_open_window_fit_size算子中的窗口尺寸写错了,导致第三个窗口显示的图像并没有自适应显示图像。在纠正以后,dev_open_window_fit_image算子和dev_open_window_fit_size算子显示的图像与dev_set_part算子显示的图像基本一致。
2.4. 将彩色图像转成灰度图像
注意:将彩色图像转成灰度图像算子有两个
① 使用rgb1_to_gray
② 使用rgb3_to_gray算子,需要和decompose3算子进行联合使用
read_image(Image,'patras')
dev_display(Image)
rgb1_to_gray(Image,GrayImage)
dev_display(GrayImage)
*创建显示窗
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
*显示图片
dev_display (Image)
*对彩色图片进行通道分离
decompose3 (Image, Image1, Image2, Image3)
*将三个通道进行合并转换为灰度图片
rgb3_to_gray (Image1, Image1, Image1, ImageGray)
*显示灰度图片
dev_display (ImageGray)
2.5.图像色彩空间转换
目标:将rgb色彩空间转换成hsv空间
色彩空间转换效果图:

练习代码:
*读取图像
read_image (Image4, 'patras')
*获取图像尺寸
get_image_size (Image4, Width, Height)
*打开窗口
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'black', WindowHandle1)
*显示图像
dev_display (Image4)
*将彩色图像分成RGB
decompose3 (Image4, Image11, Image21, Image31)
*将RGB图形转换成hsv
trans_from_rgb (Image11, Image21, Image31, ImageResult11, ImageResult21, ImageResult31, 'hsv')
*将hsv图像转化成rgb
trans_to_rgb (ImageResult11, ImageResult21, ImageResult31, ImageRed1, ImageGreen1, ImageBlue1, 'hsv')
compose3 (ImageRed1, ImageRed1, ImageRed1, MultiChannelImage1)
*显示重构的rgb图像
dev_open_window (0, 0, Width, Height, 'black', WindowHandle2)
dev_display (MultiChannelImage1)
2.6. 图像数据转换
注:关键算子convert_image_type
读取的图像数据类型是8位,高斯卷积后的图像数据类型是real
练习代码:使用convert_image_type算子将高斯卷积后的图像数据类型(real)转成byte数据类型
*读取图片
read_image (Image, 'meningg5')
*进行高斯卷积滤波
derivate_gauss (Image, DerivGauss, 1, 'none')
*将浮点数转换为byte类型
convert_image_type (DerivGauss, ImageConverted, 'byte')
2.7. 图像间隙进行填充
注:关键参数growingregion、expand_region算子
由于区域生长算法有点难理解,找了点相关的参考资料进行学习,如下所示:
- regiongrowing 算子
Halcon 中的regiongrowing算子实现了区域生长的功能,它能将灰度相近的相邻像素合并为同一区域。regiongrowing 算子的原型如下:
regiongrowing(Image : Regions : Row, Column, Tolerance, Minsize 😃
其中各参数的含义如下。
(1)参数1:Image为输入的单通道图像。
(2)参数2:Regions 为输出的一组区域。
(3)参数3和4:Row、Column分别为矩形区域的宽和高,需要是奇数,以便计算中心点坐标。默认为1,1,也可以选择其他奇数。
(4)参数5:Tolerance 为灰度差值的分割标准。如果另一个点的灰度与种子区域的灰度差值小于Tolerance,则认为它们可以合并为同一区域。这个值默认为6.0。
(5)参数6:MinSize,表示输出区域的最小像素数,默认为100。
其工作步骤如下。
(1)设定一个尺寸为RowColumn的卷积核,以及一个作为分界依据的像素灰度差值Tolerance。
(2)使用上述指定尺寸的卷积核在原图上进行扫描,并计算卷积核内矩形图像的中心点灰度与邻域矩形图像的中心点灰度差。如果差值小于Tolerance,则将这两个矩形区域合并为同一个。
卷积核默认为11,一般长宽都为奇数。如果大于11,需要先对图像进行平滑处理,平滑的卷积核大小至少为RowColum,这是为了使矩形中心更突出。如果图像上的噪点比较多并且卷积核比较小,也可以省略平滑这一步骤,以减少误判。
————————————————
间隙填充效果:

halcon练习:
*读取图像
read_image (Image1,'fabrik')
*打开窗口
dev_open_window (0, 0, 512, 512, 'black', WindowHandle1)
*显示图像
dev_display (Image1)
*将图像进行分割
regiongrowing (Image1, Regions1, 1, 3, 6, 1000)
*产生一个空的区域防止expand_region对其进行分割
gen_empty_region (EmptyRegion1)
*对图像进行间隙填充
expand_region (Regions1, EmptyRegion1, RegionExpanded1, 'maximal', 'image')
*显示间隙填充的效果
dev_clear_window ()
*显示图像效果
dev_display (RegionExpanded1)
expand_region的原理暂时不理解,有理解的小伙伴可以评论留言,一起学习
2.8. 如何在窗口上显示文字
关键算子:
① 设置文字显示位置 set_tposition
② 显示文字 write_string
*读取图片
read_image (Image, 'particle')
*获得图片的尺寸
get_image_size (Image, Width, Height)
*新建窗口
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
*进行显示图片
dev_display (Image)
*设置显示文字的位置
set_tposition (WindowHandle,Height/2, 0)
*进行显示文字
write_string (WindowHandle, '所选区域的中心坐标是'+'('+Row+','+Column+')')
2.9 分水岭算法
1.分水岭介绍

传统的分水岭分割方法,是一种基于拓扑理论的数学形态学的分割方法,其基本思想是把图像看作是地质学上的拓扑地貌,图像中每一像素的灰度值表示该点的海拔高度,每一个局部极小值及其周边区域称为集水盆地,而集水盆地的边界则形成分水岭。
2.相关概念
局部极小值点:该点对应一个盆地的最低点,当我们在盆地里滴一滴水的时候,由于重力作用,水最终会汇聚到该点。注意:可能存在一个最小值面,该平面内的都是最小值点。
3.分水岭原理
假设我们在盆地的最小值点,打一个洞,然后往盆地里面注水,并阻止两个盆地的水汇集,我们会在两个盆地的水汇集的时刻,在交接的边缘线上(也即分水岭线),建一个坝,来阻止两个盆地的水汇集成一片水域。这样图像就被分成2个像素集,一个是注水盆地像素集,一个是分水岭线像素集。
- halcon分水岭算法实际操作
*读取图片
read_image (Image, 'particle')
get_image_size (Image, Width, Height)
*显示图像
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
dev_display (Image)
*设置轮廓显示
dev_set_draw ('margin')
*设置显示颜色数量
dev_set_colored (12)
invert_image (Image, ImageInvert1)
*显示反转图像
dev_clear_window ()
dev_display (ImageInvert1)
*使用分水岭对进行图像分割
watersheds (ImageInvert1, Basins1, Watersheds1)
*显示原始图像
dev_display (image)
*显示盆地
dev_display (Basins1)
2.9.1使用分水岭算法求筛子点数
**************使用分水龄算法,分析筛子点数*************
* 1:采集图像+处理图像
* 2:分水岭算法+blob分析 求塞子的数量
* 3: blob 分析 求每个筛子上的点数。
dev_update_off ()
* 读取相对路径目录下所有的文件路径,保存到元组FilePathsFilePaths中,里面全是字符串
list_files ('./dice', ['files','follow_links'], FilePaths)
* 过滤FilePaths元组中每一个元素,将满足正则匹配条件的元素,添加到imgPaths中
tuple_regexp_select (FilePaths,['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], imgPaths)
stop()
for i:=0 to |imgPaths|-1 by 1
* 输入图像:根据路径加载图像
read_image (Image, imgPaths[i])
rgb1_to_gray (Image, img)
* 阈值分割:获取图像的筛子【需要图像哪个区域就输入哪个区域的灰度值范围】
threshold (img, Region, 128, 255)
* 填充区域:将区域中的孔洞进行填充,让区域更完整
fill_up (Region, RegionFillUp)
* 连通性分析,分割区域:问题:有粘连在一起的区域;
connection (RegionFillUp, ConnectedRegions)
stop()
**********将粘连在一起的区域分割开
* distance_transform 距离仿射变换,计算非 0 灰度值 到最近的 0 绘制的距离
* 参数:输入图像,输出仿射图像【关键看:3D点云图,看是否有7个山峰】
* 输入计算方式
* Foreground
* width 需要调参的
* height 需要调参
* 目的:为了得到7个山峰,一个区域一个山峰,问题:个别山峰有连载一起的情况
* 所以:才需要分水岭算法、
* distance_transform (ConnectedRegions, DistanceImage, 'octagonal', 'true', 1000, 1000)
* 图像类型转化:这里是将int4转为byte
* convert_image_type (DistanceImage, ImageConverted, 'byte')
* 图像增强:黑的更黑白的更白。
* scale_image_max (ImageConverted, ImageScaleMax)
* watersheds_threshold() 分水岭算法
* 参数:输入图像 注意:图像类型:byte ,如果图片类型不对,
* 使用convet_image_type 实现类型转化
* 输出区域
* 输入灰度值
* 注意:针对背景为黑 前景为白,不论设置什么值,无法分割区域
* watersheds_threshold (ImageScaleMax, Basins,125 )
* intersection (Basins, ConnectedRegions, RegionIntersection)
* 解决上面的问题:
distance_transform (ConnectedRegions, DistanceImage, 'octagonal', 'true', 1000, 1000)
* 图片数据类型转化:将int4 类型转化为 字节类型
convert_image_type (DistanceImage, ImageConverted, 'byte')
* 颠倒灰度值:为了解决分水岭无法分割区域的问题。
invert_image (ImageConverted, ImageInvert)
* 图像锐化:黑的更黑,白的更白
scale_image_max (ImageInvert, ImageScaleMax)
* 分水岭算法: 分割粘连区域。
watersheds_threshold (ImageScaleMax, Basins,10)
* 求交集: 分水岭与连通性分析(筛子区域) 的交集 等于:每个筛子分开的区域
intersection (Basins, ConnectedRegions, RegionIntersection)
* 过滤小的噪点
select_sh

最低0.47元/天 解锁文章
371

被折叠的 条评论
为什么被折叠?



