Advertisement

halcon之缺陷检测2

阅读量:

1,检查瓶子标签是否凸起,褶皱。

photometric_stereo

用于光度立体法三维表面重建的核心算子,通过多光源下的图像数据计算物体表面的高度场、梯度及反射率信息。以下是对该算子的详细解析:


1. ‌功能概述

photometric_stereo 基于 Woodham 算法,利用至少三张不同光照方向下的图像,通过光度立体技术重建物体表面的局部梯度信息,并综合为高度场(HeightField)或反射率图(Albedo)。其核心假设包括:

  • 正交投影 ‌:需使用远心镜头或长焦镜头以避免图像畸变。
  • 朗伯反射 ‌:物体表面需为漫反射材质,镜面反射区域会导致错误结果。
  • 平行光源 ‌:需使用远心光源或远距离点光源保证光线均匀性。

2. ‌核心参数

  • 输入参数 ‌:

    • Images:至少包含三张相同视角、不同光照方向的图像数组。
    • SlantsTilts:分别表示光源的倾斜角和方位角(以弧度为单位)。
  • 输出参数 ‌:

    • HeightField:高度场图像,表示表面相对高度。
    • Gradient:梯度图像,包含表面法向量的局部梯度信息。
    • Albedo:反射率图像,反映物体表面材质的光吸收特性。
  • 关键选项 ‌:

    • ResultType:控制输出类型(如高度场或梯度)。
    • ReconstructionMethod:选择重建算法(默认基于最小二乘法)。

3. ‌典型应用场景

  • 表面缺陷检测 ‌:通过梯度或高度场差异识别微小表面缺陷。
  • 打印质量检查 ‌:排除光照角度对非平面字符检测的影响。
  • 纹理分离 ‌:分离反照率信息以消除阴影干扰。

4. ‌技术限制

  • 非绝对高度重建 ‌:仅能计算相对高度,无法替代激光三角测量或结构光等绝对三维重建方法3。
  • 硬件要求严格 ‌:需远心镜头、固定视角相机及可控光源系统。
  • 材质限制 ‌:镜面或高光表面区域会导致重建错误。

5. ‌采集设置要求

  1. 相机配置 ‌:

    • 使用远心镜头,且相机光轴与物体表面正交。
    • 拍摄过程中相机与物体位置需完全固定。
  2. 光源要求 ‌:

    • 至少三种不同光照方向(通过调整 SlantsTilts 参数定义)。
    • 光源需保持平行且强度均匀。

6. ‌与其他3D重建方法的对比

方法 优势 局限性
光度立体法 无需图像匹配,适合高精度表面细节重建 依赖严格光照条件,仅支持相对高度
激光三角测量 可重建绝对高度,抗干扰性强 设备成本高,不适合大面积检测
立体视觉 适合动态场景,支持绝对深度 依赖特征匹配,计算复杂度高

通过合理配置光源和相机参数,并结合反照率与梯度信息,photometric_stereo 在工业检测与质量控制中展现出高精度表面分析能力。

derivate_vector_field

用于处理矢量场的关键算子,通过高斯导数卷积提取矢量场的局部特征。以下是其核心功能、参数及应用场景的详细解析:


1. ‌功能概述

derivate_vector_field 对输入的矢量场(vector_field_relative 类型)执行高斯导数卷积,并计算基于梯度的特征参数(如曲率、散度等)。其核心功能包括:

  • 高斯平滑 ‌:通过指定 Sigma 参数对矢量场进行高斯滤波,抑制噪声干扰。
  • 特征提取 ‌:根据 Component 参数输出不同类型的特征图像(如平均曲率、旋度等),适用于表面几何特性分析。
  • 适用性限制 ‌:仅支持语义类型为 vector_field_relative 的矢量场输入,其他类型(如绝对矢量场)需先转换。

2. ‌核心参数

  • 输入参数 ‌:

    • VectorField:输入矢量场,需通过 real_to_vector_fieldoptical_flow_mg 等算子生成26。
    • Sigma:高斯核标准差,控制平滑程度,值越大平滑效果越显著。
    • Component:指定输出特征类型,可选值包括:
      • mean_curvature:平均曲率(常用于表面缺陷检测)。
      • divergence/curl:散度或旋度(用于流体力学或变形分析)。
  • 输出参数 ‌:

    • Result:特征图像,数据类型为浮点数(real)。

3. ‌典型应用场景

  • 缺陷检测 ‌:通过计算表面梯度场的平均曲率(mean_curvature),识别凹痕、划痕等局部几何异常。
  • 变形分析 ‌:在图像拼接或模拟随机局部变形时,结合 gen_random_vector_field 生成随机矢量场,并通过本算子分析形变特征。
  • 光流处理 ‌:与 optical_flow_mg 配合,提取光流场的散度或旋度信息,用于运动场可视化或动态场景分析。

4. ‌技术限制

  • 输入类型限制 ‌:仅接受 vector_field_relative 类型矢量场,需确保输入数据格式正确。
  • 噪声敏感性 ‌:当原始矢量场噪声较大时,需增大 Sigma 值以平滑噪声,但可能牺牲细节分辨率。
  • 计算资源消耗 ‌:处理高分辨率矢量场时需较高内存和计算性能。
复制代码
 *参考案例库:inspect_shampoo_label_photometric_stereo.hdev

    
  
    
 *目的:
    
 *使用光学立体技术检查标签是否褶皱、凸起
    
  
    
 *要求:
    
 *图像需要使用配置远心镜头的相机采集,避免深度畸变。
    
  
    
 * Initialization
    
 dev_close_window ()
    
 dev_update_off ()
    
 dev_open_window (0, 0, 640, 512, 'black', WindowHandle)
    
 set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
    
 Message := 'Inspect the label of a shampoo bottle'
    
 Message[1] := 'using photometric stereo. In this case four'
    
 Message[2] := 'different light orientations were used.'
    
 disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
    
 disp_continue_message (WindowHandle, 'black', 'true')
    
 stop ()
    
 * * Show input images with different illumination
    
 read_image (Images, 'photometric_stereo/shampoo_label_0' + [1:4])
    
 for I := 1 to 4 by 1
    
     Message := 'Acquire image ' + I + ' of 4'
    
     select_obj (Images, ObjectSelected, I)
    
     dev_display (ObjectSelected)
    
     disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
    
     wait_seconds (0.5)
    
 endfor
    
 * *倾斜角
    
 Tilts := [6.1,95.0,-176.1,-86.8]
    
 *方位角
    
 Slants := [41.4,42.6,41.7,40.9]
    
 *gradient:倾斜率,albedo:反射率
    
 ResultType := ['gradient','albedo']
    
 *根据光影立体技术创建一个表面
    
 photometric_stereo (Images, HeightField, Gradient, Albedo, Slants, Tilts, ResultType, 'poisson', [], [])
    
 * * Display the albedo image
    
 dev_display (Albedo)
    
 disp_message (WindowHandle, 'Albedo image', 'window', 12, 12, 'black', 'true')
    
 disp_continue_message (WindowHandle, 'black', 'true')
    
 stop ()
    
 * *计算表面的高斯曲率
    
 *使用梯度场作为运算符的输入
    
 *缺陷通常很容易在曲率图像中检测到。
    
 derivate_vector_field (Gradient, MeanCurvature, 1.0, 'mean_curvature')
    
 * * Detect defects
    
 * * Segment the tablet areas in the curvature image
    
 threshold (MeanCurvature, Region, -10, -0.07)
    
 opening_circle (Region, RegionOpening, 1)
    
 connection (RegionOpening, ConnectedRegions)
    
 select_shape (ConnectedRegions, Defects, 'area', 'and', 50, 99999)
    
 shape_trans (Defects, Circle, 'outer_circle')
    
 * Display the defects in curvature image
    
 dev_set_draw ('margin')
    
 dev_set_color ('red')
    
 dev_set_line_width (2)
    
 dev_display (MeanCurvature)
    
 dev_display (Circle)
    
 Message := 'The defect can easily be detected'
    
 Message[1] := 'in the surface curvature image'
    
 disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
    
 stop ()
    
 * Display the defects in the albedo image
    
 dev_set_draw ('margin')
    
 dev_set_color ('red')
    
 dev_display (Albedo)
    
 dev_display (Circle)
    
 disp_message (WindowHandle, 'Defect in albedo image', 'window', 12, 12, 'black', 'true')
    
    
    
    
    XML
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/MqjgoRdnzNhJwt5XSVb7r8A1c9iW.png)

2,Board线路焊接检查。

复制代码
 *参考案例库:board.hdev

    
 *目的:
    
 *检查电路板焊锡缺失的位置
    
 *原理:
    
 *合并计算多张在不同角度拍摄的电路板图像,查找出焊锡边缘(亮处)
    
 dev_close_window ()
    
 dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
    
 dev_set_draw ('margin')
    
 dev_set_line_width (2)
    
 set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
    
 dev_update_window ('off')
    
 *1,加载图片,并进行通道合并
    
 read_image (Image, 'ic'+[0:3])
    
 channels_to_image (Image, MultiChannelImage)
    
 dev_display (MultiChannelImage)
    
 stop ()
    
 mean_n (MultiChannelImage, ImageMean)
    
 dev_display (ImageMean)
    
 stop()
    
 *2,需要焊接的线路
    
 threshold (Image, Region, 0, 40)
    
 union1 (Region, dark)
    
 fill_up (dark, darkFill)
    
 complement (darkFill, back)
    
 *3,焊接良好的线路
    
  
    
 threshold (Image, Region, 100, 255)
    
 union1 (Region, light)
    
 intersection (darkFill, light, RegionIntersection)
    
 expand_region (RegionIntersection, back, RegionExpanded, 'maximal', 'image')
    
 fill_up (RegionExpanded, good)
    
 *4,虚焊,缺焊的线路
    
 difference (darkFill, good, rest)
    
 *5,对bad区域进行适当扩展
    
 expand_gray (rest, MultiChannelImage, good, bad, 6, 'image', 6)
    
 fill_up (bad, RegionFillUp)
    
 opening_circle (RegionFillUp, RegionClosing, 2.5)
    
 connection (RegionClosing, ConnectedRegions)
    
 select_shape (ConnectedRegions, bad, 'area', 'and', 150, 99999)
    
 *6,显示结果
    
 dev_display (Image)
    
 dev_set_color ('green')
    
 dev_display (good)
    
 dev_set_color ('red')
    
 dev_display (bad)
    
    
    
    
    XML
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/krpyfXSDHAs1zVdMINKUoqWQJw6a.png)

3,Fish检查。

复制代码
 *参考案例库:count_fish_sticks.hdev

    
 *目的:
    
 *检查鱼生的数量是否为指定的数量,鱼生的宽度是否在规定的范围内
    
 *描述:
    
 *使用矩形测量获取宽度
    
 *-------------------------1,参数设置
    
 *设置生鱼片数量
    
 fishNum:=15
    
 *设置鱼生的最小宽度,最大宽度
    
 minWidth:=20
    
 maxWidth:=48
    
 dev_close_window ()
    
 *主窗口
    
 dev_open_window (0, 0, 640, 512, 'black', WindowHandle)
    
 dev_update_window ('off')
    
 set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
    
 dev_set_line_width (2)
    
 *显示灰度趋势图
    
 * dev_open_window (0, 640, 400, 200, 'black', GraphicsWindow)
    
  
    
 *------------------------2,读取图片
    
 for Index := 1 to 6 by 1
    
     dev_set_window (WindowHandle)
    
     read_image (Image, 'food/fish_stick_package_'+Index$'02')
    
     dev_display (Image)
    
     threshold (Image, Region, 100, 255)
    
     closing_rectangle1 (Region, RegionClosing, 10, 10)
    
     fill_up (RegionClosing, RegionFillUp)
    
     difference (RegionFillUp, RegionClosing, RegionDifference)
    
     smallest_rectangle2 (RegionDifference, Row, Column, Phi, Length1, Length2)
    
     gen_rectangle2_contour_xld (Rectangle, Row, Column, Phi, Length1, Length2)
    
     *----------------------3,创建测量矩形
    
     gen_measure_rectangle2 (Row, Column, Phi, Length1, 40, 640, 512, 'nearest_neighbor', MeasureHandle)
    
     gen_rectangle2_contour_xld(Rectangle1, Row, Column, Phi, Length1, 60)
    
     *测量轮廓的灰度值
    
     measure_projection (Image, MeasureHandle, GrayValues)
    
     *获取轮廓灰度值对应的函数
    
     create_funct_1d_array (GrayValues, Function)
    
     *计算函数的局部极小点和最大值。(分为多个阶段,每一阶段的最大最小值)。
    
     local_min_max_funct_1d (Function, 'plateaus_center', 'true', Min, Max)
    
     
    
     *获取横坐标对应的纵坐标(这里获得最小值对应的灰度值)
    
     get_y_value_funct_1d (Function, Min, 'constant', Y)
    
     close_measure (MeasureHandle)
    
     *----------------------4,筛选计算每片鱼生的边界
    
     
    
     *灰度小于50对应值得索引集合
    
     *find(arr,val):返回数组arr中项为val的索引
    
     indexs:=find(sgn(Y-50),-1)
    
     *两片鱼生的分界位置
    
     *subset(arr,indexs):返回数组arr中指定索引indexs对应的项
    
     boundary:=subset(Min,indexs)
    
     *界线
    
     StickEdges:=[-0.5,boundary,2*Length1]
    
     *--------------------- 5,计算鱼生的厚度
    
     fishWidth:=[boundary,2*Length1]-[-0.5,boundary]   
    
     
    
     *----------------------6,计算每块鱼生的中心点已经边界的中心点
    
     borderX:=StickEdges+Column-Length1*cos(Phi)
    
     borderY:=Row+Length1*sin(Phi)-StickEdges/(2*Length1)*Length1*sin(Phi)
    
     centerX:=borderX[0:|fishWidth|-1]+fishWidth/2*cos(Phi)
    
     centerY:=borderY[0:|fishWidth|-1]+fishWidth/2*sin(Phi)
    
     gen_cross_contour_xld (borderCross, borderY, borderX, 10, rad(45))
    
     gen_cross_contour_xld (centerCross, centerY, centerX, 6, 0)
    
     *----------------------7,打印结果
    
     *处理噪声
    
     noiseIndex:=find(sgn(fishWidth-10),-1)
    
     noiseNum:=0
    
     if(noiseIndex!=-1)
    
     noiseNum:=|noiseIndex|
    
     endif
    
     
    
     smallIndexs:=-1
    
     for i := 0 to |fishWidth|-1 by 1
    
     if(fishWidth[i]>=10 and fishWidth[i]<minWidth)
    
         smallIndexs:=[smallIndexs,i]
    
     endif
    
     endfor
    
     
    
     bigIndexs:=find(sgn(fishWidth-maxWidth),1)
    
     offsetRow:=0
    
     if(|fishWidth|-noiseNum<fishNum or smallIndexs!=-1 or bigIndexs!=-1)
    
     
    
     disp_message (WindowHandle, 'not ok', 'window', offsetRow, 20, 'red', 'false')
    
     else
    
     disp_message (WindowHandle, 'ok', 'window', offsetRow, 20, 'green', 'false')
    
     endif
    
     
    
     offsetRow:=offsetRow+25
    
     str:=''
    
     if(|fishWidth|-noiseNum<fishNum)
    
     str:='数量不足'
    
     endif
    
     gen_empty_obj (bigRectangle)
    
     
    
     if(smallIndexs!=-1 )
    
     if(str!='')
    
         str:=str+';'
    
         
    
     endif
    
     str:=str+'偏薄'       
    
     gen_rectangle2_contour_xld (smallRectangle, subset(centerY,smallIndexs), subset(centerX,smallIndexs), gen_tuple_const(|smallIndexs|,Phi),subset(fishWidth,smallIndexs),gen_tuple_const(|smallIndexs|,40) )
    
     *偏小
    
     dev_set_color ('red')
    
     dev_display (smallRectangle)
    
     endif
    
     if(bigIndexs!=-1 )
    
     if(str!='')
    
         str:=str+';'
    
         
    
     endif
    
     str:=str+'偏厚'
    
     *标记偏厚区域
    
     gen_rectangle2_contour_xld (bigRectangle, subset(centerY,bigIndexs), subset(centerX,bigIndexs), gen_tuple_const(|bigIndexs|,Phi),subset(fishWidth,bigIndexs)/2,gen_tuple_const(|bigIndexs|,40) )
    
     
    
     endif
    
     
    
     tuple_strlen (str, Length)    
    
     *显示轮廓与十字线 
    
     dev_set_color ('orange')
    
     set_line_style (WindowHandle, [5,2])
    
     dev_display (Rectangle1)
    
     set_line_style (WindowHandle, [])
    
     *符合标准的区域
    
     dev_set_color ('green')
    
     dev_display (centerCross)
    
     normalIndexs:=[0:|fishWidth|-1]
    
     smallNum:=0
    
     bigNum:=0
    
     if(noiseIndex!=-1)
    
     tuple_remove (normalIndexs, noiseIndex, normalIndexs)
    
     noiseNum:=|noiseIndex|  
    
     endif
    
     if(bigIndexs!=-1)
    
     tuple_remove (normalIndexs, bigIndexs, normalIndexs)
    
     bigNum:=|bigIndexs|  
    
     endif
    
     if(smallIndexs!=-1)
    
     tuple_remove (normalIndexs,smallIndexs, normalIndexs)
    
     smallNum:=|smallIndexs|
    
     endif
    
     gen_rectangle2_contour_xld (normalRectangle, subset(centerY,normalIndexs), subset(centerX,normalIndexs), gen_tuple_const(|normalIndexs|,Phi),subset(fishWidth,normalIndexs)/2,gen_tuple_const(|normalIndexs|,40) )
    
     dev_display (normalRectangle)
    
     dev_set_color ('red')
    
     dev_display (borderCross)
    
     *偏大的区域     
    
     dev_display (bigRectangle)
    
     
    
     if(Length!=0)
    
     disp_message (WindowHandle,'异常原因:'+ str, 'window',  offsetRow, 20,'white', 'false')
    
     offsetRow:=offsetRow+25    
    
     endif
    
     
    
     disp_message (WindowHandle, '标准数量:'+fishNum, 'window',  offsetRow,20, 'white', 'false')
    
     offsetRow:=offsetRow+25
    
     disp_message (WindowHandle, '实际数量:'+(|fishWidth|-noiseNum), 'window', offsetRow, 20,'orange', 'false')
    
     disp_message (WindowHandle, '合格数量:'+(|fishWidth|-noiseNum-smallNum-bigNum), 'window', offsetRow, 160,'green','false')
    
     disp_message (WindowHandle, '偏薄数量:'+ smallNum, 'window', offsetRow, 300, 'red', 'false')
    
     
    
     disp_message (WindowHandle, '偏厚数量:'+bigNum, 'window',  offsetRow,430, 'red', 'false')
    
     dev_set_colored (12)
    
     stop ()
    
 endfor
    
    
    
    
    Matlab
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/8Qkhp5TVcobR6dJZXC1ta3mujAiL.png)

4,Fish长度检查。

复制代码
 *参考案例库:check_fish_stick_dimension.hdev

    
 *目的:
    
 *检查鱼生的长度是否在规定的范围内
    
  
    
 *----------------------------1,标准参数
    
 *相机坐标与世界坐标的比例关系
    
 cm_per_pix := 0.0373
    
 *鱼生标准长度
    
 TargetLength := 9.0
    
 *上限容差
    
 ToleranceHigh := 0.8
    
 *下限容差
    
 ToleranceLow := 0.2
    
 *----------------------------2,读取图片
    
 dev_close_window ()
    
 read_image (Image, 'food/fish_sticks_raw_01')
    
 get_image_size (Image, Width, Height)
    
 dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
    
 set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
    
 dev_update_window ('off')
    
 dev_set_line_width (2)
    
 for Index := 1 to 10 by 1
    
     read_image (Image, 'food/fish_sticks_raw_'+Index$'02')
    
     dev_display (Image)
    
     threshold (Image, Region, 70, 255)
    
     connection (Region, ConnectedRegions)
    
     select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 150, 99999)
    
     fill_up (SelectedRegions, RegionFillUp)
    
     *获取图像边界,计算是否有超过边界的fish
    
     boundary (Image, RegionBorder, 'inner')
    
     *计算边界与fish的交集,如果交集的面积大于0则表示存在fish超过视野
    
     intersection ( RegionFillUp,RegionBorder, RegionIntersection)
    
     
    
     area_center (RegionIntersection, Area, Row, Column)
    
     *完全在视野内的fish
    
     validRegionIndex:=find(sgn(Area),0)
    
     *与视野边界相交的fish  
    
     select_tuple_large (Area, 0, regionAtBoundaryIndices)
    
     *计算处理完全在视野内的fish
    
     select_obj (RegionFillUp, validRegion, validRegionIndex+1)
    
     smallest_rectangle2 (validRegion, Row1, Column1, Phi, Length1, Length2)
    
     *fish长度由相机坐标转化为世界坐标
    
     fishLenght:=Length1*2*cm_per_pix
    
     *各区域的索引
    
     select_tuple_large (fishLenght, TargetLength-ToleranceLow, goodIndices)
    
     select_tuple_large (fishLenght, TargetLength+ToleranceHigh, badIndices)
    
     select_tuple_large (-fishLenght, -TargetLength+ToleranceLow, badIndices2)
    
     tuple_remove (goodIndices, badIndices, goodIndices)
    
     badIndices:=[badIndices,badIndices2]
    
     *------------------3,显示结果
    
     msg:='标准长度:'+TargetLength$'.1f'+'cm'
    
     msg[1]:='误差范围:+'+ToleranceHigh$'.1f'+' / -'+ToleranceLow$'.1f'
    
     disp_message (WindowHandle, msg, 'window', 20,20, 'black', 'true')
    
     *标记完全处于视野内合格的区域
    
     if(|goodIndices|!=0)
    
     dev_set_color ('green')
    
     gen_rectangle2_contour_xld (Rectangle,subset( Row1,goodIndices),subset( Column1,goodIndices) ,subset( Phi,goodIndices) , subset( Length1,goodIndices), subset( Length2,goodIndices))
    
     dev_display (Rectangle)
    
 *         disp_message (WindowHandle, 'ok', 'window', subset( Row1,goodIndices),subset( Column1,goodIndices), 'green', 'false')
    
     print_message (WindowHandle, subset( Row1,goodIndices), subset( Column1,goodIndices), 'OK', subset( fishLenght,goodIndices), 'green')
    
     endif
    
     *标记完全处于视野内但长度不合格的区域
    
     if(|badIndices|!=0)
    
     dev_set_color ('red')
    
     gen_rectangle2_contour_xld (Rectangle,subset( Row1,badIndices),subset( Column1,badIndices) ,subset( Phi,badIndices) , subset( Length1,badIndices), subset( Length2,badIndices))
    
     dev_display (Rectangle)
    
 *         disp_message (WindowHandle, 'ok', 'window', subset( Row1,badIndices),subset( Column1,badIndices), 'red', 'false')
    
     print_message (WindowHandle, subset( Row1,badIndices), subset( Column1,badIndices), 'NG', subset( fishLenght,badIndices), 'red')
    
     endif
    
     *标记处于视野界线上的区域
    
     if(|regionAtBoundaryIndices|!=0)
    
     dev_set_color ('yellow')
    
     select_obj ( RegionFillUp, regionAtBoundary, regionAtBoundaryIndices+1)
    
     gen_contour_region_xld (regionAtBoundary, Contours, 'border')
    
     dev_display (Contours)
    
     endif
    
     dev_set_colored (12)
    
     stop()
    
 endfor
    
    
    
    
    XML
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/XCH9jOLsx4nVKrAEl3TeRW0MD8dp.png)

自定义的本地函数。

print_message(operator)

复制代码
 for i := 0 to |Rows|-1 by 1

    
     dev_set_color (color)
    
     disp_message (WindowHandle, result, 'window', Rows[i]-20, Columns[i]-10, color, 'false')
    
     disp_message (WindowHandle, values[i]$'0.1f'+'cm', 'window', Rows[i]+10, Columns[i]-20, color, 'false')
    
 endfor
    
 return ()
    
    
    
    
    XML

select_tuple_large (operator)

复制代码
 tuple_find (sgn(Tuple - Value), 1, Indices)

    
 if (Indices[0] == -1)
    
     Indices := []
    
 endif
    
 return ()
    
    
    
    
    XML

5,塑料薄片异常点检查。

复制代码
 *参考案例库:detect_indent_fft.hdev

    
  
    
 *目的:
    
 *检查塑料制品表面的缺陷
    
  
    
 dev_close_window ()
    
 read_image (Image, 'plastics/plastics_01')
    
 get_image_size (Image, Width, Height)
    
 dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
    
 dev_set_line_width (2)
    
 *创建高斯滤波器
    
 gen_gauss_filter (ImageGauss2, 3, 3, 0, 'n', 'dc_center', Width, Height)
    
  dev_update_window ('off')
    
 set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
    
 for Index := 1 to 11 by 1
    
     read_image (Image1, 'plastics/plastics_'+Index$'02')
    
     dev_display (Image1)
    
     rgb1_to_gray (Image1, GrayImage)
    
     fft_generic (GrayImage, ImageFFT, 'to_freq', -1, 'none', 'dc_center', 'complex')    
    
     convol_fft (ImageFFT, ImageGauss2, ImageConvol)
    
     *获取去噪后的空间域常使用real(仅包含幅值信息)作为输出类型。
    
     fft_generic (ImageConvol, ImageFFT1, 'from_freq', 1, 'none', 'dc_center', 'real')    
    
  
    
     *计算输入图像的灰度值范围,即每个图像点在大小为(MaskHeight, Maskwidth)的矩形掩模内的
    
     *最大和最小灰度值的差值(max - min)。得到的图像在ImageResult中返回。
    
     gray_range_rect (ImageFFT1, ImageResult, 11, 11)
    
     min_max_gray (ImageResult, ImageResult, 0, Min, Max, Range)   
    
     threshold (ImageResult, Region, max([ Max*0.8,5.8]), 255)
    
     connection (Region, ConnectedRegions)
    
     opening_circle (ConnectedRegions, RegionOpening, 2)
    
     smallest_circle (RegionOpening, Row, Column, Radius)
    
     select_shape (RegionOpening, SelectedRegions, 'area', 'and', 10, 99999)
    
     count_obj (SelectedRegions, Number)
    
     if(Number!=0 )
    
     dev_set_color ('red')
    
     gen_circle_contour_xld (ContCircle,  Row, Column, Radius*3, 0, rad(360), 'positive', 1)
    
     dev_display (ContCircle)
    
     disp_message (WindowHandle, 'not ok', 'window',20, 20, 'red', 'true')
    
     else
    
     disp_message (WindowHandle, 'ok', 'window',20, 20, 'green', 'true')
    
     endif
    
     dev_set_colored (12)
    
     stop ()
    
 endfor
    
    
    
    
    XML
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/sathJVyPEcSWm4RpdN0H318oBlDj.png)

6, 药丸检测。

复制代码
 *参考案例库:Check_blister.hdev

    
 *对药丸进行检测
    
 dev_close_window ()
    
 read_image (Image, 'blister/blister_01')
    
 get_image_size (Image, Width, Height)
    
 dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
    
 dev_display (Image)
    
 dev_set_draw ('margin')
    
 dev_set_line_width (2)
    
 set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
    
 *---------------------1,获取标准图像与区域位置
    
 decompose3 (Image, R, G, B)
    
 threshold (B, Region, 100, 255)
    
 connection (Region, ConnectedRegions)
    
 *获取感兴趣区域
    
 select_shape_std (ConnectedRegions, SelectedRegions, 'max_area', 0)
    
 shape_trans (SelectedRegions, RegionTrans, 'convex')
    
 *获取仿射变换矩阵
    
 orientation_region (RegionTrans, Phi)
    
 area_center (RegionTrans, Area, staRow, staColumn)
    
 vector_angle_to_rigid (staRow, staColumn, Phi, staRow, staColumn, 0, HomMat2D)
    
 *图片仿射变化
    
 affine_trans_image (B, staImageAffinTrans, HomMat2D, 'constant', 'false')
    
 *区域仿射变化
    
 affine_trans_region (RegionTrans, staRegion, HomMat2D, 'nearest_neighbor')
    
  
    
 area_center (staRegion, Area1, refRow, refColumn)
    
 orientation_region (staRegion, refPhi)
    
 *--------------------2,设置感兴趣区域
    
 gen_empty_obj (Chambers)
    
 for i := 0 to 4 by 1
    
     for j := 0 to 2 by 1
    
     gen_rectangle1 (Rectangle, 62+i*70, 145+j*150,  122+i*70, 270+j*150)
    
     concat_obj (Chambers, Rectangle, Chambers)
    
     endfor
    
 endfor
    
 union1 (Chambers, RoiRegion)
    
 *-------------------3,进行识别
    
 read_image (Image1, 'blister/blister_'+[1:6]$'02')
    
 count_obj (Image1, Number)
    
 for Index := 1 to Number by 1
    
     dev_set_colored (12)
    
     select_obj (Image1, image, Index)
    
     decompose3 (image, tempR, tempG, tempB)
    
     threshold (tempB, tempRegion, 100, 255)
    
     connection (tempRegion, ConnectedRegions1)
    
     select_shape_std (ConnectedRegions1, SelectedRegions1, 'max_area', 0)
    
     shape_trans (SelectedRegions1, tempRegion, 'convex')
    
     orientation_region (tempRegion, tempPhi)
    
     area_center (tempRegion, Area2, tempRow, tempColumn)
    
     vector_angle_to_rigid (tempRow, tempColumn, tempPhi, refRow, refColumn, refPhi, HomMat2D1)
    
     *仿射变换
    
     affine_trans_image (tempB, ImageAffinTrans, HomMat2D1, 'constant', 'false')
    
     affine_trans_image (image, ImageAffinTrans1, HomMat2D1, 'constant', 'false')
    
     *裁剪感兴趣区域
    
     reduce_domain (ImageAffinTrans,RoiRegion , ImageReduced)
    
     var_threshold (ImageReduced, Region1, 15, 15, 0.2, 2, 'dark')
    
     dev_clear_window ()
    
     
    
     fill_up (Region1, RegionFillUp)
    
    opening_circle (RegionFillUp, RegionOpening, 3.5)
    
     connection (RegionOpening, ConnectedRegions2)
    
     
    
     select_shape (ConnectedRegions2, SelectedRegions2, 'area', 'and', 426.61, 50000)
    
     shape_trans (SelectedRegions2, RegionTrans1, 'convex')
    
     union1 (RegionTrans1, BlisterRegionUnion)
    
     *进行计算
    
     gen_empty_obj (wrongBlister)
    
     gen_empty_obj (missBlister)
    
     gen_empty_obj (passBlister)
    
     count_obj (Chambers, ChambersNumber)
    
     for k := 1 to ChambersNumber by 1
    
     select_obj (Chambers, Chamber, k)
    
     intersection (Chamber, BlisterRegionUnion, BlisterRegion)
    
     *计算交集的区域面积与灰度值
    
     area_center (BlisterRegion, Area3, Row, Column)
    
     if(Area3>0)
    
         
    
         min_max_gray (BlisterRegion, ImageReduced, 0, Min, Max, Range)
    
         if(Area3<3700 or Min<60)
    
             *异常的药丸
    
             concat_obj (wrongBlister, BlisterRegion, wrongBlister)
    
         else
    
             *ok的药丸
    
             concat_obj (passBlister, Chamber, passBlister)
    
         endif
    
     else
    
         *缺失
    
         concat_obj (missBlister, Chamber,missBlister)
    
     endif
    
     endfor
    
     *------------------结果显示
    
     dev_display (ImageAffinTrans1)
    
     count_obj (missBlister, missCount)
    
     count_obj (passBlister, passCount)
    
     count_obj (wrongBlister, wrongCount)
    
     dev_set_color ('red')
    
     dev_display (missBlister)
    
     dev_set_color ('yellow')
    
     dev_display (wrongBlister)
    
     dev_set_color ('green')
    
     dev_display (passBlister)
    
     disp_message (WindowHandle, '标准数量:'+ChambersNumber, 'window', 20, 20, 'white', 'false')
    
     disp_message (WindowHandle, '合格数量:'+passCount, 'window', 50, 20, 'green', 'false')
    
     disp_message (WindowHandle, '异常数量:'+wrongCount, 'window', 80, 20, 'yellow', 'false')
    
     disp_message (WindowHandle, '缺失数量:'+missCount, 'window', 110, 20, 'red', 'false')
    
     stop ()
    
 endfor
    
    
    
    
    XML
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/i4xRO1sC76r2dn9W5VfNFbwkETQX.png)

全部评论 (0)

还没有任何评论哟~