大家好,欢迎来到IT知识分享网。
目录
一、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 :)
间隙填充效果:
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°,在图像的左上角位置。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/118407.html















