目录
一、halcon算子讲解
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循环格式
1.3 创建图像窗口方法
dev_open_window、dev_open_window_fit_image、dev_open_window_fit_size
1.4 霍夫直线变换
定义:霍夫变换是一种广泛用于图像分析中的特征提取技术,最初由Paul Hough在1962年提出。这种方法特别适用于从图像中检测简单的几何形状,如直线、圆形和椭圆。这里主要介绍霍夫变换中最常用的形式——直线检测的霍夫变换。
1.4.1. 霍夫变换的基本原理
1. 图像空间到参数空间映射
霍夫变换的核心是将图像空间(像素坐标系)中的特征点映射到一个参数空间,并在这个空间中寻找可能的形状参数。对于直线检测,通常使用极坐标方程来表示直线: 𝑟=𝑥cos(𝜃)+𝑦sin(𝜃)r=xcos(θ)+ysin(θ) 其中,𝑟r 是直线到原点的垂直距离,𝜃θ 是直线的角度(相对于x轴的逆时针角度)。
2. 累加器数组
使用一个二维数组(称为累加器)来记录每一对 (𝑟,𝜃)(r,θ) 参数的出现频率。对图像中的每个边缘点,计算它通过所有可能角度 𝜃θ 的直线,每条直线对应一个特定的 𝑟r 值。对于每个 (𝑟,𝜃)(r,θ) 对,累加器中相应的元素增加一(这一过程也被称为“投票”)。
3. 峰值检测
经过投票过程后,累加器中的高值(峰值)表示图像中存在直线的强烈证据。每个峰值对应一个 (𝑟,𝜃)(r,θ) 对,即对应图像空间中的一条直线。
4. 从参数空间到图像空间映射
最后,根据累加器中识别的峰值,可以在原始图像中重建直线。这些直线由峰值中的 𝑟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)
2 程序素材
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算子
由于区域生长算法有点难理解,找了点相关的参考资料进行学习,如下所示:
1. 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个像素集,一个是注水盆地像素集,一个是分水岭线像素集。
4. 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)
3.0 阈值分割算子
注:
全阈值分割算法:threshold
自动阈值分割:auto_threshold(将图像分割为多个区域)、binary_threshold(能够计算出一个灰度值进行区域分割,结果为一个区域)
局部阈值分割:dyn_shreshold(需要对图像进行滤波处理等)、var_threshold (标准差越大,提取区域相互链接少,小于绝对阈值的会被忽略)
其他阈值分割算法:dual_threshold(使用阈值和灰度两个条件进行阈值分割,对于小于目标值的进行抑制)、char_shreshold
*介绍halcon中的阈值分割算法
*读取图像
read_image (Image1, 'C:/Users/Public/Documents/MVTec/HALCON-17.12-Progress/examples/images/alpha1.png')
*打开窗口并显示图像
dev_close_window ()
*获取图形尺寸
get_image_size (Image1, Width1, Height1)
dev_open_window_fit_image (Image1, 0, 0, -1, -1, WindowHandle1)
dev_display (Image1)
*对图像进行全阈值分割
threshold (Image1, Region, 0, 150)
*自动阈值分割
dev_close_window ()
auto_threshold (Image1, Regions1, 16)
dev_display (Regions1)
*使用二至阈值分割方法
dev_clear_window ()
binary_threshold (Image1, Region1, 'max_separability', 'dark', UsedThreshold)
dev_display (Region1)
*个人理解:虽然auto_threshold算子和binary_threshold算子都是基于灰度直方图进行分割图像,但是autoshold算子根据波峰波谷分割出不同的区域,
*但是,binary_threshold算子是可以计算出一个灰度值用于分割图像,输出结果位一个分割区域。
*局部阈值分割算法,用于一些无法通过单一灰度值进行分割图像,图像背景灰度情况比较复杂
*读取图像
read_image (Image2, 'alpha1.png')
*显示图像
dev_close_window ()
dev_display (Image2)
*提高图像的对比度
mult_image (Image2, Image2, ImageResult, 0.005, 0)
mean_image (ImageResult, ImageMean, 9, 9)
dyn_threshold (ImageResult, ImageMean, RegionDynThresh, 5, 'dark')
*对图像进行开运算
opening_circle (RegionDynThresh, RegionOpening,1.5)
dev_display (RegionOpening)
*其他阈值提取算法
*字符阈值分割算法
char_threshold (Image2, Image2, Characters, 2, 98, Threshold)
dev_clear_window ()
dev_display (Characters)
dev_open_window (0, 0, 512, 512, 'black', WindowHandle2)
*双阈值处理方法(需要对图像进行拉普拉斯变换),用于图像灰度是有正负的
*读取图像
read_image (Image3, 'traffic1.png')
read_image (Image4, 'traffic2.png')
*对图像进行拉普拉斯变换
diff_of_gauss (Image4, DiffOfGauss, 5, 1.6)
diff_of_gauss (Image3, DiffOfGauss1, 5, 1.6)
*对图像进行相减
sub_image (DiffOfGauss, DiffOfGauss1, ImageSub, 1,0)
dev_clear_window ()
dev_display (ImageSub)
dual_threshold (ImageSub, RegionCrossings, 300, 20, 10)
dev_clear_window ()
dev_display (RegionCrossings)
*其他阈值分割var——threshold算子(也是一种局部阈值分割算法,基于标准差和均值)
*读取图像
read_image (Image5, 'label_01')
var_threshold (Image5, Region2, 15, 15,1.1, 80, 'dark')
3.1 读写文件
注:
关键算子:
① open_file 打开文件获取文件句柄
② fwrite_string 根据句柄将要待写入的内容写进对应的文件
③ close_file 关闭文件
③ fread_line 读取行内容
read_image (Image, 'fabrik')
*获取图片的尺寸
get_image_size (Image, Width, Height)
*创建窗口显示图片
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
*显示图片
dev_display (Image)
*清空窗口里的内容
dev_clear_window ()
*进行阈值分割
threshold (Image, Regions, 0, 163)
*获取选择区域的中心位置和面积
area_center (Regions, Area, Row, Column)
*将面积和坐标写如文件保存
open_file ('C:/information.txt', 'output', FileHandle)
*将面积写入文件
fwrite_string (FileHandle, '面积是:'+Area+'\n')
*将坐标写入文件
fwrite_string (FileHandle, '横坐标: '+Row+'纵坐标:'+Column+'\n')
*关闭文件句柄
close_file (FileHandle)
*文件读取操作
open_file ('C:/information.txt', 'input', FileHandle1)
*每次读取行内容
fread_line (FileHandle1, OutLine, IsEOF)
while (IsEOF#1)
fread_line (FileHandle1, OutLine, IsEOF)
endwhile
close_file (FileHandle1)
3.2 腐蚀、膨胀、开运算、闭运算
*读取图像
read_image (Image, 'fabrik')
*阈值图像
threshold (Image, Region, 128, 255)
*连通处理
connection (Region, ConnectedRegions)
*根据面积过滤
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 8000, 9000)
* 用矩形结构元素膨胀
dilation_rectangle1 (SelectedRegions, RegionDilation1, 3, 3)
* 用圆形结构元素膨胀
dilation_circle (SelectedRegions, RegionDilation2, 2.5)
* 用矩形结构元素腐蚀
erosion_rectangle1 (SelectedRegions, RegionErosion1, 3, 3)
* 用圆形结构元素腐蚀
erosion_circle (SelectedRegions, RegionErosion2, 2.5)
* 用矩形结构元素开运算
opening_rectangle1 (SelectedRegions, RegionOpening1, 10, 10)
* 用圆形结构元素开运算
opening_circle (SelectedRegions, RegionOpening2, 2.5)
*用矩形结构元素闭运算
closing_rectangle1 (SelectedRegions, RegionClosing1, 10, 10)
*用圆形结构元素闭运算
closing_circle (SelectedRegions, RegionClosing2, 3.5)
二、halcon进阶学习
2.1 批量加载图像
* Image Acquisition 01: Code generated by Image Acquisition 01
list_files ('F:/halcon学习/1halcon初级视频/Halcon初级视频配套资料/第五课 halcon批量加载图像/image', ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
* Image Acquisition 01: Do something
endfor
2.2 将halcon程序导出高级语言
halcon软件界面:文件->导出->选择导出对应的高级语言
2.3 联合C#编程,打开窗口并显示图像
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
private HTuple mian_window;
public HObject picture = new HObject();
public Form1()
{
InitializeComponent();
openwindow();
load_image();
}
public void openwindow()
{
int window_row=0, window_col = 0;
HTuple father_window = this.pictureBox1.Handle;
HOperatorSet.SetWindowAttr("background_color","blue");
HOperatorSet.SetWindowAttr("background_color", "black");
HOperatorSet.OpenWindow(window_row, window_col,(HTuple)this.pictureBox1.Width,(HTuple)this.pictureBox1.Height, father_window, "visible","",out mian_window);
}
public void load_image()
{
HTuple width=null, height = null;
HOperatorSet.ReadImage(out picture, "F:\\创建图像窗口的几种方式\\1.jpg");
HOperatorSet.GetImageSize(picture,out width,out height);
HOperatorSet.SetColor(mian_window,"red");
HOperatorSet.SetPart(mian_window,0,0, height, width);
HOperatorSet.DispObj(picture, mian_window);
HOperatorSet.SetTposition(mian_window,height/2, width / 2);
HOperatorSet.WriteString(mian_window,"你好宝宝");
}
}
}
效果显示:
2.4 回形针项目练习
关键算子:获取区域角度 orientation_region; 箭头显示disp_arrow
*读取图像
dev_close_window ()
read_image (Image, 'clip')
*获取图像尺寸
get_image_size (Image, Width1, Height1)
*显示图像
dev_open_window_fit_size (0, 0, Width1, Height1, -1, -1, WindowHandle1)
dev_display (Image)
*显示继续信息
disp_continue_message (WindowHandle1, 'black', 'true')
stop()
*对图像进行阈值分割
binary_threshold (Image, Region1, 'max_separability', 'dark', UsedThreshold1)
*进行连通域处理
connection (Region1, ConnectedRegions1)
*使用特征筛选算子进行筛选
select_shape (ConnectedRegions1, SelectedRegions1, 'area', 'and', 5000, 99999)
*设置填充方式
dev_set_draw ('fill')
*设置显示颜色数量
dev_set_colored (12)
*显示填充后图像
dev_display (SelectedRegions1)
*获取区域角度信息
orientation_region (SelectedRegions1, Phi1)
*获取坐标信息
area_center (SelectedRegions1, Area1, Row1, Column1)
*设置线宽
dev_set_line_width (2)
*设置填充方式
dev_set_draw ('margin')
*设置箭头长度为80
arrow_length :=80
*显示箭头信息
disp_arrow (WindowHandle1, Row1, Column1, Row1-sin(Phi1)*arrow_length, Column1+cos(Phi1)*arrow_length, 2)
*显示中心坐标信息
disp_message (WindowHandle1, Row1+','+Column1, 'image', Row1, Column1, 'black', 'true')
2.5 PCB板上pad边界识别
关键算子:
fast_threshold算子:通过灰度值以及面积进行筛选
edges_sub_pix算子:获取图像边界亚像素
union_adjacent_contours_xld :将附近的轮廓进行链接
fit_rectangle2_contour_xld:拟合放射矩形
gen_rectangle2_contour_xld:生成仿射矩形
*读取一张图片
read_image (Image, 'die_pads')
*获取图像尺寸
get_image_size (Image, Width, Height)
*关闭窗口
dev_close_window ()
*显示图像
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
*自适应显示图像
dev_set_part (0, 0, Height, Width)
*显示图像
dev_display (Image)
*对图像进行fast_threshold
fast_threshold (Image, Region1, 170, 255, 25)
*连通域处理
connection (Region1, ConnectedRegions1)
*对图像进行fill_up处理
fill_up (ConnectedRegions1, RegionFillUp1)
*对图像进行特征选择
select_shape (RegionFillUp1, SelectedRegions1, 'area', 'and', 250, 99999)
*将区域合并成一个
union1 (SelectedRegions1, RegionUnion1)
*对区域进行膨胀处理
dilation_circle (RegionUnion1, RegionDilation1, 3.5)
*裁剪图片
reduce_domain (Image, RegionDilation1, ImageReduced1)
*获取亚像素边界
edges_sub_pix (ImageReduced1, Edges1, 'canny', 1, 20, 40)
*对亚像素边界进行筛选
select_shape_xld (Edges1, SelectedXLD1, 'area', 'and', 150, 99999)
*链接附近的边界
union_adjacent_contours_xld (SelectedXLD1, UnionContours1, 10, 1, 'attr_keep')
*使用仿射矩形进行拟合
fit_rectangle2_contour_xld (UnionContours1, 'regression', -1, 0, 0, 3, 2, Row1, Column1, Phi1, Length11, Length21, PointOrder1)
gen_rectangle2_contour_xld (Rectangle1, Row1, Column1, Phi1, Length11, Length21)
*显示矩形
dev_display (Rectangle1)
*在原始图像上进行显示
dev_display (Image)
dev_display (Rectangle1)
2.6 模板匹配算法
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
HObject ho_Image, ho_Rectangle, ho_ImageReduced;
HObject ho_ModelImages, ho_ModelRegions, ho_ModelContours;
HObject ho_Image2 = null, ho_Cross1 = null;
HTuple hv_WindowHandle = null, hv_Row11 = null;
HTuple hv_Column11 = null, hv_Row21 = null, hv_Column21 = null;
HTuple hv_ModelID = null, hv_Index = null, hv_Row3 = new HTuple();
HTuple image_shape_model;
private HDrawingObject draw_rectangle = new HDrawingObject();
private void button2_Click(object sender, EventArgs e)
{
HOperatorSet.SetColor(hWindowControl1.HalconWindow,"red");
HOperatorSet.SetDraw(hWindowControl1.HalconWindow,"margin");
HOperatorSet.DrawRectangle1(hWindowControl1.HalconWindow, out hv_Row11, out hv_Column11, out hv_Row21,out hv_Column21);
HOperatorSet.GenRectangle1(out ho_Rectangle, hv_Row11, hv_Column11, hv_Row21,hv_Column21);
HOperatorSet.ReduceDomain(ho_Image, ho_Rectangle, out ho_ImageReduced);
HOperatorSet.SetPart(hWindowControl2.HalconWindow, hv_Row11, hv_Column11, hv_Row21, hv_Column21);
HOperatorSet.DispObj(ho_ImageReduced,hWindowControl2.HalconWindow);
HOperatorSet.CreateShapeModel(ho_ImageReduced, "auto", (new HTuple(0)).TupleRad(), (new HTuple(1)).TupleRad(), 0.5, "auto", "use_polarity", "auto", "auto",out hv_ModelID);
//获得形状轮廓
HOperatorSet.FindShapeModel(ho_Image, hv_ModelID, 0, (new HTuple(1)).TupleRad(), 0.5, 0, 0.2, "least_squares", 1, 0.7, out hv_Row3, out hv_Column3, out hv_Angle1,out hv_Score1);
HOperatorSet.GenCrossContourXld(out ho_Cross1, hv_Row3, hv_Column3, 6, (new HTuple(45)).TupleRad());
HOperatorSet.DispObj(ho_Cross1, hWindowControl1.HalconWindow);
//draw_rectangle.CreateDrawingObjectRectangle1(100, 100, 150, 150);
//hWindowControl1.HalconWindow.AttachDrawingObjectToWindow(draw_rectangle);
//HDrawingObject.SetDrawingObjectCallback();
// Local iconic variables
//HOperatorSet.GenRectangle1(out ho_Rectangle, hv_Row11, hv_Column11, hv_Row21, hv_Column21);
//HOperatorSet.ReduceDomain(ho_Image, ho_Rectangle, out ho_ImageReduced);
//HOperatorSet.DispObj(ho_ImageReduced, hWindowControl1.HalconWindow);
}
HTuple hv_Column3 = new HTuple(), hv_Angle1 = new HTuple();
HTuple hv_Score1 = new HTuple();
HTuple image_width, image_height;
private HDrawingObject drawingObject = new HDrawingObject();
// Initialize local and output iconic variables
public Form1()
{
InitializeComponent();
}
public void initialze()
{
if (HDevWindowStack.IsOpen())
{
HOperatorSet.CloseWindow(HDevWindowStack.Pop());
}
//关闭变量更新
}
public void match_model()
{
string filenameimage = "C:\\Users\\Public\\Documents\\MVTec\\HALCON-17.12-Progress\\examples\\images\\wafer\\wafer_mirror_dies_01.png";
//读取图像
HOperatorSet.ReadImage(out ho_Image, filenameimage);
HOperatorSet.GetImageSize(ho_Image,out image_width,out image_height);
HOperatorSet.SetPart(hWindowControl1.HalconWindow, 0, 0, image_height, image_width);
HOperatorSet.DispObj(ho_Image, hWindowControl1.HalconWindow);
}
private void button1_Click(object sender, EventArgs e)
{
match_model();
}
}
}
2.6.1 C#设置控件焦点
在进行交互之前,一般情况下,可以在前面先设置好控件焦点,代码如下:
hWindowControl1.Focus();
如果不加上述内容的话,会导致在绘制ROI时,需要点击鼠标左键两下才能绘制处ROI区域
2.7 仿射变换
***重新编写模板匹配
read_image (Image2, 'G:/新建文件夹/halcon学习/image/board-03.png')
*获取图像尺寸
get_image_size (Image2, Width, Height)
*关闭窗口
dev_close_window ()
*打开窗口
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
*显示图像
dev_display (Image2)
*设置填充模式为边界
dev_set_draw ('margin')
*绘制模板匹配图像
draw_rectangle2 (WindowHandle, Row4, Column4, Phi2, Length12, Length22)
gen_rectangle2 (Rectangle3, Row4, Column4, Phi2, Length12, Length22)
*从图像上进行抠图操作
reduce_domain (Image2, Rectangle3, ImageReduced)
*显示抠下的图片
dev_display (ImageReduced)
*设置显示数量
dev_set_colored (12)
*选择最佳的金字塔层数
inspect_shape_model (ImageReduced, ModelImages, ModelRegions, 4, 30)
*创建模板匹配
create_shape_model (ImageReduced, 'auto', rad(0), rad(360), 'auto', 'auto', 'use_polarity', 'auto', 'auto', ModelID)
*获取匹配形状
find_shape_model (Image2, ModelID, rad(0), rad(360), 0.5, 1, 0, 'least_squares', 1, 0.7, Row5, Column5, Angle2, Score2)
*显示中心点
gen_cross_contour_xld (Cross, Row5, Column5, 10, rad(45))
*获得形状匹配形状
get_shape_model_contours (ModelContours1, ModelID, 1)
*显示形状图像
dev_clear_window ()
dev_display (Image2)
dev_display (ModelContours1)
dev_display (Cross)
*绘制矩形定位框
draw_rectangle2 (WindowHandle, Row6, Column6, Phi3, Length13, Length23)
gen_rectangle2 (Rectangle4, Row6, Column6, Phi3, Length13, Length23)
*计算定位框中心与模板匹配中心的距离
offrow:= Row6-Row5
offcolumn:= Column6-Column5
offangle:=Phi3-Angle2
*读取不同图像数据进行模拟视频拍摄
ImageFiles := []
ImageFiles[0] := 'G:/新建文件夹/image/board-01.png'
ImageFiles[1] := 'G:/新建文件夹//image/board-02.png'
ImageFiles[2] := 'G:/新建文件夹//image/board-03.png'
*进行循环读取图像并进行测试
for Index := 0 to |ImageFiles|-1 by 1
read_image (Image3, ImageFiles[Index])
*显示图像
dev_clear_window ()
dev_display (Image3)
*进行模板匹配
find_shape_model (Image3, ModelID, rad(0), rad(360), 0.5, 1, 0, 'least_squares', 1, 0.7, Row7, Column7, Angle3, Score3)
*创建仿射变换
hom_mat2d_identity (HomMat2DIdentity1)
*创建平移
hom_mat2d_translate (HomMat2DIdentity1, Row7, Column7,HomMat2DTranslate1)
*创建旋转
hom_mat2d_rotate (HomMat2DTranslate1, Angle3,Row7,Column7, HomMat2DRotate1)
*对识别轮廓进行仿射变换
affine_trans_contour_xld (ModelContours1, ContoursAffineTrans1, HomMat2DRotate1)
affine_trans_pixel (HomMat2DRotate1, offrow, offcolumn, RowTrans1, ColTrans1)
*对roi矩阵进行仿射变换
gen_rectangle2 (Rectangle5,RowTrans1, ColTrans1, Angle3+offangle, Length13, Length23)
*显示图像
dev_clear_window ()
dev_display (Image3)
dev_display (ContoursAffineTrans1)
dev_display (Rectangle5)
endfor
注意:
创建模板:
这里要注意的是,创建模板之后模板的位置变为(0,0)
,模板的当前角度也默认为0°
,在图像的左上角位置。