• Halcon 3D 切片法检测物料


    一、简介

            在上一篇中,学习了鞋底切片法来求轮廓,那个思路是比较简单的,其次还提到了法向量重建的方法,目前由于没有用法向量重建来做那个项目,所以还是有很大的疑问,后续会继续学习那个方法然后重新在做一次,和切片法做一个对比,今天来学一习Halcon 自带的例程 切平面检测物料,在上一阶中,留下来几个问题:

      1、project_object_model_3d 投影模型是如何来投影的,他的数学原理是什么,记得之前我手推过一个投影矩阵,但是现在也忘记了,只记得用了正交投影,相似三角形、左手坐标系等。

       2、三角化模型的原理,这个在PCL中大概看过一点,感觉看了一丁点皮毛,等有时间了系统的学一下这个知识点,从算子角度来说,三角化Halcon里面的时间有点长,就是鞋子的那个模型,三角化用了15s 的时间(Y9000),比我想象中的慢了很多,之前接触过一个做点云处理的国外同行,他说他们那边的三维重建可以控制到3s以内,当然这个和点云大小相关,但是人家有自信这么说肯定有过人之处。

    二、算子解释

    1、create_sheet_of_light_model:创建一个执行线结构光技术3D测量的光片模型

    描述
            操作符create_sheet_of_light_model使用线结构光技术创建一个模型来执行3d测量。

    该技术通过使用区域扫描摄像机和光线投影仪(通常是激光线投影仪)对不透明和漫反射固体的表面进行三维重建。照相机和放映机必须安装好,使它们的主轴形成三角形。三角测量的值通常选择在30°到60°之间。投射的光线在空间中定义了一个平面(结构光平面)。这个平面与被测量的固体表面相交,并建立了一个对摄像机可见的表面轮廓(Profile)。通过移动固体在测量系统前面,(即如照相机和激光器的组合),就有可能记录整个固体的表面。作为一种替代方案,测量系统也可以在被测表面上移动。请注意,轮廓在轮廓图像中必须大致水平定位,因为它们是逐列处理的。

    如果有测量装置的几何信息,就可以计算出重建曲面的真实三维坐标。浏览所需几何图形的描述(即,标定)的信息,请参阅操作符set_sheet_of_light_param。如果没有这样的信息,测量的结果是一个视差图像(disparity image),其中每个像素保存着被测轮廓的亚像素精确位置的记录。

    操作员在SheetOfLightModelID中返回光表模型的句柄,该句柄用于对光表模型的所有进一步操作,如修改模型的参数、测量轮廓、应用标定转换或访问测量结果。

    使用简化的线结构光模型参数
           在一个简单的设置或是否为一个真正的度量标定是必要的,观测到的视差图转换成3D值可以控制使用简化的参数集的线结构光模型:

    通过将set_sheet_of_light_param的校准设置为‘offset_scale’,位姿和相机参数将更改为这样的值,即一个像素的偏移量对应于3D结果中的一个单元。这允许从一个未校准的线结构光模型创建一个三维物体模型和三维图像。

    从视差到三维坐标的转换可以通过六个参数来控制:‘scale_x’、‘scale_y’、‘scale_z’、‘offset_x’、‘offset_y’、‘offset_z’。有关所有受支持的通用参数的详细描述,请参阅set_sheet_of_light_param。

    Halcon算子学习:create_sheet_of_light_model_Leon_Chan0的博客-CSDN博客

    1. create_sheet_of_light_model
    2. (ProfileRegion : : GenParamName, GenParamValue : SheetOfLightModelID)
    3. 创建一个执行线结构光技术3D测量的的模型
    4. 输入:
    5. ProfileRegion
    6. 包含要处理的轮廓的图像的ROI。(如果所提供的区域不是矩形的,则使用其最小的外接矩形)
    7. GenParamName
    8. 可以为线结构光模型调整的通用参数的名称。
    9. 默认值:“min_gray”
    10. 值列表:’ uity_solving’, ‘calibration’, ‘method’, ‘min_gray’, ‘num_profiles’, ‘offset_x’, ‘offset_y’, ‘offset_z’, ‘scale’, ‘scale_x’, ‘scale_y’, ‘scale_z’, ‘score_type’
    11. GenParamValue
    12. 可以为线结构光模型调整的通用参数的值。
    13. 默认值:50
    14. 建议值:‘default’, ‘center_of_gravity’, ‘last’, ‘first’, 'bright ', ‘none’, ‘intensity’, ‘width’, ‘offset_scale’, 50,100,150,180
    15. 输出:
    16. SheetOfLightModelID
    17. 用于使用和访问光照模型的句柄。
    18. set_sheet_of_light_param

     2、measure_profile_sheet_of_light 将配置文件图像作为输入处理,并将由此产生的差异存储到光片模型中。

    1. measure_profile_sheet_of_light(ProfileImage : : SheetOfLightModelID, MovementPose : )
    2. 描述:
    3. 1,ProfileImage,输入图片
    4. 2,SheetOfLightModelID,光平面模型句柄
    5. 3,MovementPose
    6. Pose 描述在以前处理过的个人资料图像和当前配置文件图像之间测量的场景移动。

    1. * Create the rectangular region in which the profiles are measured.
    2. gen_rectangle1 (ProfileRegion, 120, 75, 195, 710)
    3. *
    4. * Create a model in order to measure profiles according to
    5. * the sheet-of-light technique. Simultaneously set some
    6. * parameters for the model.
    7. create_sheet_of_light_model (ProfileRegion, ['min_gray','num_profiles', 'ambiguity_solving','score_type'], [70,290,'first','width'], SheetOfLightModelID)
    8. *
    9. * Measure the profile from successive images
    10. for Index := 1 to 290 by 1
    11. read_image (ProfileImage, 'sheet_of_light/connection_rod_'+Index$'.3')
    12. dev_display (ProfileImage)
    13. dev_display (ProfileRegion)
    14. measure_profile_sheet_of_light (ProfileImage, SheetOfLightModelID, [])
    15. endfor
    16. *
    17. * Get the resulting disparity and score images
    18. get_sheet_of_light_result (Disparity, SheetOfLightModelID, 'disparity')
    19. get_sheet_of_light_result (Score, SheetOfLightModelID, 'score')
    20. *
    21. * Close the sheet-of-light handle once the measurement
    22. * has been performed
    23. clear_sheet_of_light_model (SheetOfLightModelID)

     光平面图片:

     光片模型

     

    计算法向量:

    Halcon 3D 计算3D模型的3D表面法线_Σίσυφος1900的博客-CSDN博客_halcon 计算点云法线

    计算发向量之后的模型 

    三、算法思路

    1、声明一个光片模型句柄

    2、用这个模型句柄来把所有的都加载进行,想当与一个线激光,在不断的向前走,等线数走完之后就将生成一个模型

    将光片模型生成一个常见的3D点云模型 

    get_sheet_of_light_result_object_model_3d (SheetOfLightModelID, Model3DFull)

     3、去噪点

    4、表面法向量计算与重建

    1. * 表面法向量
    2. surface_normals_object_model_3d (Model3D, 'mls', 'mls_force_inwards', 'true', ObjectModel3DNormals)
    3. Message_1:='Surface——Model'
    4. visualize_object_model_3d(WindowHandle,ObjectModel3DNormals,[], [], ['point_size','disp_normals'], [12,'true'], Message_1, [], [], PoseOut)
    5. triangulate_object_model_3d (ObjectModel3DNormals, 'greedy', 'greedy_remove_small_surfaces', 200, ObjectModel3DReference, Information)

     triangulate_object_model_3d (ObjectModel3DNormals, 'greedy', 'greedy_remove_small_surfaces', 200, ObjectModel3DReference, Information)

    这个很重要,就是对法向量的进行三维重建

     法向量计算的模型

     

     三维重建后的模型:用时1.6s

    5、生成一个表面模型

    1. * Create a surface model for alignment
    2. create_surface_model (ObjectModel3DReference, 0.03, 'model_invert_normals', 'true', SurfaceModelID)

     

     6、生成切片平面

     7、计算切平面与表面模型的交集

    intersect_plane_object_model_3d (ObjectModel3DReference, PoseIntersectionPlane3, ObjectModel3DIntersection3)

    8、投影 :

    先做姿态变换

    1. * Determine the intersections and convert them into XLD contours
    2. *
    3. * The inverted intersection plane pose is our projection pose
    4. pose_invert (PoseIntersectionPlane, PoseInvert)
    5. * Make sure, the projection plane lies in front of the camera
    6. * 得到交点模型的直径
    7. get_object_model_3d_params (ObjectModel3DIntersection, 'diameter_axis_aligned_bounding_box', Diameter)
    8. PoseInvert[2] := PoseInvert[2] + Diameter
    9. * Use a parallel projection to achieve the desired scaling (default 1:1)
    10. Scale := 1
    11. gen_cam_par_area_scan_telecentric_division (1.0, 0, 1.0 / Scale, 1.0 / Scale, 0, 0, 512, 512, CamParam)
    12. project_object_model_3d (Intersection, ObjectModel3DIntersection, CamParam, PoseInvert, 'data', 'lines')
    13. return ()

    8 、通过轮廓来判断物料是否有损伤,里面用到的全是二维的东西,这里就不说了

    1. * 分析产品是否有损伤
    2. analyze_intersection (Intersection1, FittedLines1, OrientationRef, OrientationTolerance, MinDistance1, MaxDistance1, Angle1)
    3. analyze_intersection (Intersection2, FittedLines2, OrientationRef, OrientationTolerance, MinDistance2, MaxDistance2, Angle2)
    4. analyze_intersection (Intersection3, FittedLines3, OrientationRef, OrientationTolerance, MinDistance3, MaxDistance3, Angle3)

    四、代码显示

     

    1. * This example shows the inspection of planar intersections of
    2. * 3D objects. The intersections are derived by intersecting the
    3. * reconstructed 3D object models with suitable planes, using the
    4. * operator intersect_plane_object_model_3d.
    5. *
    6. * The objects, which are metal parts in this example, are
    7. * scanned with an uncalibrated sheet of light setup that returns
    8. * disparities for each scan line. The disparities are
    9. * transformed into a 3D object model. In this example, the
    10. * transformation is based on simple scalings of the three
    11. * dimensions that were chosen such that the reconstructed 3D
    12. * object model is given approximately in mm.
    13. *
    14. * The nominal dimensions and the tolerance limits are derived
    15. * from a reference sample of the metal part. For this,
    16. * intersections derived at predefined positions are analysed.
    17. * Note that if the nominal dimension and tolerance limits should
    18. * be specified numerically, the reconstruction must be done with
    19. * a fully calibrated setup to ensure that the specified values
    20. * are meaningfull with respect to the reconstructed 3D object
    21. * model.
    22. *
    23. * For the inspection, 3D object models of the metal parts are
    24. * reconstructed in the same way as described for the reference
    25. * sample. With the help of surface based matching, the
    26. * intersection planes, which are defined with respect to the
    27. * reference sample, are aligned with the parts to be inspected.
    28. * The resulting intersections are then analysed to check whether
    29. * the dimensions of the objects to be inspected are within the
    30. * allowed tolerance limits.
    31. *
    32. *
    33. *
    34. * Part 1: Reconstruction of the reference sample and derivation
    35. * of nominal dimensions and tolerance limits
    36. *
    37. * Set up the sheet of light model
    38. NumDisparityProfiles := 441
    39. read_image (DisparityProfile, 'sheet_of_light/metal_part_1_disparity_line_000')
    40. create_sheet_of_light_model (DisparityProfile, 'calibration', 'offset_scale', SheetOfLightModelID)
    41. * Set the scaling factors for the calibration method 'offset_scale'
    42. * such that the reconstructed 3D object model is given approximately
    43. * in mm
    44. ScaleX := 1
    45. ScaleY := 4
    46. ScaleZ := 0.5
    47. set_sheet_of_light_param (SheetOfLightModelID, 'scale_x', ScaleX)
    48. set_sheet_of_light_param (SheetOfLightModelID, 'scale_y', ScaleY)
    49. set_sheet_of_light_param (SheetOfLightModelID, 'scale_z', ScaleZ)
    50. *
    51. * Define the z coordinate at which the object can be separated from
    52. * the background
    53. MinZ := 220
    54. *
    55. * Initialize display
    56. dev_update_off ()
    57. set_system ('clip_region', 'false')
    58. dev_close_window ()
    59. * 可以理解为视差图 DisparityProfile
    60. get_image_size (DisparityProfile, DisparityProfileWidth, DisparityProfileHeight)
    61. WindowEnlargement := 350
    62. WindowWidth := DisparityProfileWidth + WindowEnlargement
    63. WindowHeight := NumDisparityProfiles
    64. dev_open_window (0, 0, WindowWidth, WindowHeight, 'black', WindowHandle)
    65. dev_set_part (0, 0, WindowHeight - 1, WindowWidth - 1)
    66. get_part (WindowHandle, PartRow1, PartColumn1, PartRow2, PartColumn2)
    67. set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
    68. dev_set_draw ('fill')
    69. *
    70. * Define some visualization parameters
    71. * 定义一个平面的大小
    72. VisualizationPlaneSize := 150
    73. * 生产相机内参
    74. gen_cam_par_area_scan_division (0.01, 0, 6e-6, 6e-6, WindowWidth / 2, WindowHeight / 2, WindowWidth, WindowHeight, VisualizationCamParam)
    75. create_pose (-1550, 680, 5390, 122, 1, 357, 'Rp+T', 'gba', 'point', VisualizationPose)
    76. VisualizationColors := ['magenta','blue','orange']
    77. *
    78. * Create the reference sample by collecting the measured
    79. * disparity profiles in a sheet-of-light model and
    80. * transforming them to a 3D object model
    81. gen_image_const (DisparityImageVis, 'uint2', DisparityProfileWidth, NumDisparityProfiles)
    82. for Index := 0 to NumDisparityProfiles - 1 by 1
    83. * Add the next disparity profile to the sheet of light model
    84. read_image (ImageModel, 'sheet_of_light/metal_part_1_disparity_line_' + Index$'03d')
    85. *设置光片模型的参数
    86. set_profile_sheet_of_light (ImageModel, SheetOfLightModelID, [])
    87. * Accumulated profiles for visualization
    88. * 将光片堆起来并可视化
    89. get_grayval (ImageModel, gen_tuple_const(DisparityProfileWidth,0), [0:DisparityProfileWidth - 1], Disparities)
    90. set_grayval (DisparityImageVis, gen_tuple_const(DisparityProfileWidth,Index), [0:DisparityProfileWidth - 1], Disparities)
    91. if (Index % 5 == 4)
    92. dev_display (DisparityImageVis)
    93. Message := 'Disparity image of the reference sample'
    94. Message[1] := 'Adding disparity profile ' + (Index + 1) + '/' + NumDisparityProfiles
    95. disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
    96. endif
    97. endfor
    98. * Display the disparity image of the reference sample
    99. dev_display (DisparityImageVis)
    100. disp_message (WindowHandle, 'Disparity image of the reference sample', 'window', 12, 12, 'black', 'true')
    101. * Get the 3D reconstruction of the reference sample and eliminate
    102. * the background from the respective 3D object model
    103. * 从光片模型生成一个3d模型
    104. get_sheet_of_light_result_object_model_3d (SheetOfLightModelID, Model3DFull)
    105. get_object_model_3d_params (Model3DFull, 'bounding_box1', BoundingBox1)
    106. MaxZ := BoundingBox1[5]
    107. select_points_object_model_3d (Model3DFull, 'point_coord_z', MinZ, MaxZ, Model3D)
    108. disp_continue_message (WindowHandle, 'black', 'true')
    109. stop ()
    110. *
    111. * Prepare the 3D object model for the intersection with
    112. * the planes and to allow the alignment of the intersection
    113. * planes to the objects to be inspected
    114. dev_clear_window ()
    115. dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)
    116. visualize_object_model_3d (WindowHandle, Model3D, [], [], [], [], [], [], [], PoseOut)
    117. disp_object_model_3d (WindowHandle, Model3D, VisualizationCamParam, VisualizationPose, [], [])
    118. Message := 'Prepare the reference model'
    119. Message[1] := ' - triangulate 3D object model and'
    120. Message[2] := ' - create surface model for alignment'
    121. disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
    122. * Triangulate the 3D object model
    123. * 表面法向量
    124. surface_normals_object_model_3d (Model3D, 'mls', 'mls_force_inwards', 'true', ObjectModel3DNormals)
    125. Message_1:='Surface——Model'
    126. visualize_object_model_3d(WindowHandle,ObjectModel3DNormals,[], [], ['point_size','disp_normals'], [12,'true'], Message_1, [], [], PoseOut)
    127. triangulate_object_model_3d (ObjectModel3DNormals, 'greedy', 'greedy_remove_small_surfaces', 200, ObjectModel3DReference, Information)
    128. * Create a surface model for alignment
    129. create_surface_model (ObjectModel3DReference, 0.03, 'model_invert_normals', 'true', SurfaceModelID)
    130. *
    131. * Define the intersection planes relative to the reference sample,
    132. * calculate the intersections and derive nominal dimensions and
    133. * tolerance limits from these intersections
    134. *
    135. * Define the intersection planes
    136. create_pose (300, 230, 250, -90, 0, 0, 'Rp+T', 'gba', 'point', PoseIntersectionPlane1)
    137. create_pose (300, 900, 250, -90, 0, 0, 'Rp+T', 'gba', 'point', PoseIntersectionPlane2)
    138. create_pose (300, 1570, 250, -90, 0, 0, 'Rp+T', 'gba', 'point', PoseIntersectionPlane3)
    139. gen_plane_object_model_3d (PoseIntersectionPlane1, [-1,-1,1,1] * VisualizationPlaneSize, [-1,1,1,-1] * VisualizationPlaneSize, IntersectionPlane1)
    140. gen_plane_object_model_3d (PoseIntersectionPlane2, [-1,-1,1,1] * VisualizationPlaneSize, [-1,1,1,-1] * VisualizationPlaneSize, IntersectionPlane2)
    141. gen_plane_object_model_3d (PoseIntersectionPlane3, [-1,-1,1,1] * VisualizationPlaneSize, [-1,1,1,-1] * VisualizationPlaneSize, IntersectionPlane3)
    142. dev_clear_window ()
    143. dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)
    144. disp_object_model_3d (WindowHandle, [ObjectModel3DReference,IntersectionPlane1,IntersectionPlane2,IntersectionPlane3], VisualizationCamParam, VisualizationPose, ['color_1','color_2','color_3','alpha','alpha_0'], [VisualizationColors,0.75,1])
    145. Message := 'Reference sample with predefined intersection planes'
    146. MessageWrapped := regexp_replace(Message + ' ',['(.{0,25})\\s','replace_all'],'$1\n')
    147. disp_message (WindowHandle, MessageWrapped, 'window', 12, 12, 'black', 'true')
    148. *
    149. * Calculate the intersections of the reference sample with the above
    150. * defined planes 求交集
    151. intersect_plane_object_model_3d (ObjectModel3DReference, PoseIntersectionPlane1, ObjectModel3DIntersection1)
    152. intersect_plane_object_model_3d (ObjectModel3DReference, PoseIntersectionPlane2, ObjectModel3DIntersection2)
    153. intersect_plane_object_model_3d (ObjectModel3DReference, PoseIntersectionPlane3, ObjectModel3DIntersection3)
    154. *
    155. * Determine the intersections and convert them into XLD contours
    156. project_object_model_3d_lines_to_contour_xld (Intersection1, PoseIntersectionPlane1, ObjectModel3DIntersection1)
    157. project_object_model_3d_lines_to_contour_xld (Intersection2, PoseIntersectionPlane2, ObjectModel3DIntersection2)
    158. project_object_model_3d_lines_to_contour_xld (Intersection3, PoseIntersectionPlane3, ObjectModel3DIntersection3)
    159. *
    160. * Determine the nominal dimensions and the tolerance limits by
    161. * analysing the measurements from the reference sample
    162. OrientationRef := 20
    163. OrientationTolerance := 20
    164. analyze_intersection (Intersection1, FittedLines1, OrientationRef, OrientationTolerance, MinDistance1, MaxDistance1, Angle1)
    165. analyze_intersection (Intersection2, FittedLines2, OrientationRef, OrientationTolerance, MinDistance2, MaxDistance2, Angle2)
    166. analyze_intersection (Intersection3, FittedLines3, OrientationRef, OrientationTolerance, MinDistance3, MaxDistance3, Angle3)
    167. *
    168. * Visualize the object with the intersection planes and the respective
    169. * intersections and measurement results
    170. hom_mat2d_identity (HomMat2DIdentity)
    171. * Display explanations
    172. Message := 'Intersections with measurement lines'
    173. MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')
    174. disp_message (WindowHandle, MessageWrapped, 'window', 12, 330, 'black', 'true')
    175. Message := 'Measurement results'
    176. MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')
    177. disp_message (WindowHandle, MessageWrapped, 'window', 12, 590, 'black', 'true')
    178. * Display first intersection
    179. hom_mat2d_translate (HomMat2DIdentity, 350, 390, HomMat2DTranslate1)
    180. affine_trans_contour_xld (Intersection1, Intersection1Vis, HomMat2DTranslate1)
    181. affine_trans_contour_xld (FittedLines1, FittedLines1Vis, HomMat2DTranslate1)
    182. dev_set_color (VisualizationColors[0])
    183. dev_set_line_width (5)
    184. dev_display (Intersection1Vis)
    185. dev_set_color ('white')
    186. dev_set_line_width (1)
    187. dev_display (FittedLines1Vis)
    188. Message := 'Angle = ' + Angle1$'.1f' + ' deg'
    189. Message[1] := 'Min Distance = ' + MinDistance1$'.1f' + ' mm'
    190. Message[2] := 'Max Distance = ' + MaxDistance1$'.1f' + ' mm'
    191. disp_message (WindowHandle, Message, 'window', 310, 600, VisualizationColors[0], 'false')
    192. * Display second intersection
    193. hom_mat2d_translate (HomMat2DIdentity, 250, 410, HomMat2DTranslate2)
    194. affine_trans_contour_xld (Intersection2, Intersection2Vis, HomMat2DTranslate2)
    195. affine_trans_contour_xld (FittedLines2, FittedLines2Vis, HomMat2DTranslate2)
    196. dev_set_color (VisualizationColors[1])
    197. dev_set_line_width (5)
    198. dev_display (Intersection2Vis)
    199. dev_set_color ('white')
    200. dev_set_line_width (1)
    201. dev_display (FittedLines2Vis)
    202. Message := 'Angle = ' + Angle2$'.1f' + ' deg'
    203. Message[1] := 'Min Distance = ' + MinDistance2$'.1f' + ' mm'
    204. Message[2] := 'Max Distance = ' + MaxDistance2$'.1f' + ' mm'
    205. disp_message (WindowHandle, Message, 'window', 210, 600, VisualizationColors[1], 'false')
    206. * Display third intersection
    207. hom_mat2d_translate (HomMat2DIdentity, 150, 430, HomMat2DTranslate3)
    208. affine_trans_contour_xld (Intersection3, Intersection3Vis, HomMat2DTranslate3)
    209. affine_trans_contour_xld (FittedLines3, FittedLines3Vis, HomMat2DTranslate3)
    210. dev_set_color (VisualizationColors[2])
    211. dev_set_line_width (5)
    212. dev_display (Intersection3Vis)
    213. dev_set_color ('white')
    214. dev_set_line_width (1)
    215. dev_display (FittedLines3Vis)
    216. Message := 'Angle = ' + Angle3$'.1f' + ' deg'
    217. Message[1] := 'Min Distance = ' + MinDistance3$'.1f' + ' mm'
    218. Message[2] := 'Max Distance = ' + MaxDistance3$'.1f' + ' mm'
    219. disp_message (WindowHandle, Message, 'window', 110, 600, VisualizationColors[2], 'false')
    220. disp_continue_message (WindowHandle, 'black', 'true')
    221. stop ()
    222. *
    223. * Define the nominal dimensions and the tolerance limits based
    224. * on the measurements of the reference sample
    225. AngleRef := mean([Angle1,Angle2,Angle3])
    226. MaxAngleDev := 2
    227. MinAngle := AngleRef - MaxAngleDev
    228. MaxAngle := AngleRef + MaxAngleDev
    229. MinDistance := 0.95 * mean([MinDistance1,MinDistance2,MinDistance3])
    230. MaxDistance := 1.05 * mean([MaxDistance1,MaxDistance2,MaxDistance3])
    231. * Display the nominal dimensions and the tolerance limits
    232. dev_clear_window ()
    233. Message := 'Tolerance limits for the angle and the distance of the mounting tabs, derived from the three measurements on the reference sample:'
    234. MessageWrapped := regexp_replace(Message + ' ',['(.{0,75})\\s','replace_all'],'$1\n')
    235. Message := MessageWrapped
    236. Message[1] := ' '
    237. Message[2] := 'Min Angle = ' + MinAngle$'.1f' + ' deg'
    238. Message[3] := 'Max Angle = ' + MaxAngle$'.1f' + ' deg'
    239. Message[4] := ' '
    240. Message[5] := 'Min Distance = ' + MinDistance$'.1f' + ' mm'
    241. Message[6] := 'Max Distance = ' + MaxDistance$'.1f' + ' mm'
    242. disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
    243. disp_continue_message (WindowHandle, 'black', 'true')
    244. stop ()
    245. *
    246. *
    247. * Part 2: Reconstruction of test objects and
    248. * checking of the respective dimensions
    249. *
    250. * Inspection loop
    251. NumScenes := 4
    252. for SceneIndex := 1 to NumScenes by 1
    253. dev_clear_window ()
    254. dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)
    255. * Reset the dispartities in the sheet of light model; all other settings can be reused
    256. reset_sheet_of_light_model (SheetOfLightModelID)
    257. *
    258. * Create the test object by collecting the measured
    259. * disparity profiles in a sheet-of-light model and
    260. * transforming them to a 3D object model
    261. gen_image_const (DisparityImageVis, 'uint2', DisparityProfileWidth, NumDisparityProfiles)
    262. for Index := 0 to NumDisparityProfiles - 1 by 1
    263. * Add the next disparity profile to the sheet of light model
    264. read_image (ImageSearch, 'sheet_of_light/metal_part_' + (SceneIndex + 1) + '_disparity_line_' + Index$'03d')
    265. set_profile_sheet_of_light (ImageSearch, SheetOfLightModelID, [])
    266. * Accumulated profiles for visualization
    267. get_grayval (ImageSearch, gen_tuple_const(DisparityProfileWidth,0), [0:DisparityProfileWidth - 1], Disparities)
    268. set_grayval (DisparityImageVis, gen_tuple_const(DisparityProfileWidth,Index), [0:DisparityProfileWidth - 1], Disparities)
    269. if (Index % 5 == 4 or Index == (NumDisparityProfiles - 1))
    270. dev_display (DisparityImageVis)
    271. Message := 'Disparity image of test object ' + SceneIndex
    272. Message[1] := 'Adding disparity profile ' + (Index + 1) + '/' + NumDisparityProfiles
    273. disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
    274. endif
    275. endfor
    276. * Get the 3D reconstruction of the test object and eliminate
    277. * the background from the respective 3D object model
    278. get_sheet_of_light_result_object_model_3d (SheetOfLightModelID, Scene3DFull)
    279. get_object_model_3d_params (Scene3DFull, 'bounding_box1', BoundingBox1)
    280. MaxZ := BoundingBox1[5]
    281. select_points_object_model_3d (Scene3DFull, 'point_coord_z', MinZ, MaxZ, Scene3D)
    282. *
    283. * Align the intersection planes to the actual position and orientation
    284. * of the test object and prepare the test object for the intersection
    285. dev_clear_window ()
    286. dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)
    287. disp_object_model_3d (WindowHandle, Scene3D, VisualizationCamParam, VisualizationPose, [], [])
    288. Message := 'Prepare the 3D object model of the test object'
    289. Message[1] := ' - perform surface based matching for alignment'
    290. Message[2] := ' - triangulate 3D object model'
    291. disp_message (WindowHandle, Message[0], 'window', 12, 12, 'black', 'true')
    292. *
    293. * Match the test object with the reference sample.
    294. * Note that the RelSamplingDistance has been set fairly small.
    295. * This is necessary because the object has only little 3D variations
    296. * that can be used by the matching process.
    297. disp_message (WindowHandle, Message[0:1], 'window', 12, 12, 'black', 'true')
    298. find_surface_model (SurfaceModelID, Scene3D, 0.005, 0.2, 0, 'false', [], [], Pose, Score, SurfaceMatchingResultID)
    299. * Align the intersection planes to the test object
    300. rigid_trans_object_model_3d (IntersectionPlane1, Pose, IntersectionPlane1Aligned)
    301. rigid_trans_object_model_3d (IntersectionPlane2, Pose, IntersectionPlane2Aligned)
    302. rigid_trans_object_model_3d (IntersectionPlane3, Pose, IntersectionPlane3Aligned)
    303. get_object_model_3d_params (IntersectionPlane1Aligned, 'primitive_parameter_pose', IntersectionPlane1AlignedPose)
    304. get_object_model_3d_params (IntersectionPlane2Aligned, 'primitive_parameter_pose', IntersectionPlane2AlignedPose)
    305. get_object_model_3d_params (IntersectionPlane3Aligned, 'primitive_parameter_pose', IntersectionPlane3AlignedPose)
    306. * Triangulate the 3D object model
    307. disp_message (WindowHandle, Message[0:2], 'window', 12, 12, 'black', 'true')
    308. triangulate_object_model_3d (Scene3D, 'greedy', [], [], Scene3DTest, Information)
    309. dev_clear_window ()
    310. disp_object_model_3d (WindowHandle, [Scene3DTest,IntersectionPlane1Aligned,IntersectionPlane2Aligned,IntersectionPlane3Aligned], VisualizationCamParam, VisualizationPose, ['color_1','color_2','color_3','alpha','alpha_0'], [VisualizationColors,0.75,1])
    311. Message := 'Test object ' + SceneIndex + ' with aligned intersection planes'
    312. MessageWrapped := regexp_replace(Message + ' ',['(.{0,25})\\s','replace_all'],'$1\n')
    313. disp_message (WindowHandle, MessageWrapped, 'window', 12, 12, 'black', 'true')
    314. *
    315. * Calculate the intersections of the test object with the respectively
    316. * aligned planes
    317. intersect_plane_object_model_3d (Scene3DTest, IntersectionPlane1AlignedPose, ObjectModel3DIntersection1)
    318. intersect_plane_object_model_3d (Scene3DTest, IntersectionPlane2AlignedPose, ObjectModel3DIntersection2)
    319. intersect_plane_object_model_3d (Scene3DTest, IntersectionPlane3AlignedPose, ObjectModel3DIntersection3)
    320. *
    321. * Determine the intersections and convert them into XLD contours
    322. project_object_model_3d_lines_to_contour_xld (Intersection1, IntersectionPlane1AlignedPose, ObjectModel3DIntersection1)
    323. project_object_model_3d_lines_to_contour_xld (Intersection2, IntersectionPlane2AlignedPose, ObjectModel3DIntersection2)
    324. project_object_model_3d_lines_to_contour_xld (Intersection3, IntersectionPlane3AlignedPose, ObjectModel3DIntersection3)
    325. *
    326. * Determine the actual dimensions by analysing the measurements
    327. * from the test object
    328. * 分析产品是否有损伤
    329. analyze_intersection (Intersection1, FittedLines1, OrientationRef, OrientationTolerance, MinDistance1, MaxDistance1, Angle1)
    330. analyze_intersection (Intersection2, FittedLines2, OrientationRef, OrientationTolerance, MinDistance2, MaxDistance2, Angle2)
    331. analyze_intersection (Intersection3, FittedLines3, OrientationRef, OrientationTolerance, MinDistance3, MaxDistance3, Angle3)
    332. *
    333. * Visualize the object with the intersection planes and the respective
    334. * intersections and measurement results
    335. * Display headings
    336. OverallCheckPassed := true
    337. Message := 'Intersections with measurement lines'
    338. MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')
    339. disp_message (WindowHandle, MessageWrapped, 'window', 12, 310, 'black', 'true')
    340. Message := 'Measurement results'
    341. MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')
    342. disp_message (WindowHandle, MessageWrapped, 'window', 12, 590, 'black', 'true')
    343. * Display first intersection
    344. affine_trans_contour_xld (Intersection1, Intersection1Vis, HomMat2DTranslate1)
    345. affine_trans_contour_xld (FittedLines1, FittedLines1Vis, HomMat2DTranslate1)
    346. dev_set_color (VisualizationColors[0])
    347. dev_set_line_width (5)
    348. dev_display (Intersection1Vis)
    349. dev_set_color ('white')
    350. dev_set_line_width (1)
    351. dev_display (FittedLines1Vis)
    352. Message := 'Angle = ' + Angle1$'.1f' + ' deg'
    353. Message[1] := 'Min Distance = ' + MinDistance1$'.1f' + ' mm'
    354. Message[2] := 'Max Distance = ' + MaxDistance1$'.1f' + ' mm'
    355. disp_message (WindowHandle, Message, 'window', 310, 600, VisualizationColors[0], 'false')
    356. ErrorIndicator := gen_tuple_const(3,'OK')
    357. ErrorIndicatorColor := gen_tuple_const(3,'dim gray')
    358. if (Angle1 [<] MinAngle or Angle1 [>] MaxAngle)
    359. ErrorIndicator[0] := 'NOK'
    360. ErrorIndicatorColor[0] := 'red'
    361. OverallCheckPassed := false
    362. endif
    363. if (MinDistance1 [<] MinDistance)
    364. ErrorIndicator[1] := 'NOK'
    365. ErrorIndicatorColor[1] := 'red'
    366. OverallCheckPassed := false
    367. endif
    368. if (MaxDistance1 [>] MaxDistance)
    369. ErrorIndicator[2] := 'NOK'
    370. ErrorIndicatorColor[2] := 'red'
    371. OverallCheckPassed := false
    372. endif
    373. disp_message (WindowHandle, ErrorIndicator, 'window', 310, 880, ErrorIndicatorColor, 'false')
    374. * Display second intersection
    375. affine_trans_contour_xld (Intersection2, Intersection2Vis, HomMat2DTranslate2)
    376. affine_trans_contour_xld (FittedLines2, FittedLines2Vis, HomMat2DTranslate2)
    377. dev_set_color (VisualizationColors[1])
    378. dev_set_line_width (5)
    379. dev_display (Intersection2Vis)
    380. dev_set_color ('white')
    381. dev_set_line_width (1)
    382. dev_display (FittedLines2Vis)
    383. Message := 'Angle = ' + Angle2$'.1f' + ' deg'
    384. Message[1] := 'Min Distance = ' + MinDistance2$'.1f' + ' mm'
    385. Message[2] := 'Max Distance = ' + MaxDistance2$'.1f' + ' mm'
    386. disp_message (WindowHandle, Message, 'window', 210, 600, VisualizationColors[1], 'false')
    387. ErrorIndicator := gen_tuple_const(3,'OK')
    388. ErrorIndicatorColor := gen_tuple_const(3,'dim gray')
    389. if (Angle2 [<] MinAngle or Angle2 [>] MaxAngle)
    390. ErrorIndicator[0] := 'NOK'
    391. ErrorIndicatorColor[0] := 'red'
    392. OverallCheckPassed := false
    393. endif
    394. if (MinDistance2 [<] MinDistance)
    395. ErrorIndicator[1] := 'NOK'
    396. ErrorIndicatorColor[1] := 'red'
    397. OverallCheckPassed := false
    398. endif
    399. if (MaxDistance2 [>] MaxDistance)
    400. ErrorIndicator[2] := 'NOK'
    401. ErrorIndicatorColor[2] := 'red'
    402. OverallCheckPassed := false
    403. endif
    404. disp_message (WindowHandle, ErrorIndicator, 'window', 210, 880, ErrorIndicatorColor, 'false')
    405. * Display third intersection
    406. affine_trans_contour_xld (Intersection3, Intersection3Vis, HomMat2DTranslate3)
    407. affine_trans_contour_xld (FittedLines3, FittedLines3Vis, HomMat2DTranslate3)
    408. dev_set_color (VisualizationColors[2])
    409. dev_set_line_width (5)
    410. dev_display (Intersection3Vis)
    411. dev_set_color ('white')
    412. dev_set_line_width (1)
    413. dev_display (FittedLines3Vis)
    414. Message := 'Angle = ' + Angle3$'.1f' + ' deg'
    415. Message[1] := 'Min Distance = ' + MinDistance3$'.1f' + ' mm'
    416. Message[2] := 'Max Distance = ' + MaxDistance3$'.1f' + ' mm'
    417. disp_message (WindowHandle, Message, 'window', 110, 600, VisualizationColors[2], 'false')
    418. ErrorIndicator := gen_tuple_const(3,'OK')
    419. ErrorIndicatorColor := gen_tuple_const(3,'dim gray')
    420. if (Angle3 [<] MinAngle or Angle3 [>] MaxAngle)
    421. ErrorIndicator[0] := 'NOK'
    422. ErrorIndicatorColor[0] := 'red'
    423. OverallCheckPassed := false
    424. endif
    425. if (MinDistance3 [<] MinDistance)
    426. ErrorIndicator[1] := 'NOK'
    427. ErrorIndicatorColor[1] := 'red'
    428. OverallCheckPassed := false
    429. endif
    430. if (MaxDistance3 [>] MaxDistance)
    431. ErrorIndicator[2] := 'NOK'
    432. ErrorIndicatorColor[2] := 'red'
    433. OverallCheckPassed := false
    434. endif
    435. disp_message (WindowHandle, ErrorIndicator, 'window', 110, 880, ErrorIndicatorColor, 'false')
    436. * Display overall check result
    437. if (OverallCheckPassed)
    438. dev_set_color ('green')
    439. gen_rectangle1 (Rectangle, 0, WindowWidth - 120, 80, WindowWidth)
    440. dev_display (Rectangle)
    441. disp_message (WindowHandle, 'OK', 'window', 30, 900, 'black', 'false')
    442. else
    443. dev_set_color ('red')
    444. gen_rectangle1 (Rectangle, 0, WindowWidth - 120, 80, WindowWidth)
    445. dev_display (Rectangle)
    446. disp_message (WindowHandle, 'NOK', 'window', 30, 900, 'white', 'false')
    447. endif
    448. if (SceneIndex < NumScenes)
    449. disp_continue_message (WindowHandle, 'black', 'true')
    450. stop ()
    451. endif
    452. endfor

  • 相关阅读:
    《动手学深度学习 Pytorch版》 5.4 自定义层
    DevExpress DxUpload实现大文件上传
    搞定面试官 - 为什么在 MySQL 中使用 Delete 删除数据之后,表数据文件大小为什么没变?
    Mac M1 M1 pro安装 protobuf 2.5.0
    Codeforces Round 855 (Div 3)(A - F)
    (附源码)springboot篮球场地预约系统 毕业设计 345655
    600+,亮眼数据背后的康铂酒店品牌硬实力
    Python sklearn实现K-means鸢尾花聚类
    详解FreeRTOS:FreeRTOS任务创建过程源码分析(进阶篇—1)
    spring揭秘总结(一)——spring的Ioc容器
  • 原文地址:https://blog.csdn.net/weixin_39354845/article/details/126438344