Halcon之计算抓取螺母的位姿

文章目录

      • 1,项目说明。
      • 2,注意事项
      • 3,关联的主要算子
        • 3.1, `gen_parallels_xld `
        • 3.2 ,`convert_pose_type`
      • 4,程序流程。
      • 5,代码
      • 6,Demo链接。

1,项目说明。

  1. Robot标定使用的模式是eye-to-hand,即相机是固定静止,相机不随Robot运动。
  2. BaseInCamPose、GripperInToolPose位姿由手眼标定事先标定完成。
  3. 抓取螺母是基于2D场景而非3D点云场景,在2D场景下忽视螺母高度,视螺母高度为0。
  4. 抓取螺母的姿态:工具坐标系位于Robot基础坐标系的位姿(ToolInBasePose)即发送给Robot的位姿数据。
  5. Demo使用的文件,图片需从halcon安装文件中获取。

2,注意事项

  • **相机的外参:**相机的姿态,世界坐标系在相机坐标系中位姿。

  • xld_cont‌ 与 ‌xld_poly 的区别:

    **xld_cont‌ 与 ‌xld_poly**‌ 是两种不同的 XLD(扩展线描述)对象类型,其核心区别如下:

    1. 数据结构差异

    • ‌**xld_cont(XLD 轮廓)**‌
      表示原始的轮廓数据,由一系列连续的、亚像素精度的点构成,通常通过边缘检测(如 edges_sub_pix)或区域转换(如 gen_contour_region_xld)生成。
      • 包含完整的几何细节,适用于需要高精度分析的任务(如曲率计算、亚像素测量)。
      • 支持开放或闭合的轮廓形态。
    • ‌**xld_poly(XLD 多边形)**‌
      是通过对 xld_cont 进行多边形近似后生成的简化表示,由折线段的关键顶点构成。
      • 通过算法(如 Ramer 算法)减少点数,保留主要形状特征。
      • 适用于几何特征提取、快速匹配等对效率要求较高的场景。

    2. 生成方式与转换

    • 生成 xld_cont 的典型方法
      • 边缘检测算子(如 edges_sub_pix)直接输出 xld_cont
      • 从区域转换而来(如 gen_contour_region_xld)。
    • 生成 xld_poly 的核心算子
      • 使用 gen_polygons_xldxld_cont 进行多边形近似,需指定算法类型(如 'ramer')和精度参数 Alpha
      • 手动创建多边形轮廓时,可通过 gen_contour_polygon_xld 直接生成 xld_poly

    3. 应用场景对比

    特征‌**xld_cont**‌‌**xld_poly**‌
    精度亚像素级,保留完整细节近似表达,精度由参数控制
    数据复杂度点数多,存储密集点数少,结构简化
    典型用途高精度测量、复杂形状分析快速几何分析、模板匹配
    操作灵活性支持复杂几何变换与特征计算便于提取线段端点或平行边
    包含的数据类型基于Row,Column的坐标基于Row,Column的坐标,长度,角度

    4. 相互转换关系

    • ‌**xld_contxld_poly**‌
      使用 gen_polygons_xld 进行多边形近似,通过调整 Alpha 参数平衡精度与简化程度。
    • ‌**xld_polyxld_cont**‌
      可通过 gen_contour_polygon_xld 反向生成轮廓,但会丢失原始细节,常用于自定义形状构建。

    总结

    xld_cont 是原始的高精度轮廓数据,适用于细节敏感场景;xld_poly 是基于 xld_cont 的简化多边形,用于提升处理效率。两者可通过 Halcon 算子灵活转换,根据任务需求选择合适的数据类型。


3,关联的主要算子

3.1, gen_parallels_xld

是 Halcon 中用于提取平行 XLD(扩展线描述)多边形的关键算子,其功能及核心要点如下:

一、功能概述

该算子通过分析输入的 XLD 多边形(EdgePolygons),检测并输出满足平行条件的 XLD 轮廓(ParallelEdges)。其核心目标是识别图像中的平行结构,适用于工业检测、物体测量等场景。


二、核心参数解析

  1. EdgePolygons
    • 输入参数,需为 XLD 多边形对象,通常通过边缘检测或其他分割算子生成。
  2. ParallelEdges
    • 输出参数,存储检测到的平行 XLD 轮廓。
  3. Len
    • 线段的最小长度阈值,仅考虑长度超过此值的多边形段,用于过滤噪声或短小边缘1。
  4. Dist
    • 平行线段间的最大允许距离。若线段在角度平分线方向上的投影距离小于此值,则判定为平行1。
  5. Alpha
    • 平行线段间的最大角度差(弧度)。角度差超过此值时,不视为平行结构1。

三、算法原理

  1. 输入处理
    接收 XLD 多边形,并基于参数过滤不符合长度要求(Len)的线段。
  2. 平行性判定
    • 距离约束‌:计算线段在角度平分线方向上的投影距离,若小于 Dist 则保留。
    • 角度约束‌:比较线段间的夹角,若小于 Alpha 则判定为平行1。
  3. 输出生成
    将满足条件的平行线对合并为 XLD 轮廓,输出至 ParallelEdges

四、典型应用场景

  • 工业零件检测‌:如提取机械零件的平行边缘,用于尺寸测量或装配验证。
  • 电子元件定位‌:识别 PCB 板上的平行引脚或线路。
  • 文本区域分割‌:提取文档图像中的平行文本行。

五、调优建议

  • Len 设置‌:过小可能引入噪声,过大可能遗漏细节,需根据目标尺寸调整。
  • Dist 与 Alpha 平衡‌:较小的 DistAlpha 可提高精度,但可能漏检;增大参数可提升召回率,但可能包含误检1。
  • 结合后处理‌:可联动 mod_parallels_xld 进一步筛选基于灰度均质性或质量因子的平行线。

3.2 ,convert_pose_type

用于转换 3D 位姿(Pose)的表示形式,涉及旋转和平移分量的数学表达切换。以下从参数列表、转换类型、数学原理及注意事项展开说明:


1. 参数列表与功能

参数类型说明
PoseIn输入输入位姿,格式由 FromType 定义(如 'Rp+T' 表示旋转矩阵+平移向量)
FromType输入输入位姿类型(支持 'Rp+T''rodriguez''abg' 等)
ToType输入目标位姿类型(如 'abg' 表示欧拉角,需配合 ToOrder 指定旋转顺序)
ToOrder输入旋转顺序(如 'ZYX' 表示绕 Z→Y→X 轴旋转)
PoseOut输出转换后的位姿

2. 核心参数解析

  1. ‌**FromTypeToType 类型**‌
    • ‌**'Rp+T'**‌:旋转矩阵(3×3)与平移向量(3×1)的组合;
    • ‌**'rodriguez'**‌:罗德里格斯向量(3×1,旋转轴归一化后乘旋转角度);
    • ‌**'abg'**‌:欧拉角(绕指定顺序的轴旋转,如 'ZYX' 对应 γ、β、α)。
  2. ‌**ToOrder 旋转顺序**‌
    • 决定欧拉角分解方式:
      • 'ZYX':绕 Z 轴旋转 γ → Y 轴旋转 β → X 轴旋转 α;
      • 'gba'(等价于 'ZYX'):按 Roll-Pitch-Yaw 顺序。
    • 万向节死锁‌:当 β ≈ ±90° 时,分解结果不唯一,需谨慎处理。
  3. 坐标系与应用视角
    位姿转换需明确视角类型(ViewOfTransform):
    • 点变换‌('point'):直接应用旋转平移矩阵(P_new = R * P_old + T)8;
    • 坐标系变换‌('coordinate_system'):需取逆矩阵描述坐标系关系(P_old = R * P_new + T)8。

3. 典型转换示例

  1. 旋转矩阵 → 欧拉角
  • 输入:旋转矩阵(Rp+T)
    create_pose(0.1, 0.2, 0.3, 0.0, 0.0, 1.5708, ‘Rp+T’, ‘ZYX’, PoseIn)
  • 转换
    convert_pose_type(PoseIn, ‘Rp+T’, ‘abg’, ‘ZYX’, PoseOut)
  • 输出:PoseOut = [0.1, 0.2, 0.3, 0.0, 0.0, 1.5708] (Tx,Ty,Tz,α,β,γ)
    1. 罗德里格斯向量 → 四元数
* 输入:罗德里格斯向量(Rodriguez)  
create_pose(0.0, 0.0, 0.0, 0.0, 0.0, 1.5708, 'rodriguez', 'ZYX', PoseIn)  
* 转换  
convert_pose_type(PoseIn, 'rodriguez', 'quaternion', '', PoseOut)  
* 输出:PoseOut = [0.0, 0.0, 0.0, 0.7071, 0.0, 0.0, 0.7071] (Tx,Ty,Tz,qx,qy,qz,qw)  

4. 注意事项

  • 单位一致性‌:平移量单位需与场景物理单位一致(如毫米或米),旋转角度默认弧度;
  • 逆矩阵处理‌:若涉及坐标系变换('coordinate_system'),需显式调用 hom_mat3d_invert 取逆;
  • 数据类型匹配‌:字符串参数需严格匹配预设值(如 'quaternion' 不可简写为 'quat')。

5. 应用场景

  1. 机器人抓取‌:将视觉检测的 'Rp+T' 位姿转换为机器人控制器支持的欧拉角格式;
  2. 多传感器标定‌:统一不同设备的位姿表示(如相机与雷达的 'rodriguez''quaternion');
  3. 运动规划‌:适配规划库(如 ROS MoveIt)的四元数输入要求。

4,程序流程。

OK
START
加载螺母图片
读取相机内参
读取BaseInCamPose
读取GripperInToolPose
标定计算出相机外参
中心点、抓取点坐标变换到世界坐标系
计算螺母中心点、抓取点、角度
生成螺母中心在世界坐标的三维矩阵
计算出螺母在相机坐标的矩阵
转化矩阵为位姿,并计算出ToolInBasePose
弹出位姿对话框
仿射、投影螺母世界坐标系中抓取点坐标到相机坐标系
在螺母图像上标记抓取点
END

5,代码

* 参考案例库:handeye_stationarycam_grasp_nut.hdev* 目的:
* 计算robot抓取螺母(不是3D点云是2D)的姿态(即ToolInRootBasePose),该数据可直接发送给Robot* 注意事项:
* 本案例是eye to hand模式即相机为固定静止dev_update_off ()
dev_close_window ()
* Directories with calibration images and data files
ImageNameStart := '3d_machine_vision/handeye/stationarycam_'
DataNameStart := 'C:/Users/Public/Documents/MVTec/HALCON-12.0/examples/solution_guide/3d_vision/handeye/stationarycam_'
read_image (Image, ImageNameStart + 'nut12_square')
dev_close_window ()
get_image_size (Image, Width, Height)
dev_open_window_fit_image (Image, 0, 0, Width, Height, WindowHandle)
dev_set_draw ('margin')
dev_set_line_width (2)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_display (Image)
disp_message (WindowHandle, 'Object to grasp', 'window', 12, 12, 'black', 'true')* ---------------1,读取相机内参read_cam_par (DataNameStart + 'final_campar.dat', CamParam)* ---------------2,读取 BaseInCamPoseread_pose (DataNameStart + 'final_pose_cam_base.dat', BaseInCamPose)
pose_to_hom_mat3d (BaseInCamPose, cam_H_base)
read_pose (DataNameStart + 'final_pose_tool_calplate.dat', CalplateInToolPose)
pose_to_hom_mat3d (CalplateInToolPose, tool_H_calplate)* ---------------3,读取 夹具在工具坐标系的姿态read_pose (DataNameStart + 'pose_tool_gripper.dat', GripperInToolPose)
pose_to_hom_mat3d (GripperInToolPose, tool_H_gripper)
stop ()*-----------------4,获取相机的外参* 相机的外参:世界坐标系在相机坐标系的位姿
* caltab_30mm.descr: Distance between mark centers : 0.00375m
CalplateFile := 'caltab_30mm.descr'
read_image (calpImage, ImageNameStart +'calib3cm_00')
* 从标定板描述文件中读取 Mark的 X,Y,Z值
caltab_points (CalplateFile, X, Y, Z)
* 
* parameter settings for find_caltab and find_marks_and_pose
SizeGauss := 3
MarkThresh := 100
MinDiamMarks := 5
StartThresh := 128
DeltaThresh := 10
MinThresh := 18
Alpha := 0.9
MinContLength := 15
MaxDiamMarks := 100
* 获取标定板区域
find_caltab (calpImage, Caltab, CalplateFile, SizeGauss, MarkThresh, MinDiamMarks)
* 获取Mark点 坐标 与 相机外参: 标定板在相机中的位姿(标定板代表世界坐标系)
find_marks_and_pose (calpImage, Caltab, CalplateFile, CamParam, StartThresh, DeltaThresh, MinThresh, Alpha, MinContLength, MaxDiamMarks, RCoord, CCoord, PoseRef)
* disp_cross (3600, RCoord, CCoord, 6, 0)
* 绘制坐标系
disp_3d_coord_system (WindowHandle, CamParam, PoseRef, 0.01)*--------------------5,获取螺母在世界坐标系中的位姿
*5.1,提取出螺母的轮廓
threshold (Image, Regions, 60, 255)fill_up (Regions, RegionFillUp)
connection (RegionFillUp, ConnectedRegions)
select_shape_std (ConnectedRegions, SelectedRegions, 'max_area', 0)
gen_contour_region_xld (SelectedRegions, Contours, 'border')
segment_contours_xld (Contours, ContoursSplit, 'lines_circles', 3, 6, 4)
*5.2,进行直线的拟合
count_obj (ContoursSplit, Number)
gen_empty_obj (lines)
for Index := 1 to Number by 1select_obj (ContoursSplit, ObjectSelected, Index)fit_line_contour_xld (ObjectSelected, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)gen_contour_polygon_xld (line,[ RowBegin,RowEnd], [ColBegin,ColEnd])concat_obj (lines, line, lines)
endfor
* 5.3,找出螺母平行的两条边
gen_polygons_xld (lines, Polygons, 'ramer', 2)
gen_parallels_xld (Polygons, Parallels, 50, 130, rad(10), 'false')
* 5.4, 获取平行线起点终点的坐标
get_parallels_xld (Parallels, Row1, Col1, Length1, Phi1, Row2, Col2, Length2, Phi2)
CornersRow := [Row1[0],Row1[1],Row2[0],Row2[1]]
CornersCol := [Col1[0],Col1[1],Col2[0],Col2[1]]
* 5.5, 将坐标转换到世界坐标系
image_points_to_world_plane (CamParam, PoseRef, CornersRow, CornersCol, 'm', CornersX_Ref, CornersY_Ref)
* 5.7, 计算在世界坐标系中螺母平行边的中心点与中点,角度
*CenterPointY_ref,CenterPointX_ref,GraspPointsX_ref,GraspPointsY_ref,GraspPhiZ_ref
CenterPointX_ref:=mean( CornersX_Ref)
CenterPointY_ref:=mean( CornersY_Ref)
* 抓取点的世界坐标
GraspPointsX_ref:=[mean([CornersX_Ref[0],CornersX_Ref[1]]),mean([CornersX_Ref[2],CornersX_Ref[3]])]
GraspPointsY_ref:=[mean([CornersY_Ref[0],CornersY_Ref[1]]),mean([CornersY_Ref[2],CornersY_Ref[3]])]
* 在世界坐标中螺母的旋转角度,atan返回的值为弧度
GraspPhiZ_ref:=atan((CornersY_Ref[1]-CornersY_Ref[0])/(CornersX_Ref[1]-CornersX_Ref[0]))
* 5.8,计算螺母在世界坐标系中的矩阵
hom_mat3d_identity (HomMat3DIdentity)
*绕Z axis 旋转
hom_mat3d_rotate (HomMat3DIdentity, GraspPhiZ_ref, 'z', 0, 0, 0, HomMat3DRotate)
* 平移
hom_mat3d_translate (HomMat3DRotate, CenterPointX_ref, CenterPointY_ref, 0, ref_H_grasp)* 5.9,计算出螺母在世界坐标系中的位姿
hom_mat3d_to_pose (ref_H_grasp, graspInRefPose)*------------------------6,计算螺母在相机坐标系中的位姿,显示螺母的抓取点
* 方法1:
pose_compose (graspInRefPose, PoseRef, graspInCamPose)* 方法2:
vector_to_pose (CornersX_Ref,CornersY_Ref, gen_tuple_const(|CornersX_Ref|,0), CornersRow, CornersCol, CamParam, 'iterative', 'error', graspInCamPose2, Quality)*螺母在世界坐标的抓取点仿射,投影出在相机坐标系中(用于在相机坐标系中展示抓取点)
pose_to_hom_mat3d (PoseRef, Cam_H_Ref)
affine_trans_point_3d (Cam_H_Ref, GraspPointsX_ref, GraspPointsY_ref, [0,0], Qx, Qy, Qz)
* 投影
project_3d_point (Qx, Qy, Qz, CamParam, Row, Column)
* 绘制夹取点
gen_cross_contour_xld (Cross, Row, Column, 12, 0)
* 显示坐标系
disp_3d_coord_system (WindowHandle, CamParam, PoseRef, 0.01)
* 显示螺母的平行边、夹取点
dev_display (Parallels)
dev_set_color ('green')
dev_set_line_width (3)
* 显示夹取点
dev_display (Cross)
disp_message (WindowHandle, 'G1', 'window', Row[0]-10, Column[0]+10, 'yellow', 'false')
disp_message (WindowHandle, 'G2', 'window', Row[1]-10, Column[1]-20, 'yellow', 'false')
dev_set_colored (12)
dev_set_line_width (1)*-----------------------7,计算最终的姿态:ToolInBasePose
pose_invert (BaseInCamPose,CamInBasePose)
pose_compose ( graspInCamPose,CamInBasePose, GripperInBasePose)
pose_invert (GripperInToolPose, ToolInGripperPose)
pose_compose (ToolInGripperPose, GripperInBasePose, ToolInBasePose)*-----------------------8,转换为发送给Robot的位姿
* Rp+T:先旋转后平移;R(p-T):先平移后旋转
* gba:以欧拉角(Euler angles)‌ 的 γ-β-α 顺序描述旋转,
* abg:以欧拉角,的 ‌α-β-γ 顺序旋转convert_pose_type (ToolInBasePose, 'Rp+T', 'abg', 'point', PoseOut)
*弹出位姿窗口
dev_inspect_ctrl (PoseOut)
disp_continue_message (WindowHandle, 'black', 'true')
stop()
*关闭位姿窗口
dev_close_inspect_ctrl (PoseOut)

效果显示:
在这里插入图片描述

6,Demo链接。

Halcon之Robot抓取螺母姿态计算Demo

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

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

相关文章

互联网大厂Java求职面试:AI集成场景下的技术挑战与架构设计

标题:互联网大厂Java求职面试:AI集成场景下的技术挑战与架构设计 第一幕:向量数据库选型与性能调优 技术总监(严肃脸): 郑薪苦,我们最近在做一个基于大语言模型的企业级AI应用,需要…

ABB电机控制和保护单元与Profibus DP主站转Modbus TCP网关快速通讯案例

ABB电机控制和保护单元与Profibus DP主站转Modbus TCP网关快速通讯案例 在现代工业自动化系统中,设备之间的互联互通至关重要。Profibus DP和Modbus TCP是两种常见的通信协议,分别应用于不同的场景。为了实现这两种协议的相互转换,Profibus …

智慧农业、智慧养殖平台—监控摄像头管理监控设计—仙盟创梦IDE

智慧养殖 监控摄像头是核心管理工具,主要通过以下方式提升养殖效率与管理水平: 环境实时监测:对养殖区域进行全天候可视化监控,及时捕捉温度、湿度、通风等环境要素变化,确保动物生存环境稳定 。例如在规模化猪场&…

YOLO 从入门到精通学习指南

一、引言 在计算机视觉领域,目标检测是一项至关重要的任务,其应用场景广泛,涵盖安防监控、自动驾驶、智能交通等众多领域。YOLO(You Only Look Once)作为目标检测领域的经典算法系列,以其高效、快速的特点受到了广泛的关注和应用。本学习指南将带领你从 YOLO 的基础概念…

Java 24新特性深度解析:从优化技巧到高手进阶指南

一、Java 24核心新特性详解 Java 24作为长期支持版本(LTS),带来了许多令人振奋的新特性,下面我们将深入探讨其中最值得关注的改进。 1. 字符串模板(String Templates)正式发布 字符串模板结束了Java字符串拼接的混乱时代&#…

《类和对象(中)》

引言: 上次我们主要学习了类的相关知识,今天我们就来学习类和对象(中),今天也会用到之前学习过的东西,可以说是前面知识的结合,较前面会难一点(打个预防针)。 一:类的默认成员函数…

为什么 AI 理解不了逻辑问题?

人类擅长“如果 A 则 B”,AI 擅长“这个像那个”。逻辑推理?对它来说是一场灾难性的认知挑战。 前言 在实际使用 AI(尤其是大型语言模型,比如 GPT、Claude、Gemini 等)时,我们常发现一个诡异的现象:它们文采斐然,甚至能讲出笑话,但一旦问点小学奥数或逻辑问题,就集体…

C# 使用SunnyUI控件 (VS 2019)

前言:建议下载源码,源码中包含了各种控件的用法案例。 下载 帮助文档: 文档预览 - Gitee.comGitee: SunnyUI: SunnyUI.NET 是基于.NET Framework 4.0、.NET8、.NET9 框架的 C# WinForm UI、开源控件库、工具类库、扩展类库、多页面开发框架。GitHub: h…

Spring Cloud: Nacos

Nacos Nacos是阿里巴巴开源的一个服务发现,配置管理和服务管理平台。只要用于分布式系统中的微服务注册,发现和配置管理,nacos是一个注册中心的组件 官方仓库:https://nacos.io/ Nacos的下载 Releases alibaba/nacos 在官网中…

Linux下的c/c++开发之操作mysql数据库

libmysqlclient-dev介绍(Linux 下的 Mysql C/C 开发包) libmysqlclient-dev 是一个开发包,在Linux环境下为使用 MySQL C API 进行开发的c/c程序员提供头文件(如 mysql.h)和静态库/动态库的链接信息(如 lib…

Java EE(Spring+Spring MVC+MyBatis)从入门到精通企业级应用开发教程——1初识MyBatis框架

1、MyBatis工作原理 MyBatis操作数据库流程分为8个步骤,具体介绍如下: (1)MyBatis读取核心配置文件mybatis-config.xml mybatis-config.xml核心配置文件主要配置了MyBatis的运行环境等信息。 (2)加载映射…

【许可证】Open Source Licenses

长期更新 扩展:shield.io装饰 开源许可证(Open Source Licenses)有很多种,每种都有不同的授权和限制,适用于不同目的。 默认的ISC🟰MIT License是否可商用是否要求开源衍生项目是否必须署名是否有专利授权…

ZooKeeper工作机制与应用场景

目录 1.1、概述1.2、选举机制1.2.1、选举触发条件1.2.2、选举规则1.2.3、选举过程详解 1.3、数据同步机制1.3.1、正常同步1.3.2、宕机同步 1.4、客户端常用命令1.5、应用场景1.5.1、配置管理1.5.2、命令服务1.5.3、分布式锁服务1.5.4、集群管理1.5.5、分布式ID1.5.6、分布式协调…

前端面经-VUE3篇(四)--pinia篇-基本使用、store、state、getter、action、插件

一、基本使用 1、什么是 Pinia? Pinia 是 Vue.js 的官方状态管理库,是 Vuex 的“升级版”。它专为 Vue 3 和 Composition API 设计,用于管理多个组件之间共享的数据(也叫“全局状态”)。 2、为什么需要状态管理库&a…

数据结构之图的遍历

图的遍历 图的遍历目的是访问图的每一个顶点恰好一次,,同时访问图中每条边恰好一 次。 对于无向图,常见的遍历方式有深度优先遍历(Depth-First Search, DFS) 和广度优先遍历(Breadth-First Search, BFS)。…

Ubuntu 第11章 网络管理_常用的网络配置命令

为了管理网络,Linux提供了许多非常有用的网络管理命令。利用这些命令,一方面可以有效地管理网络,另一方面出现网络故障时,可以快速进行诊断。本节将对Ubuntu提供的网络管理命令进行介绍。 11.2.1 ifconfig命令 关于ifconfig命令&…

Qt解决自定义窗口样式不生效问题

方法一: this->setAttribute(Qt::WA_StyledBackground, true); 方法二: 将类继承QWidget 改成继承 QFrame class MyWidget : public QFrame {} 方法三:重新实现QWidget的paintEvent函数时,使用QStylePainter绘制。 void p…

HNUST湖南科技大学-软件测试期中复习考点(保命版)

使用说明:本复习考点仅用于及格保命。软件测试和其他专业课不太一样,记忆的太多了,只能说考试的时候,想到啥就写啥,多写一点!多写一点!多写一点!(重要事情说三遍&#xf…

ES6 知识点整理

一、变量声明:var、let、const 的区别 作用域 var:函数作用域(函数内有效)。let/const:块级作用域({} 内有效,如 if、for)。 变量提升 var 会提升变量到作用域顶部(值为…

分布式爬虫去重:Python + Redis实现高效URL去重

1. 引言 在互联网数据采集(爬虫)过程中,URL去重是一个关键问题。如果不对URL进行去重,爬虫可能会重复抓取相同页面,导致资源浪费、数据冗余,甚至触发目标网站的反爬机制。 对于单机爬虫,可以使…