当前位置:   article > 正文

Halcon 3D 切片法检测物料_halcon 3d测量

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/109041
推荐阅读
相关标签
  

闽ICP备14008679号