Halcon的Blob分析 电脑版发表于:2024/5/7 11:25 ![](https://img.tnblog.net/arcimg/hb/0cebbc624ef24f6582d16debf7db6b30.png) >#Halcon的Blob分析 [TOC] 什么是Blob分析 ------------ tn2>图像处理(image processing),用计算机对图像进行分析,以达到所需结果的技术。又称影像处理。图像处理一般指数字图像处理。数字图像是指用工业相机、摄像机、扫描仪等设备经过拍摄得到的一个大的二维数组,该数组的元素称为像素,其值称为灰度值。图像处理技术一般包括图像压缩,增强和复原,匹配、描述和识别3个部分。<br/> Blob,即binary large object,二进制大型对象,是事务处理过程中遇到的一些大型的、复杂的数据项,必须作为一个完整的数据项看待。如一幅图形、一帧图像、一段语言等。在计算机视觉中的Blob是指图像中的具有相似颜色、纹理等特征所组成的一块连通区域。<br/> Blob分析(Blob Analysis)是对图像中相同像素的连通域进行分析(该连通域称为Blob)。其过程其实就是将图像进行二值化,分割得到前景和背景,然后进行连通区域检测,从而得到Blob块的过程。简单来说,blob分析就是在一块“光滑”区域内,将出现“灰度突变”的小区域寻找出来。<br/> Blob分析工具可以从背景中分离出目标,并可以计算出目标的数量、位置、形状、方向和大小,还可以提供相关斑点间的拓扑结构。在处理过程中不是对单个像素逐一分析,而是对图像的行进行操作。图像的每一行都用游程长度编码(RLE)来表示相邻的目标范围。这种算法与基于像素的算法相比,大大提高了处理的速度。<br/> 适用范围:针对二维目标图像和高对比度图像,适用于有无检测和缺陷检测。常用于二维目标图像、高对比度图像、存在/缺陷检测、数值范围和旋转不变性需求。显然,纺织品的瑕疵检测,玻璃的瑕疵检测,机械零件表面缺陷检测,可乐瓶缺陷检测,药品胶囊缺陷检测等很多场合都会用到blob分析。 Blob分析流程及常用算子 ------------ ### 基本步骤 tn2>Blob分析的基本步骤,这是一种理想状态,也是最基本的套路,获取图像->分割图像(区分前景像素和背景像素)->特征提取(比如面积、重心、旋转角度等)。 halcon代码实现如下: ```bash read_image(Image,'particle')//读取图像 threshold(Image, BrightPixels,120,255)//阈值分割算子 二值化 connection(BrightPixels,Particles)//断开联通区域 area_center(Particles,Area,Row,Column)//获取这个区域的中心和面积 ``` ![](https://img.tnblog.net/arcimg/hb/9c6d13e9ae7b4994b29be60d987df434.png) tn2>实际上,提取Blob之前和分析Blob之后也存在重要的步骤。比如,提取Blob之前一般要对图像进行预处理,比如图像的变换和校正、平滑与去噪、以及增强处理;分析Blob之后需要将Blob进行选取,或者将Blob重心的像素值向物理坐标系坐标值的转化。 因此,Blob实现方法需要具体情况具体分析。就拿阈值分割提取Blob而言,是用固定阈值还是动态阈值,这都是根据图片情况进行具体分析的。 ### 完整的Blob分析步骤 tn2>在实际应用中,Blob 的分割会很复杂,需要处理更多步骤。 其原因有多种,比如杂乱或不均匀的照明、图像中有很多杂斑(很难提取目标位)。 此外,对Blob进行后处理以获取客户需要的直观显示数据,例如将特征转换为真实世界单位或结果可视化。 ![](https://img.tnblog.net/arcimg/hb/4f12bc2ba6d0496087a7237fcaf66817.png) tn2>整个过程为:获取图像->应用ROI->定位ROI->矫正图像->图像预处理->动态获取分割参数->分割图像->处理区域->特征提取->将像素坐标转换到世界坐标->结果显示或者输出。 ![](https://img.tnblog.net/arcimg/hb/483fa56d9e4e44d39557878077cdaaf9.png) tn2>首先加载图片。 ```bash ** 关闭窗口更新,即在显示图像后不立即更新窗口,提高性能。 dev_update_window ('off') ** 关闭当前打开的窗口,清除窗口相关资源。 dev_close_window () ** 打开一个新窗口,大小为728x512,背景颜色为黑色,WindowID是窗口的标识符。 dev_open_window (0, 0, 728, 512, 'black', WindowID) ** 从文件 'die/die_03' 中读取图像数据到变量 Bond 中。读取的就是我上传的图片 read_image (Bond, 'die/die_03') ** 在当前打开的窗口中显示图像 Bond。 dev_display (Bond) ** 设置窗口中显示文本的字体属性,大小为14,字体为单色(单色意味着文本颜色不受当前显示图像的影响)。 set_display_font (WindowID, 14, 'mono', 'true', 'false') ** 在窗口中显示持续性消息,文本颜色为黑色。 disp_continue_message (WindowID, 'black', 'true') ** 停止当前程序的执行。 stop () ``` ![](https://img.tnblog.net/arcimg/hb/79f5784c3bea4545875bc3302c0a0293.png) ```bash *灰度处理 二值化 threshold (Bond, Bright, 100, 255) *形态学处理,一般用于定位,形状转换,rectangle2带方向的矩形 shape_trans (Bright, Die, 'rectangle2') ** 设置绘图颜色为绿色 dev_set_color ('green') ** 设置绘图线条宽度为 3 个像素 dev_set_line_width (3) ** 设置绘图时为图形边缘着色,这意味着绘制的矩形将在边缘处着色 dev_set_draw ('margin') ** 在当前窗口中显示处理后的图像Die dev_display (Die) ** 在窗口中显示持续性消息,文本颜色为黑色 disp_continue_message (WindowID, 'black', 'true') stop () ``` ![](https://img.tnblog.net/arcimg/hb/0aaa36bad4dc4fe7a39c09ec6c7fc4e2.png) ```bash *区域锁定 将图像 Bond 限制在矩形区域 Die 内,并将结果存储在 DieGrey 中。 reduce_domain (Bond, Die, DieGrey) *再次二值化 对图像 DieGrey 进行二值化处理,将灰度值在 0 到 50 之间的像素设为白色,其他设为黑色,结果存储在 Wires 中。 threshold (DieGrey, Wires, 0, 50) *用给定的形状特征填充区域:面积为1~100的区域 fill_up_shape (Wires, WiresFilled, 'area', 1, 100) ** 在当前窗口中显示图像 Bond。 dev_display (Bond) ** 设置绘图模式为填充模式。 dev_set_draw ('fill') ** 设置绘图颜色为红色。 dev_set_color ('red') ** 在当前窗口中显示填充后的图像 WiresFilled。 dev_display (WiresFilled) ** 在窗口中显示持续性消息,文本颜色为黑色。 disp_continue_message (WindowID, 'black', 'true') stop () ``` ![](https://img.tnblog.net/arcimg/hb/12cfcdc1777b49d6b94d0d2c9cf091f3.png) ```bash *形态学处理:此处为开运算/(也可以用腐蚀),减少像素,circle–对圆形作用最大 *形态学 腐蚀 * erosion_circle (WiresFilled, RegionErosion, 15.5) *形态学 膨胀 * dilation_circle (RegionErosion, RegionDilation, 15.5) *形态学 开运算(效果同上 先腐蚀后膨胀 先变小再变大) opening_circle (WiresFilled, Balls, 15.5) dev_set_color ('green') dev_display (Balls) disp_continue_message (WindowID, 'black', 'true') stop () ``` ![](https://img.tnblog.net/arcimg/hb/2b2924d7a59a4909adbe1a179869f839.png) ![](https://img.tnblog.net/arcimg/hb/13cba6f255534b27bf3fe27487fc0496.png) tn2>我们可以看到矩形的面积为2418,而圆形的面积只在1000多点左右,所以我们可以通过的它的大小范围来进行提取特征值。 这里设置了`800-1200`的范围。 ```bash *将二值化分开的区域划分为不同的连通区域,断成不同的区域,方便后面作特征值提取处理 connection (Balls, SingleBalls) *特征值提取 * select_shape (SingleBalls, IntermediateBalls, 'circularity', 'and', 0.85, 1.0) ** 根据形状的面积选择区域,将面积在 800 到 1200 之间的形状选出,结果存储在 IntermediateBalls 中。 select_shape (SingleBalls, IntermediateBalls, 'area', 'and', 800, 1200) ** 对 IntermediateBalls 中的形状按照其第一个点的位置进行排序,排序方式为按照列顺序,结果存储在 FinalBalls 中。 sort_region (IntermediateBalls, FinalBalls, 'first_point', 'true', 'column') ** 在当前窗口中显示图像 Bond。 dev_display (Bond) ** 设置彩色显示,可能是指定一种颜色的显示。 dev_set_colored (12) ** 在当前窗口中显示 FinalBalls。 dev_display (FinalBalls) ** 在窗口中显示持续性消息,文本颜色为黑色。 disp_continue_message (WindowID, 'black', 'true') stop () ``` ![](https://img.tnblog.net/arcimg/hb/b8a08bff052247279b793eab5b14bb1e.png) ```bash ** 计算 FinalBalls 中每个形状的最小外接圆,结果的圆心坐标存储在 (Row, Column) 中,半径存储在 Radius 中。 smallest_circle (FinalBalls, Row, Column, Radius) ** 计算最小外接圆的数量,即形状的数量。 NumBalls := |Radius| ** 计算最小外接圆的直径。 Diameter := 2 * Radius ** 计算最小外接圆直径的平均值。 meanDiameter := mean(Diameter) ** 计算最小外接圆直径的最小值。 minDiameter := min(Diameter) ** 在当前窗口中显示图像 Bond。 dev_display (Bond) ** 在窗口中显示最小外接圆。 disp_circle (WindowID, Row, Column, Radius) ** 设置绘图颜色为白色。 dev_set_color ('white') ** 在窗口中显示形状直径信息。 disp_message (WindowID, 'D: ' + Diameter$'.4', 'image', Row - 2 * Radius, Column, 'white', 'false') ** 恢复窗口的更新功能,即重新启用窗口的更新。 dev_update_window ('on') ``` ![](https://img.tnblog.net/arcimg/hb/54073d1632ea4f06bbe64742c9479012.png) ### 常见特征提取 tn2>1)、区域特征: a:面积area; b:力矩Moments; c:平行于主轴的最小矩形smallest_rectangle1; d:任意方向的最小矩形smallest_rectangle2; e:最小圆形smallest_circle; f:凸包面积convexity; g:contlength区域边界长度; h:圆形roundness; j:圆度circularity; k:紧密度compactness; l:矩形度rectangularity;<br/> 2)、灰度特征 a:简单灰度值特征:区域的平均灰度值; b:区域的最小和最大灰度值; ### 常用算子总结 tn2>1)、图像预处理常用算子: a:mean_image:均值滤波 b:gauss_image:高斯滤波 c:median_image:中值滤波<br/> 2)、动态获取分割参数常用算子: a:gray_histo_abs:灰度直方图 b:histo_to_thresh:直方图二值化 ### 开运算和闭运算(形态学) tn2>图像分割时,会用到开运算和闭运算,采用不同的分割策略,效果会不一样,这里仅先介绍下概念。 1)、开运算 先腐蚀后膨胀; 2)、闭运算 先膨胀后腐蚀; 3)、腐蚀; 4)、膨胀。<br/> 开运算和闭运算要用到的算子如下: 1)、开运算 opening(ConnectedRegions, ConnectedRegions, RegionOpening1) 2)、闭运算 closing(RegionOpening1, RegionOpening1, RegionClosing1) 3)、腐蚀 erosion1(RegionClosing1, RegionClosing1, RegionErosion1, 1) 4)、膨胀 dilation1(RegionErosion1, RegionErosion1, RegionDilation1, 1) 5)、圆形结构开运算 opening_circle(ConnectedRegions, RegionOpening, 3.5) 6)、圆形结构闭运算 closing_circle(RegionOpening, RegionClosing, 3.5) 7)、圆形结构腐蚀 erosion_circle(RegionClosing, RegionErosion, 3.5) 8)、圆形结构膨胀 dilation_circle(RegionErosion, RegionDilation, 3.5) Blob分析案例说明 ------------ ### 豆子分割统计(形态学案例) tn2>加载我们的图像。 ```bash * 采集图像操作 ** 关闭图像更新,提高处理效率。 dev_update_off () ** 读取图像 'pellets'。 read_image (Image, 'pellets') ** 关闭当前窗口。 dev_close_window () ** 获取图像尺寸。 get_image_size (Image, Width, Height) ** 打开窗口,设置窗口大小和背景颜色。 dev_open_window (0, 0, Width, Height, 'black', WindowID) ** 设置显示区域。 dev_set_part (0, 0, Height - 1, Width - 1) ** 设置显示字体。 set_display_font (WindowID, 16, 'mono', 'true', 'false') ** 设置彩色显示。 dev_set_colored (6) ** 设置绘图模式为边缘绘制。 dev_set_draw ('margin') ** 设置绘图线条宽度。 dev_set_line_width (3) ** 在窗口中显示图像。 dev_display (Image) ** 在窗口中显示消息。 disp_message (WindowID, 'Detect each single pellet', 'window', 12, 12, 'black', 'true') ** 在窗口中显示持续性消息。 disp_continue_message (WindowID, 'black', 'true') ** 停止程序执行。 stop () ``` ![](https://img.tnblog.net/arcimg/hb/3eae21fc5d6d439ba33326ec5634785d.png) ```bash * 从背景分割颗粒的区域 ** 对图像进行二值化。 binary_threshold (Image, LightRegion, 'max_separability', 'light', UsedThreshold) ** 对二值化图像进行开运算。 opening_circle (LightRegion, Region, 3.5) ** 在窗口中显示分割结果。 dev_display (Region) ** 在窗口中显示消息。 disp_message (WindowID, 'First, segment the pellets', 'window', 12, 12, 'black', 'true') ** 在窗口中显示持续性消息。 disp_continue_message (WindowID, 'black', 'true') ** 停止程序执行。 stop () ``` ![](https://img.tnblog.net/arcimg/hb/07fb671dd5c84a78b2fecaea2d13e6ae.png) ```bash * 第一次分割出颗粒区域,只是分割处理而已不能进行统计 ** 进行连通性分析。 connection (Region, ConnectedRegionsWrong) ** 在窗口中显示图像和连通区域。 dev_display (Image) dev_display (ConnectedRegionsWrong) ** 在窗口中显示消息。 disp_message (WindowID, 'Simple connection fails', 'window', 12, 12, 'black', 'true') ** 在窗口中显示持续性消息。 disp_continue_message (WindowID, 'black', 'true') ** 停止程序执行。 stop () ``` ![](https://img.tnblog.net/arcimg/hb/8783410d8094422988adc2794eb98b83.png) tn2>我们可以发现进行开运算后(先腐蚀再扩大),再进行添加颜色,发现有很多是关联在一起的。 如果不希望关联在一起,我们可以先腐蚀再添加颜色,最后再扩大。 ```bash * 通过腐蚀的方式来分割出每个区域 ** 对图像进行腐蚀操作。 erosion_circle (Region, RegionErosion, 7.5) ** 在窗口中显示图像和腐蚀结果。 dev_display (Image) dev_display (RegionErosion) ** 在窗口中显示消息。 disp_message (WindowID, 'Erosion of the pellet regions', 'window', 12, 12, 'black', 'true') ** 在窗口中显示持续性消息。 disp_continue_message (WindowID, 'black', 'true') ** 停止程序执行。 stop () ``` ![](https://img.tnblog.net/arcimg/hb/b35dc0b797764c9099cdfcbf99de5d94.png) ```bash * 在次分割连通区域 ** 进行连通性分析。 connection (RegionErosion, ConnectedRegions) ** 在窗口中显示图像和连通区域。 dev_display (Image) dev_display (ConnectedRegions) ** 在窗口中显示消息。 disp_message (WindowID, 'Perform connection now', 'window', 12, 12, 'black', 'true') ** 在窗口中显示持续性消息。 disp_continue_message (WindowID, 'black', 'true') ** 停止程序执行。 stop () ``` ![](https://img.tnblog.net/arcimg/hb/753d234c6c254dcb8c5cde69e0669a85.png) ```bash * 通过应用膨胀使其恢复到原始颗粒大小 ** 对图像进行膨胀操作。 dilation_circle (ConnectedRegions, RegionDilation, 7.5) * 统计颗粒数量 ** 统计连通区域数量。 count_obj (RegionDilation, Number) ** 在窗口中显示图像和膨胀结果。 dev_display (Image) dev_display (RegionDilation) ** 在窗口中显示消息和颗粒数量。 disp_message (WindowID, Number + ' pellets detected', 'window', 12, 12, 'black', 'true') ``` ![](https://img.tnblog.net/arcimg/hb/91c8cfd7a4534087983e9efb6edf374d.png) ### 木材统计(形态学) ```bash *读取图像 read_image(image,'D:/ai/Halcon/vedio/061--机器视觉Course061Halcon的Blob图像分析/素材与源码/wood.jpg') *图像转灰度 rgb1_to_gray(image,grayimage) *阈值分割 threshold (grayimage, regions, 60, 255) *开运算 opening_rectangle1(regions,Cut,2,7) *打断非连通区域 connection(Cut,connectedregions) *面积筛选 select_shape (connectedregions, SelectedRegions, 'area', 'and', 391.24, 20056.3) *数出第一个部分木材个数 count_obj(SelectedRegions,Number1) *面积筛选 select_shape (connectedregions, SelectedRegions1, 'area', 'and', 24334.9, 100000) *腐蚀运算 erosion_circle(SelectedRegions1,regionerosion1,7.5) *打断非连通区域 connection(regionerosion1,connectedregions1) *面积筛选 select_shape (connectedregions1, SelectedRegions2, 'area', 'and', 2707.36, 20000) *数出第二个部分木材个数 count_obj(SelectedRegions2,Number2) *将第一个部分和第二个部分合并 concat_obj(SelectedRegions,SelectedRegions2,objectsconcat) *数出合并部分总木材个数 count_obj(objectsconcat,Number3) ``` ![](https://img.tnblog.net/arcimg/hb/9cb06804f4ea4d37ba6bca2044500d57.png) tn2>看到Number3给出了木头的总数。 ### 车牌的字符分割(数字与字母) tn2>首先读取图片 ```bash ***** 读取图片 ** 关闭当前窗口。 dev_close_window () ** 读取图像 '素材/chepai18.jpg'。 read_image (Image, 'D:/ai/Halcon/vedio/061--机器视觉Course061Halcon的Blob图像分析/素材与源码/chepai18.jpg') ** 打开窗口并适应图像大小。 dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) ** 在窗口中显示图像。 dev_display (Image) ``` tn2>然后我们对图片进行二值化操作,并对灰度图进行阈值化处理 ```bash ***** 处理图片-定位车牌 ** 将图像转换为灰度图像。 rgb1_to_gray (Image, GrayImage) ** 对灰度图像进行阈值化。 threshold (GrayImage, Region, 80, 100) ** 对图像进行连通性分析。 connection (Region, ConnectedRegions) ** 根据区域面积选择形状。 select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 8870.97, 10000) ``` ![](https://img.tnblog.net/arcimg/hb/d881baf710014d7bb90a9c9a874bd30f.png) ```bash ***** 处理图片- 转正图片 ** 对选定的区域进行形状转换。 shape_trans (SelectedRegions, RegionTrans, 'rectangle2') ** 计算区域的中心和方向。 area_center (RegionTrans, Area, Row, Column) orientation_region (RegionTrans, Phi) ** 将区域校正为水平状态。 vector_angle_to_rigid (Row, Column, Phi, Row, Column, rad(0), HomMat2D) hom_mat2d_slant (HomMat2D, rad(15), 'x', Column, Row, HomMat2DSlant) affine_trans_region (RegionTrans, RegionAffineTrans, HomMat2DSlant, 'nearest_neighbor') affine_trans_image (Image, ImageAffineTrans, HomMat2DSlant, 'constant', 'false') reduce_domain (ImageAffineTrans, RegionAffineTrans, ImageReduced) ``` ![](https://img.tnblog.net/arcimg/hb/250c7115517141ddb8b649cb46c887cb.png) ```bash *************** 开始识别之车牌图片预处理 ** 将图像转换为灰度图像。 rgb1_to_gray (ImageReduced, GrayImage1) ** 对灰度图像进行阈值化。 threshold (GrayImage1, Region1, 128, 255) ** 对区域进行腐蚀操作。 erosion_rectangle1 (Region1, RegionErosion, 3, 3) ** 对区域进行开运算。 opening_rectangle1 (RegionErosion, RegionOpening, 1, 3) ** 对图像进行连通性分析。 connection (RegionOpening, ConnectedRegions1) ** 根据区域面积选择形状。 select_shape (ConnectedRegions1, SelectedRegions1, 'area', 'and', 200, 500) ** 根据字符在车牌中的位置进行排序。 sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'column') ``` ![](https://img.tnblog.net/arcimg/hb/1a1018be16c949de8d925db7752c894a.png) tn2>select_shape(Regions : SelectedRegions : Features, Operation, Min, Max : ) (将连接的区域进行筛选,筛选的特征有很多,如面积长度等,可以去掉不满足条件的轮廓) 描述: 操作符select_shape根据形状选择区域。对于来自区域的每个输入区域,计算所指示的特征(features)。如果计算特征的每个(Operation=‘and’)或至少一个(Operation=‘or’)在默认限制(最小值、最大值)内,则该区域将适应输出(复制)。 条件:Min_i <= Feature_i(Object) <= Max_i ### 功能特征的取值 |特征|英|译|备注| | ------------ | ------------ | ------------ | ------------ | |area|Area of the object|对象的面积 | |row|Row index of the center|中心点的行坐标 | |column|Column index of the center|中心点的列坐标 | |width|Width of the region|区域的宽度 | |height|Height of the region|区域的高度 | |row1|Row index of upper left corner|左上角行坐标 | |column1|Column index of upper left corner|左上角列坐标 | |row2|Row index of lower right corner|右下角行坐标 | |column2|Column index of lower right corner|右下角列坐标 | |circularity|Circularity|圆度|0~1| |compactness|Compactness|紧密度|0~1| |contlength|Total length of contour |轮廓线总长 | |convexity|Convexity|凸性 | |rectangularity|Rectangularity|矩形度 0~1| |ra|Main radius of the equivalent ellipse|等效椭圆长轴半径长度 | |rb|Secondary radius of the equivalent ellipse|等效椭圆短轴半径长度 | |phi|Orientation of the equivalent ellipse|等效椭圆方向 | |anisometry|Anisometry|椭圆参数,Ra/Rb长轴与短轴的比值| |bulkiness|Bulkiness|椭圆参数,蓬松度π*Ra*Rb/A| |struct_factor|Structur Factor|椭圆参数,`Anisometry*Bulkiness-1` | |outer_radius|Radius of smallest surrounding circle|最小外接圆半径 | |inner_radius|Radius of largest inner circle|最大内接圆半径 | |inner_width|Width of the largest axis-parallel rectangle that fits into the region|最大内接矩形宽度| |inner_height|Height of the largest axis-parallel rectangle that fits into the region|最大内接矩形高度 | |dist_mean|Mean distance from the region border to the center|区域边界到中心的平均距离 | |dist_deviation|Deviation of the distance from the region border from the center|区域边界到中心距离的偏差| |roundness|Roundness|圆度,与circularity计算方法不同 | |num_sides|Number of polygon sides|多边形边数 | |connect_num|Number of connection components|连通数 | |holes_num|Number of holes|区域内洞数| |area_holes|Area of the holes of the object|所有洞的面积 | |max_diameter|Maximum diameter of the region|最大直径 | |orientation|Orientation of the region|区域方向 | |euler_number|Euler number|欧拉数,即连通数和洞数的差| |rect2_phi|Orientation of the smallest surrounding rectangle|最小外接矩形的方向 | |rect2_len1|Half the length of the smallest surrounding rectangle|最小外接矩形长度的一半 smallest_rectangle2| |rect2_len2|Half the width of the smallest surrounding rectangle|最小外接矩形宽度的一半 | |moments_m11|Geometric moments of the region|几何矩 | |moments_m20|Geometric moments of the region|几何矩 | |moments_m02|Geometric moments of the region|几何矩 | |moments_ia|Geometric moments of the region|几何矩 | |moments_ib|Geometric moments of the region|几何矩 | |moments_m11_invar|Geometric moments of the region|几何矩 | |moments_m20_invar|Geometric moments of the region|几何矩 | |moments_m02_invar|Geometric moments of the region|几何矩 | |moments_phi1|Geometric moments of the region|几何矩| |moments_phi2|Geometric moments of the region|几何矩| |moments_m21|Geometric moments of the region|几何矩| |moments_m12|Geometric moments of the region|几何矩| |moments_m03|Geometric moments of the region|几何矩| |moments_m30|Geometric moments of the region|几何矩| |moments_m21_invar|Geometric moments of the region|几何矩| |moments_m12_invar|Geometric moments of the region|几何矩| |moments_m03_invar|Geometric moments of the region|几何矩| |moments_m30_invar|Geometric moments of the region|几何矩| |moments_i1|Geometric moments of the region|几何矩| |moments_i2|Geometric moments of the region|几何矩| |moments_i3|Geometric moments of the region|几何矩| |moments_i4|Geometric moments of the region|几何矩| |moments_psi1|Geometric moments of the region|几何矩| |moments_psi2|Geometric moments of the region|几何矩| |moments_psi3|Geometric moments of the region|几何矩| |moments_psi4|Geometric moments of the region|几何矩| ### 车牌字符分割带中文(中文、数字、字母) ```bash ***** 读取图片 dev_close_window () read_image (Image, 'D:/ai/Halcon/vedio/061--机器视觉Course061Halcon的Blob图像分析/素材与源码/chepai18.jpg') dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) dev_display (Image) ***** 处理图片-定位车牌 rgb1_to_gray (Image, GrayImage) threshold (GrayImage, Region, 80, 100) connection (Region, ConnectedRegions) select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 8870.97, 10000) ***** 处理图片- 转正图片 shape_trans (SelectedRegions, RegionTrans, 'rectangle2') area_center (RegionTrans, Area, Row, Column) orientation_region (RegionTrans, Phi) vector_angle_to_rigid (Row, Column, Phi, Row, Column, rad(0), HomMat2D) hom_mat2d_slant (HomMat2D, rad(15), 'x', Column, Row, HomMat2DSlant) affine_trans_region (RegionTrans, RegionAffineTrans, HomMat2DSlant, 'nearest_neighbor') affine_trans_image (Image, ImageAffineTrans, HomMat2DSlant, 'constant', 'false') reduce_domain (ImageAffineTrans, RegionAffineTrans, ImageReduced) *************** 开始识别之车牌图片预处理,带中文字符分割 rgb1_to_gray (ImageReduced, GrayImage1) threshold (GrayImage1, Regions, 176, 242) closing_circle (Regions, RegionClosing, 3.5) opening_circle (Regions, RegionOpening, 1.7) connection (RegionOpening, ConnectedRegions1) select_shape (ConnectedRegions1, SelectedRegions1, 'area', 'and', 20, 600) sort_region (SelectedRegions1, SortedRegions, 'character', 'true', 'column') *************** 组装苏字区域 select_obj (SortedRegions, ObjectSelected1, 1) select_obj (SortedRegions, ObjectSelected2, 2) select_obj (SortedRegions, ObjectSelected3, 3) union2 (ObjectSelected1, ObjectSelected2, RegionUnion) union2 (RegionUnion, ObjectSelected3, RegionUnion1) select_obj (SortedRegions, ObjectSelected4, 4) select_obj (SortedRegions, ObjectSelected5, 5) select_obj (SortedRegions, ObjectSelected6, 6) select_obj (SortedRegions, ObjectSelected7, 7) select_obj (SortedRegions, ObjectSelected8, 8) select_obj (SortedRegions, ObjectSelected9, 9) ***************** 把所有区域组成一个对象 gen_empty_obj (NumberObject) concat_obj (NumberObject, RegionUnion1, NumberObject) concat_obj (NumberObject, ObjectSelected4, NumberObject) concat_obj (NumberObject, ObjectSelected5, NumberObject) concat_obj (NumberObject, ObjectSelected6, NumberObject) concat_obj (NumberObject, ObjectSelected7, NumberObject) concat_obj (NumberObject, ObjectSelected8, NumberObject) concat_obj (NumberObject, ObjectSelected9, NumberObject) **************** 创建训练文件 TrainFile:='D:/ai/Halcon/vedio/061--机器视觉Course061Halcon的Blob图像分析/素材与源码/code/Charactor.trf' Words:=['苏','E','C','6','2','N','8'] ** 完成图像与字符训练对应关系 write_ocr_trainf (NumberObject, GrayImage1, Words, TrainFile) ** 读取训练文件 read_ocr_trainf_names (TrainFile, CharacterNames, CharacterCount) ** 创建一个分类识别器 create_ocr_class_mlp (8, 10, 'constant', 'default', CharacterNames, 80, 'none', 10, 42, OCRHandle) ** 训练分类识别器 trainf_ocr_class_mlp (OCRHandle, TrainFile, 200, 1, 0.01, Error, ErrorLog) ** 保存分类识别文件 write_ocr_class_mlp (OCRHandle, 'D:/ai/Halcon/vedio/061--机器视觉Course061Halcon的Blob图像分析/素材与源码/code/Charactor.omc') *********************** 基于训练omc文件开始识别带中文车牌************** read_ocr_class_mlp ('D:/ai/Halcon/vedio/061--机器视觉Course061Halcon的Blob图像分析/素材与源码/code/Charactor.omc', OCRHandle1) do_ocr_multi_class_mlp (NumberObject, GrayImage1, OCRHandle1, Class, Confidence) dev_clear_window () dev_display (Image) dev_set_color ('red') set_display_font (WindowHandle, 30, 'mono', 'true', 'false') for Index := 0 to |Class|-1 by 1 set_tposition (WindowHandle,30, 120+36*Index) write_string (WindowHandle, Class[Index]) endfor ``` ![](https://img.tnblog.net/arcimg/hb/63674c582075474fa4ef103e567920dc.png) ### 统计每个骰子的点数(距离变换+分水岭) ```bash ** 关闭当前窗口。 dev_close_window () ** 打开一个新窗口,设置窗口大小和背景颜色。 dev_open_window (0, 0, 500, 500, 'black', WindowHandle) ** 设置显示字体。 set_display_font (WindowHandle, 30, 'mono', 'true', 'false') ** 列出指定目录下的所有文件。 list_files ('D:/ai/Halcon/vedio/061--机器视觉Course061Halcon的Blob图像分析/素材与源码/dice/', ['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) ** 初始化结果索引。 ResultIndex:=1 ** 遍历图像文件列表。 for Index := 0 to |ImageFiles| - 1 by 1 ** 读取图像文件。 read_image (Image, ImageFiles[Index]) ** 获取图像尺寸。 get_image_size (Image, Width, Height) ** 对图像进行预处理 ** 对图像进行阈值化。 threshold (Image, Regions, 180, 255) ** 填充区域。 fill_up (Regions, RegionFillUp) ** 进行连通性分析。 connection (RegionFillUp, ConnectedRegions) ** 计算距离变换。 distance_transform (ConnectedRegions, DistanceImage, 'octagonal', 'true', 1000, 1000) ** 转换图像类型为 BYTE。 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_shape (RegionIntersection, SelectedRegions, 'area', 'and', 30000, 100000) ** 统计选定区域数量。 count_obj (SelectedRegions, Number) ** 在窗口中显示原始图像。 dev_display (Image) ** 遍历每个选定区域。 for Index1 := 1 to Number by 1 ** 选择指定的区域。 select_obj (SelectedRegions, ObjectSelected, Index1) ** 缩小图像域。 reduce_domain (Image, ObjectSelected, ImageReduced) ** 对缩小后的图像进行阈值化。 threshold (ImageReduced, Regions1, 0, 150) ** 填充区域。 fill_up (Regions1, RegionFillUp1) ** 进行连通性分析。 connection (RegionFillUp1, ConnectedRegions1) ** 根据面积选择形状。 select_shape (ConnectedRegions1, SelectedRegions1, 'area', 'and', 200, 20000) ** 统计选定区域数量。 count_obj (SelectedRegions1, Number1) ** 计算区域中心。 area_center (ObjectSelected, Area, Row, Column) ** 在图像中显示消息。 disp_message (WindowHandle, Number1, 'image', Row, Column, 'green', 'false') endfor ** 停止程序执行。 stop() endfor ``` ![](https://img.tnblog.net/arcimg/hb/019e3d7c105845e59ab0777af2384217.png)