1,目的。

  • 测量3D翼片的距离与角度。
  • 说明:
    1. 标注A 红色框选的区域即为翼片,本示例的3D 对象共有3个翼片待测。
    2. L1L2的距离、L1L2的角度即为所求的翼片距离与角度。
      在这里插入图片描述

在这里插入图片描述在这里插入图片描述


2,原理。

  1. 使用线结构光模型(标定模式)获取作为参考对象的 3D 点云,以及结构光模型默认的lightPlaneposemovementpose
  2. 使用三个光平面与 作为参考对象的 3D 点云对象相交,获取光平面与 3D 对象的交集点云,将该交集点云投影到2D 平面形成轮廓。
  3. 筛选出所需的轮廓L1L2,求出3组 L1L2的距离均值,角度均值,将该值作为标准值。
  4. 使用结构光模型获取被测的 3D 点云,并将该3D点云与参考对象的3D点云进行表面匹配获取Pose。
  5. 对三个光平面进行刚体变化,保证光平面与被测的3D点云相切,获取切平面。
  6. 对被测对象的切平面进行投影,筛选出轮廓,计算轮廓的距离与角度是否在规定的范围内。

3,程序解析。

3.1,创建参考 3D 对象样本。
* 参考案例库:inspect_3d_surface_intersections.hdev* 目的:测量三个金属薄片翅凸起的角度与距离*
* ------------Part01,建立参考 3D 对象样本* 1.1,配置线性结构光模型。
* 模式为‘calibration’,该模式将生成默认的lightpanelpose与movementpose,如果缺省则这两个位姿为空
NumDisparityProfiles := 441
read_image (DisparityProfile, 'sheet_of_light/metal_part_1_disparity_line_000')
create_sheet_of_light_model (DisparityProfile, 'calibration', 'offset_scale', SheetOfLightModelID)
* 设置校准方法‘offset_scale’的缩放因子
* 使得重建的三维物体模型近似给出
* 单位毫米
ScaleX := 1
ScaleY := 4
ScaleZ := 0.5
set_sheet_of_light_param (SheetOfLightModelID, 'scale_x', ScaleX)
set_sheet_of_light_param (SheetOfLightModelID, 'scale_y', ScaleY)
set_sheet_of_light_param (SheetOfLightModelID, 'scale_z', ScaleZ)
* 
* 1.2,定义物体背景 z 轴分界值
MinZ := 220
* 
* Initialize display
dev_update_off ()
set_system ('clip_region', 'false')
dev_close_window ()
get_image_size (DisparityProfile, DisparityProfileWidth, DisparityProfileHeight)
WindowEnlargement := 350
WindowWidth := DisparityProfileWidth + WindowEnlargement
WindowHeight := NumDisparityProfiles
dev_open_window (0, 0, WindowWidth, WindowHeight, 'black', WindowHandle)
dev_set_part (0, 0, WindowHeight - 1, WindowWidth - 1)
get_part (WindowHandle, PartRow1, PartColumn1, PartRow2, PartColumn2)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_draw ('fill')
* 
* 1.3,定义一些可视化参数
VisualizationPlaneSize := 150
VisualizationCamParam := [0.01,0,6e-6,6e-6,WindowWidth / 2,WindowHeight / 2,WindowWidth,WindowHeight]
VisualizationPose := [-1550,680,5390,122,1,357,0]
VisualizationColors := ['magenta','blue','orange']
* 
* 1.4,通过收集测量值来创建参考样本
* 通过 线激光测量模型 将视差轮廓转换为3D对象模型
gen_image_const (DisparityImageVis, 'uint2', DisparityProfileWidth, NumDisparityProfiles)
for Index := 0 to NumDisparityProfiles - 1 by 1* Add the next disparity profile to the sheet of light modelread_image (ImageModel, 'sheet_of_light/metal_part_1_disparity_line_' + Index$'03d')set_profile_sheet_of_light (ImageModel, SheetOfLightModelID, [])* Accumulated profiles for visualizationget_grayval (ImageModel, gen_tuple_const(DisparityProfileWidth,0), [0:DisparityProfileWidth - 1], Disparities)set_grayval (DisparityImageVis, gen_tuple_const(DisparityProfileWidth,Index), [0:DisparityProfileWidth - 1], Disparities)if (Index % 5 == 4)dev_display (DisparityImageVis)Message := 'Disparity image of the reference sample'Message[1] := 'Adding disparity profile ' + (Index + 1) + '/' + NumDisparityProfilesdisp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')endif
endfor* 1.5,显示引用样本的视差图像
dev_display (DisparityImageVis)
stop ()
disp_message (WindowHandle, '引用样本的视差图', 'window', 12, 12, 'black', 'true')* 1.6,获取标定测量的三维对象(参考样本对象)
get_sheet_of_light_result_object_model_3d (SheetOfLightModelID, Model3DFull)* 最小外接长方体(min_x, min_y, min_z, max_x, max_y, max_z)。此属性长度为 6。
get_object_model_3d_params (Model3DFull, 'bounding_box1', BoundingBox1)* 1.7,去除背景后的样本 3D 对象
MaxZ := BoundingBox1[5]
select_points_object_model_3d (Model3DFull, 'point_coord_z', MinZ, MaxZ, Model3D)
clear_object_model_3d (Model3DFull)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Prepare the 3D object model for the intersection with
* the planes and to allow the alignment of the intersection
* planes to the objects to be inspected
dev_clear_window ()
dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)* 1.8,显示去除背景后的 3D 引用
disp_object_model_3d (WindowHandle, Model3D, VisualizationCamParam, VisualizationPose, [], [])
Message := '准备参考模型'
Message[1] := ' - triangulate 3D object model and'
Message[2] := ' - create surface model for alignment'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')* 1.9,计算 3D 模型的法线,并将法线信息附加到输入的模型
surface_normals_object_model_3d (Model3D, 'mls', 'mls_force_inwards', 'true', ObjectModel3DNormals)* 1.10,将离散的点数数据转换为三角网格模型
triangulate_object_model_3d (ObjectModel3DNormals, 'greedy', 'greedy_remove_small_surfaces', 200, ObjectModel3DReference, Information)
clear_object_model_3d (Model3D)
clear_object_model_3d (ObjectModel3DNormals)

释疑解析:

  1. surface_normals_object_model_3d (Model3D, 'mls', 'mls_force_inwards', 'true', ObjectModel3DNormals)

    用于计算3D物体模型的表面法线,具体参数解析如下:

    1. 核心功能:
      • 采用移动最小二乘法(MLS)计算3D点云数据的曲面法线
      • 输出带法线信息的3D对象模型(ObjectModel3DNormals)
    2. 关键参数说明:
      • Model3D:输入3D点云模型句柄
      • 'mls':当前唯一支持的法线计算方法
      • mls_force_inwards':强制法线指向模型内部的控制参数
      • 'true':启用上述强制内指功能
    3. 技术原理:
      通过MLS算法对每个点的k邻域拟合曲面(平面或高阶多项式),计算投影点的法线方向。当启用mls_force_inwards时,系统会调整法线方向使其一致指向模型内部。

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

    用于将3D点云数据转换为三角网格模型,具体参数解析如下:

    1. 核心功能:
      • 采用贪心算法(greedy)进行曲面重建
      • 可移除表面积小于指定阈值的小面片
      • 输出三角化后的3D模型(ObjectModel3DReference)和重建信息(Information)
    2. 关键参数说明:
      • ObjectModel3DNormals:输入带法线的3D模型句柄
      • 'greedy':指定使用贪心三角化算法
      • 'greedy_remove_small_surfaces':小面片过滤功能开关
      • 200:面积阈值(单位取决于输入模型),小于该值的面片将被移除
    3. 技术特点:
      • 贪心算法通过迭代连接最近邻点形成三角形,效率较高但可能丢失细节
      • 法线信息可提高重建准确性
      • 小面片过滤能有效去除噪声和离群点

3.2,创建表面匹配模型,切平面位姿
*---------------------Part02,创建表面匹配模型,翼片的切平面位姿* 2.1,Create a surface model for alignment
create_surface_model (ObjectModel3DReference, 0.03, 'model_invert_normals', 'true', SurfaceModelID)
* 
* 2.2,定义与翼片相切的位姿,平面
create_pose (300, 230, 250, -90, 0, 0, 'Rp+T', 'gba', 'point', PoseIntersectionPlane1)
create_pose (300, 900, 250, -90, 0, 0, 'Rp+T', 'gba', 'point', PoseIntersectionPlane2)
create_pose (300, 1570, 250, -90, 0, 0, 'Rp+T', 'gba', 'point', PoseIntersectionPlane3)
gen_plane_object_model_3d (PoseIntersectionPlane1, [-1,-1,1,1] * VisualizationPlaneSize, [-1,1,1,-1] * VisualizationPlaneSize, IntersectionPlane1)
gen_plane_object_model_3d (PoseIntersectionPlane2, [-1,-1,1,1] * VisualizationPlaneSize, [-1,1,1,-1] * VisualizationPlaneSize, IntersectionPlane2)
gen_plane_object_model_3d (PoseIntersectionPlane3, [-1,-1,1,1] * VisualizationPlaneSize, [-1,1,1,-1] * VisualizationPlaneSize, IntersectionPlane3)
dev_clear_window ()
dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)* 2.3,显示样本 3D 对象与与之相切的切平面
disp_object_model_3d (WindowHandle, [ObjectModel3DReference,IntersectionPlane1,IntersectionPlane2,IntersectionPlane3],VisualizationCamParam,VisualizationPose, ['color_1','color_2','color_3','alpha','alpha_0','disp_pose'], [VisualizationColors,0.75,1,'true'])
Message := 'Reference sample with predefined intersection planes'
* 正则表达式替换
MessageWrapped := regexp_replace(Message + ' ',['(.{0,25})\\s','replace_all'],'$1\n')
disp_message (WindowHandle, MessageWrapped, 'window', 12, 12, 'black', 'true'

显示效果:

在这里插入图片描述

3.3,计算 样本 翼片组的距离均值与角度均值(重点)
* ----------------------Part03,计算 样本 翼片组的距离与角度,推导出距离与角度的标准值* 3.1,获取样本 3D 对象切平面的点云
intersect_plane_object_model_3d (ObjectModel3DReference, PoseIntersectionPlane1, ObjectModel3DIntersection1)
intersect_plane_object_model_3d (ObjectModel3DReference, PoseIntersectionPlane2, ObjectModel3DIntersection2)
intersect_plane_object_model_3d (ObjectModel3DReference, PoseIntersectionPlane3, ObjectModel3DIntersection3)
* 
* 3.2,投影翼片切平面点云获取切平面XLD轮廓
project_object_model_3d_lines_to_contour_xld (Intersection1, PoseIntersectionPlane1, ObjectModel3DIntersection1)
project_object_model_3d_lines_to_contour_xld (Intersection2, PoseIntersectionPlane2, ObjectModel3DIntersection2)
project_object_model_3d_lines_to_contour_xld (Intersection3, PoseIntersectionPlane3, ObjectModel3DIntersection3)
* 
* Clean up memory
clear_object_model_3d ([ObjectModel3DIntersection1,ObjectModel3DIntersection2,ObjectModel3DIntersection3])
* 
* 3.3,筛选提取旋转角度为20±15的轮廓
OrientationRef := 20
OrientationTolerance := 15* 3.4,分析计算表示翼片的轮廓之间距离与角度
* Intersection1,投影出来的翼片轮廓; FittedLines1:拟合的翼片上线下线轮廓
analyze_intersection (Intersection1, FittedLines1, OrientationRef, OrientationTolerance, MinDistance1, MaxDistance1, Angle1)
analyze_intersection (Intersection2, FittedLines2, OrientationRef, OrientationTolerance, MinDistance2, MaxDistance2, Angle2)
analyze_intersection (Intersection3, FittedLines3, OrientationRef, OrientationTolerance, MinDistance3, MaxDistance3, Angle3)
* 
* Visualize the object with the intersection planes and the respective
* intersections and measurement results
hom_mat2d_identity (HomMat2DIdentity)* 3.5 ,显示测量结果
Message := 'Intersections with measurement lines'
MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')
disp_message (WindowHandle, MessageWrapped, 'window', 12, 330, 'black', 'true')
Message := 'Measurement results'
MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')
disp_message (WindowHandle, MessageWrapped, 'window', 12, 590, 'black', 'true')* 显示第1个翼片测量数据
hom_mat2d_translate (HomMat2DIdentity, 350, 390, HomMat2DTranslate1)
* 仿射变化相交的轮廓
affine_trans_contour_xld (Intersection1, Intersection1Vis, HomMat2DTranslate1)
* 仿射变化作为上线与下线的轮廓
affine_trans_contour_xld (FittedLines1, FittedLines1Vis, HomMat2DTranslate1)
dev_set_color (VisualizationColors[0])
dev_set_line_width (5)
dev_display (Intersection1Vis)
dev_set_color ('white')
dev_set_line_width (1)
dev_display (FittedLines1Vis)
Message := 'Angle        = ' + Angle1$'.1f' + ' deg'
Message[1] := 'Min Distance = ' + MinDistance1$'.1f' + ' mm'
Message[2] := 'Max Distance = ' + MaxDistance1$'.1f' + ' mm'
disp_message (WindowHandle, Message, 'window', 310, 600, VisualizationColors[0], 'false')* 显示第2个翼片测量数据
hom_mat2d_translate (HomMat2DIdentity, 250, 410, HomMat2DTranslate2)
affine_trans_contour_xld (Intersection2, Intersection2Vis, HomMat2DTranslate2)
affine_trans_contour_xld (FittedLines2, FittedLines2Vis, HomMat2DTranslate2)
dev_set_color (VisualizationColors[1])
dev_set_line_width (5)
dev_display (Intersection2Vis)
dev_set_color ('white')
dev_set_line_width (1)
dev_display (FittedLines2Vis)
Message := 'Angle        = ' + Angle2$'.1f' + ' deg'
Message[1] := 'Min Distance = ' + MinDistance2$'.1f' + ' mm'
Message[2] := 'Max Distance = ' + MaxDistance2$'.1f' + ' mm'
disp_message (WindowHandle, Message, 'window', 210, 600, VisualizationColors[1], 'false')* 显示第3个翼片测量数据
hom_mat2d_translate (HomMat2DIdentity, 150, 430, HomMat2DTranslate3)
affine_trans_contour_xld (Intersection3, Intersection3Vis, HomMat2DTranslate3)
affine_trans_contour_xld (FittedLines3, FittedLines3Vis, HomMat2DTranslate3)
dev_set_color (VisualizationColors[2])
dev_set_line_width (5)
dev_display (Intersection3Vis)
dev_set_color ('white')
dev_set_line_width (1)
dev_display (FittedLines3Vis)
Message := 'Angle        = ' + Angle3$'.1f' + ' deg'
Message[1] := 'Min Distance = ' + MinDistance3$'.1f' + ' mm'
Message[2] := 'Max Distance = ' + MaxDistance3$'.1f' + ' mm'
disp_message (WindowHandle, Message, 'window', 110, 600, VisualizationColors[2], 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* 3.6,根据样本三个翼片测量结果,推导出的标准参数* ======推导出的翼片标准参数
AngleRef := mean([Angle1,Angle2,Angle3])
* 角度的容差范围
MaxAngleDev := 2
* 许可的最小角度值
MinAngle := AngleRef - MaxAngleDev
* 许可的最大角度
MaxAngle := AngleRef + MaxAngleDev
* 许可的最大距离
MinDistance := 0.95 * mean([MinDistance1,MinDistance2,MinDistance3])
* 许可的最小距离
MaxDistance := 1.05 * mean([MaxDistance1,MaxDistance2,MaxDistance3])
* Display the nominal dimensions and the tolerance limits
dev_clear_window ()
Message := 'Tolerance limits for the angle and the distance of the mounting tabs, derived from the three measurements on the reference sample:'
MessageWrapped := regexp_replace(Message + ' ',['(.{0,75})\\s','replace_all'],'$1\n')
Message := MessageWrapped
Message[1] := ' '
Message[2] := 'Min Angle    = ' + MinAngle$'.1f' + ' deg'
Message[3] := 'Max Angle    = ' + MaxAngle$'.1f' + ' deg'
Message[4] := ' '
Message[5] := 'Min Distance = ' + MinDistance$'.1f' + ' mm'
Message[6] := 'Max Distance = ' + MaxDistance$'.1f' + ' mm'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*======================

效果图:

在这里插入图片描述

在这里插入图片描述


本地函数:

1,project_object_model_3d_lines_to_contour_xld

作用: 将 3D对象 投影为xld轮廓。

* PoseIntersectionPlane:切平面在世界坐标系的位姿
* PoseInvert:在切平面位置有一个虚拟相机,这个就是这个虚拟相机的位姿(外参)
* 也就是世界坐标系在虚拟相机的相机坐标系的位姿
pose_invert (PoseIntersectionPlane, PoseInvert)* 确保投影平面在虚拟的正前方
* 获取三维对象模型沿坐标轴对齐的包围盒的对角线长度,即包围盒的直径。
* 因为虚拟相机和切平面点云重合所有为了投影成像需要将该虚拟相机沿z轴进行偏移
get_object_model_3d_params (ObjectModel3DIntersection, 'diameter_axis_aligned_bounding_box', Diameter)PoseInvert[2] := PoseInvert[2] + Diameter* 3,虚拟相机的内参。
*========================
* 相机内参参数组成:*Focus:相机的焦距,如果是远心相机,则焦距为0*Kappa:畸变系数,初始值可以设置为0*Sx、Sy:单个像元的宽,高(可从相机说明书中获取)*Cx、Cy:图像的原点坐标,初始值可认为是图像的中心点,即坐标分为为图像的宽度和高度的一半*ImageWidth,ImageHeight:采集图像的宽和高*===========================
* Focus:=0:表示虚拟相机无透视缩放仅为平行投影
* 虚拟相机不需要畸变所以 Kappa:=0;
*  Sx,Sy:=1,不进行缩放按照原图大小输出
* 使用平行投影来实现所需的缩放(默认为1:1)
* CamParam为虚拟相机的内参
Scale := 1
CamParam := [0,0,1.0 / Scale,1.0 / Scale,0,0,512,512]
* 4,投影获取xld轮廓。
project_object_model_3d (Intersection, ObjectModel3DIntersection, CamParam, PoseInvert, 'data', 'lines')
return ()

释疑解惑:

为什么需要PoseInvert[2] := PoseInvert[2] + Diameter?

  • 避免物体遮挡投影
    • 当投影平面与物体位置重叠时,投影结果可能因‌物体自身遮挡‌而丢失部分几何信息。例如,若投影平面位于物体内部,部分表面会被遮挡,导致轮廓线残缺。
    • 通过沿z轴正方向平移投影平面(如代码中 PoseInvert[2] += Diameter),可使投影平面位于物体包围盒之外,从而完整捕捉物体的可见边界。
  • 平行投影的几何精度保障
    • 平行投影需保持严格的比例关系(如默认1:1缩放)。若投影平面与物体距离过近,可能导致‌坐标溢出或畸变‌,尤其在物体跨越坐标系原点时。
    • 平移后,投影平面与物体间形成安全距离(通常为包围盒直径),确保物体所有顶点坐标均位于相机视锥体内,避免裁剪错误。
  • 三维坐标系变换的物理意义
    • 位姿逆变换 pose_invert 将物体从世界坐标系转换到投影平面坐标系。此时投影平面默认位于新坐标系的‌原点‌(即原平面位置),可能导致投影平面与物体空间重叠。
    • 沿z轴平移可理解为将投影平面从“观察者视角的原点”移至“观察者前方”,符合人类视觉感知习惯。
  • 正交投影的规范化需求
    • 规范化坐标系要求投影范围限定在合理区间(如[-1,1])。若投影平面距离过近,物体坐标可能超出该范围,导致投影结果失真或不可控。
    • 调整z轴位置可对物体坐标进行归一化处理,满足图形API(如OpenGL/Direct3D)的标准化视口要求。

运算获取的轮廓Intersection示例:

在这里插入图片描述

2,analyze_intersection

作用: 筛选符合条件的轮廓片段,对符合条件的轮廓片段进行拟合,计算彼此间的距离、角度。

* selected and grouped.
* 
* Cut the contour into segments
segment_contours_xld (Intersection, ContoursSplit, 'lines_circles', 7, 3, 2)
* Select the segments that have approximately the expected orientation
select_shape_xld (ContoursSplit, SelectedXLD, ['orientation_points','orientation_points'], 'or', rad([OrientationRef,OrientationRef - 180]) - rad(OrientationTolerance), rad([OrientationRef,OrientationRef - 180]) + rad(OrientationTolerance))
* Select the three longest segments
length_xld (SelectedXLD, Length)
SelectedId := sort_index(-Length)[0:2] + 1
* 最长的片段
select_obj (SelectedXLD, ObjectSelected1, SelectedId[0])
* 第2长的片段
select_obj (SelectedXLD, ObjectSelected2, SelectedId[1])
* 第3长的片段
select_obj (SelectedXLD, ObjectSelected3, SelectedId[2])
* 计算三个片段的两两距离
* to decide, which of them represents the mounting tab
distance_cc_min (ObjectSelected1, ObjectSelected2, 'fast_point_to_segment', DistanceMin12)
distance_cc_min (ObjectSelected1, ObjectSelected3, 'fast_point_to_segment', DistanceMin13)
distance_cc_min (ObjectSelected2, ObjectSelected3, 'fast_point_to_segment', DistanceMin23)
* 两两距离最大的 距离索引
LargestDistId := sort_index(-[DistanceMin12,DistanceMin13,DistanceMin23])[0]
switch (LargestDistId)
case 0:* 片段1 与 片段2 的距离是最大时:concat_obj (ObjectSelected1, ObjectSelected2, GroundPlane)copy_obj (ObjectSelected3, MountingTab, 1, 1)break
case 1:* 片段1 与 片段3 的距离是最大时:concat_obj (ObjectSelected1, ObjectSelected3, GroundPlane)copy_obj (ObjectSelected2, MountingTab, 1, 1)break
case 2:*片段2 与 片段3 的距离是最大时:concat_obj (ObjectSelected2, ObjectSelected3, GroundPlane)copy_obj (ObjectSelected1, MountingTab, 1, 1)break
endswitch
* 
* 两个片段距离最大时,则认为这两个片段延长线是共线(翼片底线)
union_adjacent_contours_xld (GroundPlane, GroundPlaneUnion, 1000, 50, 'attr_keep')
* 拟合翼片底线
fit_line_contour_xld (GroundPlaneUnion, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
if (ColEnd < ColBegin)* Reverse the orientation of the lineT := ColEndColEnd := ColBeginColBegin := TT := RowEndRowEnd := RowBeginRowBegin := TNr := -NrNc := -Nc
endif
* 计算出的上线
gen_contour_polygon_xld (Contour, [RowBegin,RowEnd], [ColBegin,ColEnd])
*  MoutingTab 是与 另外两个共线的片段 不共线的片段
fit_line_contour_xld (MountingTab, 'tukey', -1, 0, 5, 2, RowBeginMT, ColBeginMT, RowEndMT, ColEndMT, NrMT, NcMT, DistMT)
if (ColEndMT < ColBeginMT)* Reverse the orientation of the lineT := ColEndMTColEndMT := ColBeginMTColBeginMT := TT := RowEndMTRowEndMT := RowBeginMTRowBeginMT := TNrMT := -NrMTNcMT := -NcMT
endif
* 计算出的下线
gen_contour_polygon_xld (ContourMT, [RowBeginMT,RowEndMT], [ColBeginMT,ColEndMT])
* 连接上线 与 下线
concat_obj (ContourMT, Contour, FittedLines)
* 
* Calculate the opening width and the angle
distance_pl ([RowBeginMT,RowEndMT], [ColBeginMT,ColEndMT], RowBegin, ColBegin, RowEnd, ColEnd, Distances)
MinDistance := min(Distances)
MaxDistance := max(Distances)
* 上线法向量与下线法向量的夹角
angle_ll (0, 0, NrMT, NcMT, 0, 0, Nr, Nc, AngleRad)
Angle := deg(AngleRad)
* Wrap the absolute angle to 90 deg or less
if (Angle < -90)Angle := Angle + 180
elseif (Angle > 90)Angle := Angle - 180
endif
* 
return ()

释疑解惑:

select_shape_xld算子使用orientationorientation_points作为筛选特征时,有何差异?

  • 计算原理差异
特征orientation参数orientation_points参数
几何基础基于等效椭圆主轴方向或外接矩形方向计算基于离散点集拟合主方向(类似点云处理)
轮廓依赖性依赖轮廓顺序和几何完整性忽略轮廓顺序,仅分析点集分布
自相交兼容性仅适用于非自交轮廓支持自相交轮廓
  • 参数行为差异
    1. 角度范围处理
      • orientation返回-π/2 < Phi ≤ π/2,需通过OrientationRef - 180覆盖所有方向
      • orientation_points返回-π ≤ Phi < π,直接支持全角度范围判断
    2. 筛选逻辑实现
    * orientation版本(非自交轮廓适用)
    select_shape_xld(ContoursSplit, SelectedXLD, ['orientation','orientation'], 'or', rad([OrientationRef,OrientationRef-180])-rad(OrientationTolerance),rad([OrientationRef,OrientationRef-180])+rad(OrientationTolerance)) :ml-citation{ref="3" data="citationList"}* orientation_points版本(自交轮廓适用)
    select_shape_xld(ContoursSplit, SelectedXLD, ['orientation_points','orientation_points'], 'or',rad([OrientationRef,OrientationRef-180])-rad(OrientationTolerance),rad([OrientationRef,OrientationRef-180])+rad(OrientationTolerance)) :ml-citation{ref="3" data="citationList"}
    
    注:两者均通过'or'逻辑合并OrientationRefOrientationRef-180的容忍区间,但底层计算方式不同
  • 应用场景对比
场景推荐参数原因
规则几何体筛选orientation依赖几何主轴方向,结果更稳定(如矩形零件方向检测)
自交轮廓处理orientation_points避免因轮廓自交导致方向误判(如复杂多边形或点云数据)
抗噪需求高orientation_points对离散点噪声更鲁棒(需配合test_self_intersection_xld检测)
  • 返回值验证建议
    1. 使用test_self_intersection_xld检测轮廓自交性
    2. 自交轮廓优先选择orientation_points,否则使用orientation
    3. 通过get_shape_xld算子验证实际返回的角度值范围是否符合预期

本地函数运行效果:

在这里插入图片描述

3.4,对被测 3D 对象进行测量
* --------------------------Part 4:对点云对象进行测量
*           
* 
* Inspection loop
NumScenes := 4* 4.1,通过线结构光模型获取待测的 3D 对象
for SceneIndex := 1 to NumScenes by 1dev_clear_window ()dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)* Reset 线结构光测量模型的 视差图 ; 所有其他设置都可以重用reset_sheet_of_light_model (SheetOfLightModelID)* * Create the test object by collecting the measured* disparity profiles in a sheet-of-light model and* transforming them to a 3D object modelgen_image_const (DisparityImageVis, 'uint2', DisparityProfileWidth, NumDisparityProfiles)for Index := 0 to NumDisparityProfiles - 1 by 1* Add the next disparity profile to the sheet of light modelread_image (ImageSearch, 'sheet_of_light/metal_part_' + (SceneIndex + 1) + '_disparity_line_' + Index$'03d')set_profile_sheet_of_light (ImageSearch, SheetOfLightModelID, [])* Accumulated profiles for visualizationget_grayval (ImageSearch, gen_tuple_const(DisparityProfileWidth,0), [0:DisparityProfileWidth - 1], Disparities)set_grayval (DisparityImageVis, gen_tuple_const(DisparityProfileWidth,Index), [0:DisparityProfileWidth - 1], Disparities)if (Index % 5 == 4 or Index == (NumDisparityProfiles - 1))dev_display (DisparityImageVis)Message := 'Disparity image of test object ' + SceneIndexMessage[1] := 'Adding disparity profile ' + (Index + 1) + '/' + NumDisparityProfilesdisp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')endifendfor* Get the 3D reconstruction of the test object and eliminate* the background from the respective 3D object modelget_sheet_of_light_result_object_model_3d (SheetOfLightModelID, Scene3DFull)* 4.2,去除被测 3D对像的背景*  最小外接长方体(min_x, min_y, min_z, max_x, max_y, max_z)。此属性长度为 6。get_object_model_3d_params (Scene3DFull, 'bounding_box1', BoundingBox1)MaxZ := BoundingBox1[5]* 去除背景后的 3D 点云select_points_object_model_3d (Scene3DFull, 'point_coord_z', MinZ, MaxZ, Scene3D)clear_object_model_3d (Scene3DFull)* * Align the intersection planes to the actual position and orientation* of the test object and prepare the test object for the intersectiondev_clear_window ()dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)disp_object_model_3d (WindowHandle, Scene3D, VisualizationCamParam, VisualizationPose, [], [])Message := 'Prepare the 3D object model of the test object'Message[1] := ' - perform surface based matching for alignment'Message[2] := ' - triangulate 3D object model'disp_message (WindowHandle, Message[0], 'window', 12, 12, 'black', 'true')* * Match the test object with the reference sample.* Note that the RelSamplingDistance has been set fairly small.* This is necessary because the object has only little 3D variations* that can be used by the matching process.disp_message (WindowHandle, Message[0:1], 'window', 12, 12, 'black', 'true')* 4.3,表面匹配,查找到参考对象相对于被测对象的位姿find_surface_model (SurfaceModelID, Scene3D, 0.005, 0.2, 0, 'false', [], [], Pose, Score, SurfaceMatchingResultID)* 4.4,将 相交平面 与 测试对象 进行对齐rigid_trans_object_model_3d (IntersectionPlane1, Pose, IntersectionPlane1Aligned)rigid_trans_object_model_3d (IntersectionPlane2, Pose, IntersectionPlane2Aligned)rigid_trans_object_model_3d (IntersectionPlane3, Pose, IntersectionPlane3Aligned)get_object_model_3d_params (IntersectionPlane1Aligned, 'primitive_parameter_pose', IntersectionPlane1AlignedPose)get_object_model_3d_params (IntersectionPlane2Aligned, 'primitive_parameter_pose', IntersectionPlane2AlignedPose)get_object_model_3d_params (IntersectionPlane3Aligned, 'primitive_parameter_pose', IntersectionPlane3AlignedPose)* 三角网格化 3D object modeldisp_message (WindowHandle, Message[0:2], 'window', 12, 12, 'black', 'true')triangulate_object_model_3d (Scene3D, 'greedy', [], [], Scene3DTest, Information)dev_clear_window ()disp_object_model_3d (WindowHandle, [Scene3DTest,IntersectionPlane1Aligned,IntersectionPlane2Aligned,IntersectionPlane3Aligned], VisualizationCamParam, VisualizationPose, ['color_1','color_2','color_3','alpha','alpha_0'], [VisualizationColors,0.75,1])Message := 'Test object ' + SceneIndex + ' with aligned intersection planes'MessageWrapped := regexp_replace(Message + ' ',['(.{0,25})\\s','replace_all'],'$1\n')disp_message (WindowHandle, MessageWrapped, 'window', 12, 12, 'black', 'true')* * 4.5 投影获取被测 3D 翼片的切平面xld轮廓intersect_plane_object_model_3d (Scene3DTest, IntersectionPlane1AlignedPose, ObjectModel3DIntersection1)intersect_plane_object_model_3d (Scene3DTest, IntersectionPlane2AlignedPose, ObjectModel3DIntersection2)intersect_plane_object_model_3d (Scene3DTest, IntersectionPlane3AlignedPose, ObjectModel3DIntersection3)* * project_object_model_3d_lines_to_contour_xld (Intersection1, IntersectionPlane1AlignedPose, ObjectModel3DIntersection1)project_object_model_3d_lines_to_contour_xld (Intersection2, IntersectionPlane2AlignedPose, ObjectModel3DIntersection2)project_object_model_3d_lines_to_contour_xld (Intersection3, IntersectionPlane3AlignedPose, ObjectModel3DIntersection3)* * Clean up memoryclear_object_model_3d ([ObjectModel3DIntersection1,ObjectModel3DIntersection2,ObjectModel3DIntersection3])clear_object_model_3d ([IntersectionPlane1Aligned,IntersectionPlane2Aligned,IntersectionPlane3Aligned])clear_object_model_3d ([Scene3D,Scene3DTest])* * 4.6,分析拟合计算表示翼片上下线轮廓片段的角度与距离analyze_intersection (Intersection1, FittedLines1, OrientationRef, OrientationTolerance, MinDistance1, MaxDistance1, Angle1)analyze_intersection (Intersection2, FittedLines2, OrientationRef, OrientationTolerance, MinDistance2, MaxDistance2, Angle2)analyze_intersection (Intersection3, FittedLines3, OrientationRef, OrientationTolerance, MinDistance3, MaxDistance3, Angle3)* * 4.7,显示被测3D 对象的测量结果OverallCheckPassed := trueMessage := 'Intersections with measurement lines'MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')disp_message (WindowHandle, MessageWrapped, 'window', 12, 310, 'black', 'true')Message := 'Measurement results'MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')disp_message (WindowHandle, MessageWrapped, 'window', 12, 590, 'black', 'true')* 显示第1个翼片测量结果affine_trans_contour_xld (Intersection1, Intersection1Vis, HomMat2DTranslate1)affine_trans_contour_xld (FittedLines1, FittedLines1Vis, HomMat2DTranslate1)dev_set_color (VisualizationColors[0])dev_set_line_width (5)dev_display (Intersection1Vis)dev_set_color ('white')dev_set_line_width (1)dev_display (FittedLines1Vis)Message := 'Angle        = ' + Angle1$'.1f' + ' deg'Message[1] := 'Min Distance = ' + MinDistance1$'.1f' + ' mm'Message[2] := 'Max Distance = ' + MaxDistance1$'.1f' + ' mm'disp_message (WindowHandle, Message, 'window', 310, 600, VisualizationColors[0], 'false')ErrorIndicator := gen_tuple_const(3,'OK')ErrorIndicatorColor := gen_tuple_const(3,'dim gray')* 注意[<]与< 的区别:* [<]用于‌两个数组(元组)‌ 的逐元素比较,返回一个‌布尔值数组* < 单个数值比较,返回一个布尔值if (Angle1 [<] MinAngle or Angle1 [>] MaxAngle)ErrorIndicator[0] := 'NOK'ErrorIndicatorColor[0] := 'red'OverallCheckPassed := falseendifif (MinDistance1 [<] MinDistance)ErrorIndicator[1] := 'NOK'ErrorIndicatorColor[1] := 'red'OverallCheckPassed := falseendifif (MaxDistance1 [>] MaxDistance)ErrorIndicator[2] := 'NOK'ErrorIndicatorColor[2] := 'red'OverallCheckPassed := falseendifdisp_message (WindowHandle, ErrorIndicator, 'window', 310, 880, ErrorIndicatorColor, 'false')* 第2个翼片测量数据affine_trans_contour_xld (Intersection2, Intersection2Vis, HomMat2DTranslate2)affine_trans_contour_xld (FittedLines2, FittedLines2Vis, HomMat2DTranslate2)dev_set_color (VisualizationColors[1])dev_set_line_width (5)dev_display (Intersection2Vis)dev_set_color ('white')dev_set_line_width (1)dev_display (FittedLines2Vis)Message := 'Angle        = ' + Angle2$'.1f' + ' deg'Message[1] := 'Min Distance = ' + MinDistance2$'.1f' + ' mm'Message[2] := 'Max Distance = ' + MaxDistance2$'.1f' + ' mm'disp_message (WindowHandle, Message, 'window', 210, 600, VisualizationColors[1], 'false')ErrorIndicator := gen_tuple_const(3,'OK')ErrorIndicatorColor := gen_tuple_const(3,'dim gray')if (Angle2 [<] MinAngle or Angle2 [>] MaxAngle)ErrorIndicator[0] := 'NOK'ErrorIndicatorColor[0] := 'red'OverallCheckPassed := falseendifif (MinDistance2 [<] MinDistance)ErrorIndicator[1] := 'NOK'ErrorIndicatorColor[1] := 'red'OverallCheckPassed := falseendifif (MaxDistance2 [>] MaxDistance)ErrorIndicator[2] := 'NOK'ErrorIndicatorColor[2] := 'red'OverallCheckPassed := falseendifdisp_message (WindowHandle, ErrorIndicator, 'window', 210, 880, ErrorIndicatorColor, 'false')* 第3个翼片测量数据affine_trans_contour_xld (Intersection3, Intersection3Vis, HomMat2DTranslate3)affine_trans_contour_xld (FittedLines3, FittedLines3Vis, HomMat2DTranslate3)dev_set_color (VisualizationColors[2])dev_set_line_width (5)dev_display (Intersection3Vis)dev_set_color ('white')dev_set_line_width (1)dev_display (FittedLines3Vis)Message := 'Angle        = ' + Angle3$'.1f' + ' deg'Message[1] := 'Min Distance = ' + MinDistance3$'.1f' + ' mm'Message[2] := 'Max Distance = ' + MaxDistance3$'.1f' + ' mm'disp_message (WindowHandle, Message, 'window', 110, 600, VisualizationColors[2], 'false')ErrorIndicator := gen_tuple_const(3,'OK')ErrorIndicatorColor := gen_tuple_const(3,'dim gray')if (Angle3 [<] MinAngle or Angle3 [>] MaxAngle)ErrorIndicator[0] := 'NOK'ErrorIndicatorColor[0] := 'red'OverallCheckPassed := falseendifif (MinDistance3 [<] MinDistance)ErrorIndicator[1] := 'NOK'ErrorIndicatorColor[1] := 'red'OverallCheckPassed := falseendifif (MaxDistance3 [>] MaxDistance)ErrorIndicator[2] := 'NOK'ErrorIndicatorColor[2] := 'red'OverallCheckPassed := falseendifdisp_message (WindowHandle, ErrorIndicator, 'window', 110, 880, ErrorIndicatorColor, 'false')* * 4.8,显示整体测量结果if (OverallCheckPassed)dev_set_color ('green')gen_rectangle1 (Rectangle, 0, WindowWidth - 120, 80, WindowWidth)dev_display (Rectangle)disp_message (WindowHandle, 'OK', 'window', 30, 900, 'black', 'false')elsedev_set_color ('red')gen_rectangle1 (Rectangle, 0, WindowWidth - 120, 80, WindowWidth)dev_display (Rectangle)disp_message (WindowHandle, 'NOK', 'window', 30, 900, 'white', 'false')endifif (SceneIndex < NumScenes)disp_continue_message (WindowHandle, 'black', 'true')stop ()endif
endfor

释疑解惑:

两个比较操作 [<] 与 < 有什么区别?

  • 操作对象与返回值差异

    • <(单值比较)
      用于‌单个数值‌的比较,返回一个‌布尔值‌(true/false)。
      示例:
    Result := (5 < 10)  // 返回 true
    
    • [<](数组元素级比较)
      用于‌两个数组(元组)‌ 的逐元素比较,返回一个‌布尔值数组‌。
      示例:
    A := [1, 2, 3]
    B := [3, 2, 1]
    Result := A [<] B  // 返回 [true, false, false]
    

该部分运行效果:

在这里插入图片描述
在这里插入图片描述


4,完整代码。

* 参考案例库:inspect_3d_surface_intersections.hdev* 目的:测量三个金属薄片翅凸起的角度与距离*
* ------------Part01,建立参考 3D 对象样本* 1.1,配置线性结构光模型。
* 模式为‘calibration’,该模式将生成默认的lightpanelpose与movementpose,如果缺省则这两个位姿为空
NumDisparityProfiles := 441
read_image (DisparityProfile, 'sheet_of_light/metal_part_1_disparity_line_000')
create_sheet_of_light_model (DisparityProfile, 'calibration', 'offset_scale', SheetOfLightModelID)
* 设置校准方法‘offset_scale’的缩放因子
* 使得重建的三维物体模型近似给出
* 单位毫米
ScaleX := 1
ScaleY := 4
ScaleZ := 0.5
set_sheet_of_light_param (SheetOfLightModelID, 'scale_x', ScaleX)
set_sheet_of_light_param (SheetOfLightModelID, 'scale_y', ScaleY)
set_sheet_of_light_param (SheetOfLightModelID, 'scale_z', ScaleZ)
* 
* 1.2,定义物体可以被分离的背景 z 轴坐标
MinZ := 220
* 
* Initialize display
dev_update_off ()
set_system ('clip_region', 'false')
dev_close_window ()
get_image_size (DisparityProfile, DisparityProfileWidth, DisparityProfileHeight)
WindowEnlargement := 350
WindowWidth := DisparityProfileWidth + WindowEnlargement
WindowHeight := NumDisparityProfiles
dev_open_window (0, 0, WindowWidth, WindowHeight, 'black', WindowHandle)
dev_set_part (0, 0, WindowHeight - 1, WindowWidth - 1)
get_part (WindowHandle, PartRow1, PartColumn1, PartRow2, PartColumn2)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_draw ('fill')
* 
* 1.3,定义一些可视化参数
VisualizationPlaneSize := 150
VisualizationCamParam := [0.01,0,6e-6,6e-6,WindowWidth / 2,WindowHeight / 2,WindowWidth,WindowHeight]
VisualizationPose := [-1550,680,5390,122,1,357,0]
VisualizationColors := ['magenta','blue','orange']
* 
* 1.4,通过收集测量值来创建参考样本
* 通过 线激光测量模型 将视差轮廓转换为3D对象模型
gen_image_const (DisparityImageVis, 'uint2', DisparityProfileWidth, NumDisparityProfiles)
for Index := 0 to NumDisparityProfiles - 1 by 1* Add the next disparity profile to the sheet of light modelread_image (ImageModel, 'sheet_of_light/metal_part_1_disparity_line_' + Index$'03d')set_profile_sheet_of_light (ImageModel, SheetOfLightModelID, [])* Accumulated profiles for visualizationget_grayval (ImageModel, gen_tuple_const(DisparityProfileWidth,0), [0:DisparityProfileWidth - 1], Disparities)set_grayval (DisparityImageVis, gen_tuple_const(DisparityProfileWidth,Index), [0:DisparityProfileWidth - 1], Disparities)if (Index % 5 == 4)dev_display (DisparityImageVis)Message := 'Disparity image of the reference sample'Message[1] := 'Adding disparity profile ' + (Index + 1) + '/' + NumDisparityProfilesdisp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')endif
endfor* 1.5,显示引用样本的视差图像
dev_display (DisparityImageVis)
stop ()
disp_message (WindowHandle, '引用样本的视差图', 'window', 12, 12, 'black', 'true')* 1.6,获取标定测量的三维对象(参考样本对象)
get_sheet_of_light_result_object_model_3d (SheetOfLightModelID, Model3DFull)* 最小外接长方体(min_x, min_y, min_z, max_x, max_y, max_z)。此属性长度为 6。
get_object_model_3d_params (Model3DFull, 'bounding_box1', BoundingBox1)* 1.7,去除背景后的样本 3D 对象
MaxZ := BoundingBox1[5]
select_points_object_model_3d (Model3DFull, 'point_coord_z', MinZ, MaxZ, Model3D)
clear_object_model_3d (Model3DFull)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Prepare the 3D object model for the intersection with
* the planes and to allow the alignment of the intersection
* planes to the objects to be inspected
dev_clear_window ()
dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)* 1.8,显示去除背景后的 3D 引用
disp_object_model_3d (WindowHandle, Model3D, VisualizationCamParam, VisualizationPose, [], [])
Message := '准备参考模型'
Message[1] := ' - triangulate 3D object model and'
Message[2] := ' - create surface model for alignment'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')* 1.9,计算 3D 模型的法线,并将法线信息附加到输入的模型
surface_normals_object_model_3d (Model3D, 'mls', 'mls_force_inwards', 'true', ObjectModel3DNormals)* 1.10,将离散的点数数据转换为三角网格模型
triangulate_object_model_3d (ObjectModel3DNormals, 'greedy', 'greedy_remove_small_surfaces', 200, ObjectModel3DReference, Information)
clear_object_model_3d (Model3D)
clear_object_model_3d (ObjectModel3DNormals)*---------------------Part02,创建表面匹配模型,翼片的切平面位姿* 2.1,Create a surface model for alignment
create_surface_model (ObjectModel3DReference, 0.03, 'model_invert_normals', 'true', SurfaceModelID)
* 
* 2.2,定义与翼片相切的位姿,平面
create_pose (300, 230, 250, -90, 0, 0, 'Rp+T', 'gba', 'point', PoseIntersectionPlane1)
create_pose (300, 900, 250, -90, 0, 0, 'Rp+T', 'gba', 'point', PoseIntersectionPlane2)
create_pose (300, 1570, 250, -90, 0, 0, 'Rp+T', 'gba', 'point', PoseIntersectionPlane3)
gen_plane_object_model_3d (PoseIntersectionPlane1, [-1,-1,1,1] * VisualizationPlaneSize, [-1,1,1,-1] * VisualizationPlaneSize, IntersectionPlane1)
gen_plane_object_model_3d (PoseIntersectionPlane2, [-1,-1,1,1] * VisualizationPlaneSize, [-1,1,1,-1] * VisualizationPlaneSize, IntersectionPlane2)
gen_plane_object_model_3d (PoseIntersectionPlane3, [-1,-1,1,1] * VisualizationPlaneSize, [-1,1,1,-1] * VisualizationPlaneSize, IntersectionPlane3)
dev_clear_window ()
dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)* 2.3,显示样本 3D 对象与与之相切的切平面
disp_object_model_3d (WindowHandle, [ObjectModel3DReference,IntersectionPlane1,IntersectionPlane2,IntersectionPlane3],VisualizationCamParam,VisualizationPose, ['color_1','color_2','color_3','alpha','alpha_0','disp_pose'], [VisualizationColors,0.75,1,'true'])
Message := 'Reference sample with predefined intersection planes'
* 正则表达式替换
MessageWrapped := regexp_replace(Message + ' ',['(.{0,25})\\s','replace_all'],'$1\n')
disp_message (WindowHandle, MessageWrapped, 'window', 12, 12, 'black', 'true')
* * ----------------------Part03,计算 样本 翼片组的距离与角度,推导出距离与角度的标准值* 3.1,获取样本 3D 对象切平面的点云
intersect_plane_object_model_3d (ObjectModel3DReference, PoseIntersectionPlane1, ObjectModel3DIntersection1)
intersect_plane_object_model_3d (ObjectModel3DReference, PoseIntersectionPlane2, ObjectModel3DIntersection2)
intersect_plane_object_model_3d (ObjectModel3DReference, PoseIntersectionPlane3, ObjectModel3DIntersection3)
* 
* 3.2,投影翼片切平面点云获取切平面XLD轮廓
project_object_model_3d_lines_to_contour_xld (Intersection1, PoseIntersectionPlane1, ObjectModel3DIntersection1)
project_object_model_3d_lines_to_contour_xld (Intersection2, PoseIntersectionPlane2, ObjectModel3DIntersection2)
project_object_model_3d_lines_to_contour_xld (Intersection3, PoseIntersectionPlane3, ObjectModel3DIntersection3)
* 
* Clean up memory
clear_object_model_3d ([ObjectModel3DIntersection1,ObjectModel3DIntersection2,ObjectModel3DIntersection3])
* 
* 3.3,筛选提取旋转角度为20±15的轮廓
OrientationRef := 20
OrientationTolerance := 15* 3.4,分析计算表示翼片的轮廓之间距离与角度
* Intersection1,投影出来的翼片轮廓; FittedLines1:拟合的翼片上线下线轮廓
analyze_intersection (Intersection1, FittedLines1, OrientationRef, OrientationTolerance, MinDistance1, MaxDistance1, Angle1)
analyze_intersection (Intersection2, FittedLines2, OrientationRef, OrientationTolerance, MinDistance2, MaxDistance2, Angle2)
analyze_intersection (Intersection3, FittedLines3, OrientationRef, OrientationTolerance, MinDistance3, MaxDistance3, Angle3)
* 
* Visualize the object with the intersection planes and the respective
* intersections and measurement results
hom_mat2d_identity (HomMat2DIdentity)* 3.5 ,显示测量结果
Message := 'Intersections with measurement lines'
MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')
disp_message (WindowHandle, MessageWrapped, 'window', 12, 330, 'black', 'true')
Message := 'Measurement results'
MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')
disp_message (WindowHandle, MessageWrapped, 'window', 12, 590, 'black', 'true')* 显示第1个翼片测量数据
hom_mat2d_translate (HomMat2DIdentity, 350, 390, HomMat2DTranslate1)
* 仿射变化相交的轮廓
affine_trans_contour_xld (Intersection1, Intersection1Vis, HomMat2DTranslate1)
* 仿射变化作为上线与下线的轮廓
affine_trans_contour_xld (FittedLines1, FittedLines1Vis, HomMat2DTranslate1)
dev_set_color (VisualizationColors[0])
dev_set_line_width (5)
dev_display (Intersection1Vis)
dev_set_color ('white')
dev_set_line_width (1)
dev_display (FittedLines1Vis)
Message := 'Angle        = ' + Angle1$'.1f' + ' deg'
Message[1] := 'Min Distance = ' + MinDistance1$'.1f' + ' mm'
Message[2] := 'Max Distance = ' + MaxDistance1$'.1f' + ' mm'
disp_message (WindowHandle, Message, 'window', 310, 600, VisualizationColors[0], 'false')* 显示第2个翼片测量数据
hom_mat2d_translate (HomMat2DIdentity, 250, 410, HomMat2DTranslate2)
affine_trans_contour_xld (Intersection2, Intersection2Vis, HomMat2DTranslate2)
affine_trans_contour_xld (FittedLines2, FittedLines2Vis, HomMat2DTranslate2)
dev_set_color (VisualizationColors[1])
dev_set_line_width (5)
dev_display (Intersection2Vis)
dev_set_color ('white')
dev_set_line_width (1)
dev_display (FittedLines2Vis)
Message := 'Angle        = ' + Angle2$'.1f' + ' deg'
Message[1] := 'Min Distance = ' + MinDistance2$'.1f' + ' mm'
Message[2] := 'Max Distance = ' + MaxDistance2$'.1f' + ' mm'
disp_message (WindowHandle, Message, 'window', 210, 600, VisualizationColors[1], 'false')* 显示第3个翼片测量数据
hom_mat2d_translate (HomMat2DIdentity, 150, 430, HomMat2DTranslate3)
affine_trans_contour_xld (Intersection3, Intersection3Vis, HomMat2DTranslate3)
affine_trans_contour_xld (FittedLines3, FittedLines3Vis, HomMat2DTranslate3)
dev_set_color (VisualizationColors[2])
dev_set_line_width (5)
dev_display (Intersection3Vis)
dev_set_color ('white')
dev_set_line_width (1)
dev_display (FittedLines3Vis)
Message := 'Angle        = ' + Angle3$'.1f' + ' deg'
Message[1] := 'Min Distance = ' + MinDistance3$'.1f' + ' mm'
Message[2] := 'Max Distance = ' + MaxDistance3$'.1f' + ' mm'
disp_message (WindowHandle, Message, 'window', 110, 600, VisualizationColors[2], 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* 3.6,根据样本三个翼片测量结果,推导出的标准参数* ======推导出的翼片标准参数
AngleRef := mean([Angle1,Angle2,Angle3])
* 角度的容差范围
MaxAngleDev := 2
* 许可的最小角度值
MinAngle := AngleRef - MaxAngleDev
* 许可的最大角度
MaxAngle := AngleRef + MaxAngleDev
* 许可的最大距离
MinDistance := 0.95 * mean([MinDistance1,MinDistance2,MinDistance3])
* 许可的最小距离
MaxDistance := 1.05 * mean([MaxDistance1,MaxDistance2,MaxDistance3])
* Display the nominal dimensions and the tolerance limits
dev_clear_window ()
Message := 'Tolerance limits for the angle and the distance of the mounting tabs, derived from the three measurements on the reference sample:'
MessageWrapped := regexp_replace(Message + ' ',['(.{0,75})\\s','replace_all'],'$1\n')
Message := MessageWrapped
Message[1] := ' '
Message[2] := 'Min Angle    = ' + MinAngle$'.1f' + ' deg'
Message[3] := 'Max Angle    = ' + MaxAngle$'.1f' + ' deg'
Message[4] := ' '
Message[5] := 'Min Distance = ' + MinDistance$'.1f' + ' mm'
Message[6] := 'Max Distance = ' + MaxDistance$'.1f' + ' mm'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*======================
* 
* 
* --------------------------Part 4:对点云对象进行测量
*           
* 
* Inspection loop
NumScenes := 4* 4.1,通过线结构光模型获取待测的 3D 对象
for SceneIndex := 1 to NumScenes by 1dev_clear_window ()dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)* Reset 线结构光测量模型的 视差图 ; 所有其他设置都可以重用reset_sheet_of_light_model (SheetOfLightModelID)* * Create the test object by collecting the measured* disparity profiles in a sheet-of-light model and* transforming them to a 3D object modelgen_image_const (DisparityImageVis, 'uint2', DisparityProfileWidth, NumDisparityProfiles)for Index := 0 to NumDisparityProfiles - 1 by 1* Add the next disparity profile to the sheet of light modelread_image (ImageSearch, 'sheet_of_light/metal_part_' + (SceneIndex + 1) + '_disparity_line_' + Index$'03d')set_profile_sheet_of_light (ImageSearch, SheetOfLightModelID, [])* Accumulated profiles for visualizationget_grayval (ImageSearch, gen_tuple_const(DisparityProfileWidth,0), [0:DisparityProfileWidth - 1], Disparities)set_grayval (DisparityImageVis, gen_tuple_const(DisparityProfileWidth,Index), [0:DisparityProfileWidth - 1], Disparities)if (Index % 5 == 4 or Index == (NumDisparityProfiles - 1))dev_display (DisparityImageVis)Message := 'Disparity image of test object ' + SceneIndexMessage[1] := 'Adding disparity profile ' + (Index + 1) + '/' + NumDisparityProfilesdisp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')endifendfor* Get the 3D reconstruction of the test object and eliminate* the background from the respective 3D object modelget_sheet_of_light_result_object_model_3d (SheetOfLightModelID, Scene3DFull)* 4.2,去除被测 3D对像的背景*  最小外接长方体(min_x, min_y, min_z, max_x, max_y, max_z)。此属性长度为 6。get_object_model_3d_params (Scene3DFull, 'bounding_box1', BoundingBox1)MaxZ := BoundingBox1[5]* 去除背景后的 3D 点云select_points_object_model_3d (Scene3DFull, 'point_coord_z', MinZ, MaxZ, Scene3D)clear_object_model_3d (Scene3DFull)* * Align the intersection planes to the actual position and orientation* of the test object and prepare the test object for the intersectiondev_clear_window ()dev_set_part (PartRow1, PartColumn1, PartRow2, PartColumn2)disp_object_model_3d (WindowHandle, Scene3D, VisualizationCamParam, VisualizationPose, [], [])Message := 'Prepare the 3D object model of the test object'Message[1] := ' - perform surface based matching for alignment'Message[2] := ' - triangulate 3D object model'disp_message (WindowHandle, Message[0], 'window', 12, 12, 'black', 'true')* * Match the test object with the reference sample.* Note that the RelSamplingDistance has been set fairly small.* This is necessary because the object has only little 3D variations* that can be used by the matching process.disp_message (WindowHandle, Message[0:1], 'window', 12, 12, 'black', 'true')* 4.3,表面匹配,查找到参考对象相对于被测对象的位姿find_surface_model (SurfaceModelID, Scene3D, 0.005, 0.2, 0, 'false', [], [], Pose, Score, SurfaceMatchingResultID)* 4.4,将 相交平面 与 测试对象 进行对齐rigid_trans_object_model_3d (IntersectionPlane1, Pose, IntersectionPlane1Aligned)rigid_trans_object_model_3d (IntersectionPlane2, Pose, IntersectionPlane2Aligned)rigid_trans_object_model_3d (IntersectionPlane3, Pose, IntersectionPlane3Aligned)get_object_model_3d_params (IntersectionPlane1Aligned, 'primitive_parameter_pose', IntersectionPlane1AlignedPose)get_object_model_3d_params (IntersectionPlane2Aligned, 'primitive_parameter_pose', IntersectionPlane2AlignedPose)get_object_model_3d_params (IntersectionPlane3Aligned, 'primitive_parameter_pose', IntersectionPlane3AlignedPose)* 三角网格化 3D object modeldisp_message (WindowHandle, Message[0:2], 'window', 12, 12, 'black', 'true')triangulate_object_model_3d (Scene3D, 'greedy', [], [], Scene3DTest, Information)dev_clear_window ()disp_object_model_3d (WindowHandle, [Scene3DTest,IntersectionPlane1Aligned,IntersectionPlane2Aligned,IntersectionPlane3Aligned], VisualizationCamParam, VisualizationPose, ['color_1','color_2','color_3','alpha','alpha_0'], [VisualizationColors,0.75,1])Message := 'Test object ' + SceneIndex + ' with aligned intersection planes'MessageWrapped := regexp_replace(Message + ' ',['(.{0,25})\\s','replace_all'],'$1\n')disp_message (WindowHandle, MessageWrapped, 'window', 12, 12, 'black', 'true')* * 4.5 投影获取被测 3D 翼片的切平面xld轮廓intersect_plane_object_model_3d (Scene3DTest, IntersectionPlane1AlignedPose, ObjectModel3DIntersection1)intersect_plane_object_model_3d (Scene3DTest, IntersectionPlane2AlignedPose, ObjectModel3DIntersection2)intersect_plane_object_model_3d (Scene3DTest, IntersectionPlane3AlignedPose, ObjectModel3DIntersection3)* * project_object_model_3d_lines_to_contour_xld (Intersection1, IntersectionPlane1AlignedPose, ObjectModel3DIntersection1)project_object_model_3d_lines_to_contour_xld (Intersection2, IntersectionPlane2AlignedPose, ObjectModel3DIntersection2)project_object_model_3d_lines_to_contour_xld (Intersection3, IntersectionPlane3AlignedPose, ObjectModel3DIntersection3)* * Clean up memoryclear_object_model_3d ([ObjectModel3DIntersection1,ObjectModel3DIntersection2,ObjectModel3DIntersection3])clear_object_model_3d ([IntersectionPlane1Aligned,IntersectionPlane2Aligned,IntersectionPlane3Aligned])clear_object_model_3d ([Scene3D,Scene3DTest])* * 4.6,分析拟合计算表示翼片上下线轮廓片段的角度与距离analyze_intersection (Intersection1, FittedLines1, OrientationRef, OrientationTolerance, MinDistance1, MaxDistance1, Angle1)analyze_intersection (Intersection2, FittedLines2, OrientationRef, OrientationTolerance, MinDistance2, MaxDistance2, Angle2)analyze_intersection (Intersection3, FittedLines3, OrientationRef, OrientationTolerance, MinDistance3, MaxDistance3, Angle3)* * 4.7,显示被测3D 对象的测量结果OverallCheckPassed := trueMessage := 'Intersections with measurement lines'MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')disp_message (WindowHandle, MessageWrapped, 'window', 12, 310, 'black', 'true')Message := 'Measurement results'MessageWrapped := regexp_replace(Message + ' ',['(.{0,20})\\s','replace_all'],'$1\n')disp_message (WindowHandle, MessageWrapped, 'window', 12, 590, 'black', 'true')* 显示第1个翼片测量结果affine_trans_contour_xld (Intersection1, Intersection1Vis, HomMat2DTranslate1)affine_trans_contour_xld (FittedLines1, FittedLines1Vis, HomMat2DTranslate1)dev_set_color (VisualizationColors[0])dev_set_line_width (5)dev_display (Intersection1Vis)dev_set_color ('white')dev_set_line_width (1)dev_display (FittedLines1Vis)Message := 'Angle        = ' + Angle1$'.1f' + ' deg'Message[1] := 'Min Distance = ' + MinDistance1$'.1f' + ' mm'Message[2] := 'Max Distance = ' + MaxDistance1$'.1f' + ' mm'disp_message (WindowHandle, Message, 'window', 310, 600, VisualizationColors[0], 'false')ErrorIndicator := gen_tuple_const(3,'OK')ErrorIndicatorColor := gen_tuple_const(3,'dim gray')* 注意[<]与< 的区别:* [<]用于‌两个数组(元组)‌ 的逐元素比较,返回一个‌布尔值数组* < 单个数值比较,返回一个布尔值if (Angle1 [<] MinAngle or Angle1 [>] MaxAngle)ErrorIndicator[0] := 'NOK'ErrorIndicatorColor[0] := 'red'OverallCheckPassed := falseendifif (MinDistance1 [<] MinDistance)ErrorIndicator[1] := 'NOK'ErrorIndicatorColor[1] := 'red'OverallCheckPassed := falseendifif (MaxDistance1 [>] MaxDistance)ErrorIndicator[2] := 'NOK'ErrorIndicatorColor[2] := 'red'OverallCheckPassed := falseendifdisp_message (WindowHandle, ErrorIndicator, 'window', 310, 880, ErrorIndicatorColor, 'false')* 第2个翼片测量数据affine_trans_contour_xld (Intersection2, Intersection2Vis, HomMat2DTranslate2)affine_trans_contour_xld (FittedLines2, FittedLines2Vis, HomMat2DTranslate2)dev_set_color (VisualizationColors[1])dev_set_line_width (5)dev_display (Intersection2Vis)dev_set_color ('white')dev_set_line_width (1)dev_display (FittedLines2Vis)Message := 'Angle        = ' + Angle2$'.1f' + ' deg'Message[1] := 'Min Distance = ' + MinDistance2$'.1f' + ' mm'Message[2] := 'Max Distance = ' + MaxDistance2$'.1f' + ' mm'disp_message (WindowHandle, Message, 'window', 210, 600, VisualizationColors[1], 'false')ErrorIndicator := gen_tuple_const(3,'OK')ErrorIndicatorColor := gen_tuple_const(3,'dim gray')if (Angle2 [<] MinAngle or Angle2 [>] MaxAngle)ErrorIndicator[0] := 'NOK'ErrorIndicatorColor[0] := 'red'OverallCheckPassed := falseendifif (MinDistance2 [<] MinDistance)ErrorIndicator[1] := 'NOK'ErrorIndicatorColor[1] := 'red'OverallCheckPassed := falseendifif (MaxDistance2 [>] MaxDistance)ErrorIndicator[2] := 'NOK'ErrorIndicatorColor[2] := 'red'OverallCheckPassed := falseendifdisp_message (WindowHandle, ErrorIndicator, 'window', 210, 880, ErrorIndicatorColor, 'false')* 第3个翼片测量数据affine_trans_contour_xld (Intersection3, Intersection3Vis, HomMat2DTranslate3)affine_trans_contour_xld (FittedLines3, FittedLines3Vis, HomMat2DTranslate3)dev_set_color (VisualizationColors[2])dev_set_line_width (5)dev_display (Intersection3Vis)dev_set_color ('white')dev_set_line_width (1)dev_display (FittedLines3Vis)Message := 'Angle        = ' + Angle3$'.1f' + ' deg'Message[1] := 'Min Distance = ' + MinDistance3$'.1f' + ' mm'Message[2] := 'Max Distance = ' + MaxDistance3$'.1f' + ' mm'disp_message (WindowHandle, Message, 'window', 110, 600, VisualizationColors[2], 'false')ErrorIndicator := gen_tuple_const(3,'OK')ErrorIndicatorColor := gen_tuple_const(3,'dim gray')if (Angle3 [<] MinAngle or Angle3 [>] MaxAngle)ErrorIndicator[0] := 'NOK'ErrorIndicatorColor[0] := 'red'OverallCheckPassed := falseendifif (MinDistance3 [<] MinDistance)ErrorIndicator[1] := 'NOK'ErrorIndicatorColor[1] := 'red'OverallCheckPassed := falseendifif (MaxDistance3 [>] MaxDistance)ErrorIndicator[2] := 'NOK'ErrorIndicatorColor[2] := 'red'OverallCheckPassed := falseendifdisp_message (WindowHandle, ErrorIndicator, 'window', 110, 880, ErrorIndicatorColor, 'false')* * 4.8,显示整体测量结果if (OverallCheckPassed)dev_set_color ('green')gen_rectangle1 (Rectangle, 0, WindowWidth - 120, 80, WindowWidth)dev_display (Rectangle)disp_message (WindowHandle, 'OK', 'window', 30, 900, 'black', 'false')elsedev_set_color ('red')gen_rectangle1 (Rectangle, 0, WindowWidth - 120, 80, WindowWidth)dev_display (Rectangle)disp_message (WindowHandle, 'NOK', 'window', 30, 900, 'white', 'false')endifif (SceneIndex < NumScenes)disp_continue_message (WindowHandle, 'black', 'true')stop ()endif
endfor
* Clean up memory
clear_object_model_3d ([ObjectModel3DReference,IntersectionPlane1,IntersectionPlane2,IntersectionPlane3])
clear_sheet_of_light_model (SheetOfLightModelID)
clear_surface_model (SurfaceModelID)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/907761.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/907761.shtml
英文地址,请注明出处:http://en.pswp.cn/news/907761.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入理解 SQL 的 JOIN 查询:从基础到高级的第一步

在处理数据库时&#xff0c;我们常常需要从多个表中提取数据。比如想知道一个城市的天气情况&#xff0c;同时又想知道这个城市的具体位置。这就需要将 weather 表和 cities 表结合起来查询。这种操作在 SQL 中被称为 JOIN 查询。 现在看下两种表的情况 1.weather 表&#xff…

上传头像upload的简易方法,转base64调接口的

1.首页使用el-image显示数据&#xff0c;用的是转base64后端返给的 <el-table-column prop"avatar" align"center" label"头像"><template #default"scope"><el-image style"height: 40px;width: 40px;" :sr…

[AD] CrownJewel-1 Logon 4799+vss-ShadowCopy+NTDS.dit/SYSTEM+$MFT

QA QA攻擊者可以濫用 vssadmin 實用程式來建立卷影快照&#xff0c;然後提取 NTDS.dit 等敏感檔案來繞過安全機制。確定卷影複製服務進入運作狀態的時間。2024-05-14 03:42:16建立卷影快照時&#xff0c;磁碟區複製服務會使用機器帳戶驗證權限並列舉使用者群組。找到卷影複製過…

rtpmixsound:实现音频混音攻击!全参数详细教程!Kali Linux教程!

简介 一种将预先录制的音频与指定目标音频流中的音频&#xff08;即 RTP&#xff09;实时混合的工具。 一款用于将预先录制的音频与指定目标音频流中的音频&#xff08;即 RTP&#xff09;实时混合的工具。该工具创建于 2006 年 8 月至 9 月之间。该工具名为 rtpmixsound。它…

GitHub 趋势日报 (2025年05月28日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 2379 agenticSeek 1521 computer-science 841 n8n 577 langflow 351 qlib 282 skt…

threejsPBR材质与纹理贴图

1. PBR材质简介 本节课没有具体的代码&#xff0c;就是给大家科普一下PBR材质&#xff0c;所谓PBR就是&#xff0c;基于物理的渲染(physically-based rendering)。 Three.js提供了两个PBR材质相关的APIMeshStandardMaterial和MeshPhysicalMaterial,MeshPhysicalMaterial是Mes…

Android 12系统源码_多屏幕(四)自由窗口模式

一、小窗模式 1.1 小窗功能的开启方式 开发者模式下开启小窗功能 adb 手动开启 adb shell settings put global enable_freeform_support 1 adb shell settings put global force_resizable_activities 11.2 源码配置 copy file # add for freedom PRODUCT_COPY_FILES …

C# 将HTML文档、HTML字符串转换为图片

在.NET开发中&#xff0c;将HTML内容转换为图片的需求广泛存在于报告生成、邮件内容存档、网页快照等场景。Free Spire.Doc for .NET作为一款免费的专业文档处理库&#xff0c;无需Microsoft Word依赖&#xff0c;即可轻松实现这一功能。本文将深入解析HTML文档和字符串转图片两…

【HTML-15.2】HTML表单按钮全面指南:从基础到高级实践

表单按钮是网页交互的核心元素&#xff0c;作为用户提交数据、触发操作的主要途径&#xff0c;其重要性不言而喻。本文将系统性地介绍HTML表单按钮的各种类型、使用场景、最佳实践以及高级技巧&#xff0c;帮助开发者构建更高效、更易用的表单交互体验。 1. 基础按钮类型 1.1…

吴恩达MCP课程(4):connect_server_mcp_chatbot

目录 完整代码代码解释1. 导入和初始化2. 类型定义3. MCP_ChatBot 类初始化4. 查询处理 (process_query)5. 服务器连接管理6. 核心特性总结 示例 完整代码 原课程代码是用Anthropic写的&#xff0c;下面代码是用OpenAI改写的&#xff0c;模型则用阿里巴巴的模型做测试 .env 文…

C++内存学习

引入 在实例化对象时&#xff0c;不管是编译器还是我们自己&#xff0c;会使用构造函数给成员变量一个合适的初始值。 但是经过构造函数之后&#xff0c;我们还不能将其称为成员变量的初始化&#xff1a; 构造函数中的语句只能称为赋初值&#xff0c;而不能称作初始化 因为初…

MySQL 大战 PostgreSQL

一、底层架构对比 ​​维度​​​​MySQL​​​​PostgreSQL​​​​存储引擎​​多引擎支持&#xff08;InnoDB、MyISAM等&#xff09;单一存储引擎&#xff08;支持扩展如Zheap、Zedstore&#xff09;​​事务实现​​基于UNDO日志的MVCC基于堆表(Heap)的MVCC​​锁机制​​…

基于FPGA的二叉决策树cart算法verilog实现,训练环节采用MATLAB仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) MATLAB训练结果 上述决策树判决条件&#xff1a; 分类的决策树1 if x21<17191.5 then node 2 elseif x21>17191…

【RAG】RAG综述|一文了解RAG|从零开始(下)

文章目录 5. RAG的架构5.1 Naive RAG5.2 Advanced RAG5.2.1 检索前处理和数据索引技术5.2.2 知识分片技术5.2.3 分层索引5.2.4 检索技术5.2.4.1 优化用户查询5.2.4.2 通过假想文档嵌入修复查询和文档不对称5.2.4.3 Routing5.2.4.5 自查询检索5.2.4.6 混合搜索5.2.4.7 图检索5.2…

山东大学软件学院项目实训-基于大模型的模拟面试系统-面试官和面试记录的分享功能(2)

本文记录在发布文章时&#xff0c;可以添加自己创建的面试官和面试记录到文章中这一功能的实现。 前端 首先是在原本的界面的底部添加了两个多选框&#xff08;后期需要美化调整&#xff09; 实现的代码&#xff1a; <el-col style"margin-top: 1rem;"><e…

FPGA纯verilog实现MIPI-DSI视频编码输出,提供工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我这里已有的 MIPI 编解码方案 3、设计思路框架工程设计原理框图FPGA内部彩条RGB数据位宽转换RGB数据缓存MIPI-DSI协议层编码MIPI-DPHY物理层串化MIPI-LVDS显示屏工程…

LXQt修改开始菜单高亮

开始菜单红色高亮很难看 mkdir -p ~/.local/share/lxqt/palettes/ mkdir -p ~/.local/share/lxqt/themes/ cp /usr/share/lxqt/palettes/Dark ~/.local/share/lxqt/palettes/Darker cp -p /usr/share/lxqt/themes/dark ~/.local/share/lxqt/themes/darker lxqt-panel.qss L…

DeepSeek-R1-0528-Qwen3-8B 本地ollama离线运行使用和llamafactory lora微调

参考: https://huggingface.co/deepseek-ai/DeepSeek-R1-0528-Qwen3-8B 量化版本: https://huggingface.co/unsloth/DeepSeek-R1-0528-Qwen3-8B-GGUF https://docs.unsloth.ai/basics/deepseek-r1-0528-how-to-run-locally 1、ollama运行 升级ollama版本到0.9.0 支持直接…

vue3 + WebSocket + Node 搭建前后端分离项目 开箱即用

[TOC](vue3 WebSocket Node 搭建前后端分离项目) 开箱即用 前言 top1&#xff1a;vue3.5搭建前端H5 top2&#xff1a;Node.js koa搭建后端服务接口 top3&#xff1a;WebSocket 长连接实现用户在线聊天 top4&#xff1a;接口实现模块化 Mysql 自定义 top5&#xff1a;文件上…

Vue 前端代码规范实战:ESLint v9、Prettier 与 Stylelint 集成指南与最佳实践

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …