当前位置: 首页 > news >正文

无人机视觉:连接像素与现实世界 —— 像素与GPS坐标双向转换指南

在无人机航拍应用中,一个核心的需求是将图像上的某个点与现实世界中的地理位置精确对应起来。无论是目标跟踪、地图测绘还是农情监测,理解图像像素与其对应的经纬度(GPS坐标)之间的关系至关重要。本文将详细介绍如何实现单个像素坐标到GPS坐标的双向转换,并提供基于Python的实现思路。
在这里插入图片描述

核心问题

  1. 像素坐标 -> GPS坐标: 已知图像上一个点的像素坐标 (u, v),以及拍摄时无人机的状态(位置、姿态、相机参数),如何计算该像素点对应的地面GPS经纬度 (Lon, Lat)?
  2. GPS坐标 -> 像素坐标: 已知地面上一个目标的GPS经纬度 (Lon, Lat),以及拍摄时无人机的状态,如何反算出该目标出现在图像中的像素坐标 (u, v)?

所需信息(前提条件)

  • 图像参数: 图像宽度 img_width (像素),图像高度 img_height (像素)。
  • 相机内参:
    • 传感器尺寸:宽度 sensor_width (毫米),高度 sensor_height (毫米)。
    • 相机焦距 focal_length (毫米)。
  • 无人机状态信息:
    • 相机位置:经度 camera_lon (度),纬度 camera_lat (度),相对于海平面的高度或起飞点的高度 flight_height (米)。
    • 相机姿态:偏航角 yaw_angle (度),俯仰角 pitch_angle (度),滚转角 roll_angle (度)。

坐标系约定(非常重要!)

为了保证计算的正确性,我们必须明确并统一坐标系的定义。以下是一种常见的约定,你的具体实现可能需要根据实际情况调整:

  1. 图像坐标系 (u, v)
    • 原点:图像左上角。
    • u轴:水平向右。
    • v轴:垂直向下。
    • 单位:像素。
  2. 相机坐标系 (Xc, Yc, Zc)
    • 原点:相机光心。
    • Xc轴:指向相机传感器的右方。
    • Yc轴:指向相机传感器的下方(与图像v轴同向)。
    • Zc轴:指向相机前方(光轴方向)。
    • 单位:米。
    • 注意:也有约定Yc轴向上的,这会影响内参矩阵 fy 和后续计算中的符号。本文档和示例代码采用Yc向下的约定。
  3. 世界/导航坐标系 (Xw, Yw, Zw)
    • 通常使用 NED (North-East-Down) 坐标系。
    • 原点:无人机(相机)位置在地面上的投影点。
    • Xw轴:指向正北 (North)。
    • Yw轴:指向正东 (East)。
    • Zw轴:指向地心 (Down)。
    • 单位:米。
  4. 地理坐标系 (Lat, Lon)
    • 使用WGS84标准。
    • 单位:度。

第一部分:像素坐标 (u, v) -> GPS坐标 (Lon, Lat)

这个过程模拟了光线从地面点穿过相机光心最终成像在传感器像素上的逆过程。
步骤:

  1. 计算相机内参矩阵 (K)
  • 将焦距从毫米转换为米:focal_m = focal_length / 1000。

  • 将传感器尺寸从毫米转换为米:

    • sensor_width_m = sensor_width / 1000,
    • sensor_height_m = sensor_height / 1000。
  • 计算以像素为单位的焦距:

    • fx = focal_m / sensor_width_m * img_width
    • fy = focal_m / sensor_height_m * img_height
  • 计算主点(通常是图像中心):

    • cx = img_width / 2
    • cy = img_height / 2
  • 构建内参矩阵 K:

    K = np.array([[fx, 0, cx],[0, fy, cy],[0, 0,  1]
    ])
    
  • 计算 K 的逆矩阵 K_inv = np.linalg.inv(K)。

  1. 像素坐标转相机坐标系方向向量
  • 将像素坐标 (u, v) 转换为齐次坐标 [u, v, 1]。
  • 使用内参矩阵的逆 K_inv 将像素坐标转换到相机坐标系下的一个方向向量:
    • camera_coords_homogeneous = K_inv @ np.array([u, v, 1])
  • 这个向量表示从相机光心指向该像素方向的三维射线。为了后续计算,我们通常将其归一化或设定一个深度。由于我们采用 Zc 轴向前的约定,可以将 Zc 分量设为 1(或者 -1,取决于后续旋转定义,这里设为 1 方便理解):
    • Xc = camera_coords_homogeneous[0]
    • Yc = camera_coords_homogeneous[1]
    • Zc = 1.0 # 方向向量,Z分量设为1
  1. 计算旋转矩阵 ( R ):

    • 将无人机姿态角(Yaw, Pitch, Roll)从度转换为弧度。

    • 根据 世界坐标系 (NED)相机坐标系 的转换关系,构建旋转矩阵。这通常是一个组合旋转,例如按 ZYX 的顺序(先绕Z轴偏航,再绕新的Y轴俯仰,最后绕新的X轴滚转 - 这是内旋顺序;或者按 ZYX 外旋,先滚转,再俯仰,最后偏航)。一个常见的 NED 到 相机 (X右Y下Z前) 的旋转矩阵构建方式(外旋 ZYX,对应 Roll, Pitch, Yaw):

      # 角度转弧度
      yaw_rad, pitch_rad, roll_rad = np.radians(yaw_angle), np.radians(pitch_angle), np.radians(roll_angle)# 基本旋转矩阵
      Rx = np.array([[1, 0, 0],[0, np.cos(roll_rad), -np.sin(roll_rad)],[0, np.sin(roll_rad), np.cos(roll_rad)]]) # Roll 绕 X (North)Ry = np.array([[np.cos(pitch_rad), 0, np.sin(pitch_rad)],[0, 1, 0],[-np.sin(pitch_rad), 0, np.cos(pitch_rad)]]) # Pitch 绕 Y (East)Rz = np.array([[np.cos(yaw_rad), -np.sin(yaw_rad), 0],[np.sin(yaw_rad), np.cos(yaw_rad), 0],[0, 0, 1]]) # Yaw 绕 Z (Down)# 从 NED 到 机体坐标系的旋转矩阵 (注意顺序和内外旋定义)
      # 如果姿态角是相对于NED的,常见的组合是 R = Rz @ Ry @ Rx
      # 这个 R 表示将 NED 坐标系下的向量转换到相机坐标系下
      # 我们需要的是从相机坐标系转到NED,所以用 R 的转置 R.T
      R_cam_to_ned = (Rz @ Ry @ Rx).T
      

      - 注意:旋转矩阵的构建方式和顺序严格依赖于姿态角的定义(是相对于NED还是机体?旋转顺序是怎样的?)。上述是一个示例,你需要根据你的无人机数据定义来确定正确的 R。

  2. 将相机坐标系方向向量旋转到世界坐标系 (NED)

    • world_direction = R_cam_to_ned @ np.array([Xc, Yc, Zc])
  3. 计算射线与地面的交点

    • 假设地面是平坦的,位于无人机下方 flight_height 米处。
    • 在NED坐标系中,地面点的 Zw 坐标为 flight_height。
    • 我们需要找到缩放因子 scale,使得 scale * world_direction 的 Z 分量等于 flight_height。
    • scale = flight_height / world_direction[2] (Zw 分量)
    • 检查:如果 world_direction[2] <= 0,表示射线指向天空或水平,无法与下方地面相交,应返回无效值。
    • 计算地面点在NED坐标系下的坐标(相对于无人机投影点):
      • ground_ned_x = scale * world_direction[0] (North)
      • ground_ned_y = scale * world_direction[1] (East)
  4. 将NED坐标偏移转换为经纬度偏移

    • 计算相机所在纬度的地球半径 R_earth (可以使用 WGS84 模型精确计算,或用平均半径近似)。
    • 纬度变化 delta_lat = (ground_ned_x / R_earth) * (180 / np.pi) (向北为正)
    • 经度变化 delta_lon = (ground_ned_y / (R_earth * np.cos(np.radians(camera_lat)))) * (180 / np.pi) (向东为正)
  5. 计算最终GPS坐标

    • target_lat = camera_lat + delta_lat
    • target_lon = camera_lon + delta_lon

第二部分:GPS坐标 (Lon, Lat) -> 像素坐标 (u, v)

这个过程模拟光线从目标发出,经过空间变换,最终投影到相机传感器的过程。
步骤:

  1. 计算目标点相对于无人机投影点的NED坐标

    • 计算目标点与相机之间的经纬度差值:
      • delta_lat_deg = target_lat - camera_lat
      • delta_lon_deg = target_lon - camera_lon
    • 计算相机所在纬度的地球半径 R_earth。
    • 将经纬度差值转换为NED坐标系下的米:
      • ground_ned_x = delta_lat_deg * (np.pi / 180) * R_earth (North)
      • ground_ned_y = delta_lon_deg * (np.pi / 180) * (R_earth * np.cos(np.radians(camera_lat))) (East)
    • 目标点在NED坐标系下的向量为 [ground_ned_x, ground_ned_y, flight_height] (因为 Zw 指向下方)。
  2. 计算从世界坐标系 (NED) 到相机坐标系的旋转矩阵 (R_ned_to_cam):

    • 这通常是第一部分中 R_cam_to_ned 的逆矩阵,也就是它的转置 R_ned_to_cam = R_cam_to_ned.T。使用与第一部分相同的姿态角和旋转顺序构建。
    • R_ned_to_cam = Rz @ Ry @ Rx (假设使用 ZYX 外旋)
  3. 将目标点的NED坐标转换到相机坐标系:

    • target_cam_coords = R_ned_to_cam @ np.array([ground_ned_x, ground_ned_y, flight_height])
    • 得到目标点在相机坐标系下的 (Xc, Yc, Zc)。
  4. 计算相机内参矩阵 (K):

    • 同第一部分的步骤1。
    • 注意符号问题: 如果你的相机坐标系定义是 Yc 向上,而图像坐标系 v 向下,则 K 矩阵中的 fy 可能需要取负值,或者在投影计算时调整。如果像我们约定的 Yc 向下,则 K 不需要修改。
      # 假设 K 与第一部分相同 (Yc向下)
      K = np.array([[fx, 0, cx],[0, fy, cy],[0, 0,  1]
      ])
      
  5. 将相机坐标系下的点投影到像素坐标系:

    • 应用内参矩阵 K:pixel_homogeneous = K @ target_cam_coords
    • 进行透视除法(齐次坐标转普通坐标):
      • u_raw = pixel_homogeneous[0] / pixel_homogeneous[2]
      • v_raw = pixel_homogeneous[1] / pixel_homogeneous[2]
  6. 得到最终像素坐标:

    • u = int(round(u_raw))
    • v = int(round(v_raw))
    • 检查:计算出的 (u, v) 是否在图像边界内 (0 <= u < img_width, 0 <= v < img_height)?如果不在,说明该GPS点不在当前图像视野内。

Python 代码示例

下面是实现像素坐标与GPS坐标双向转换的完整Python代码:

import numpy as npclass UAVGeolocationCalculator:def __init__(self, img_width, img_height, sensor_width, sensor_height):"""初始化计算器。Args:img_width: 图像宽度(单位:像素)。img_height: 图像高度(单位:像素)。sensor_width: 传感器的宽度(单位:毫米)。sensor_height: 传感器的高度(单位:毫米)。"""self.sensor_width = sensor_width / 1000  # 转换为米self.sensor_height = sensor_height / 1000  # 转换为米self.img_width = img_widthself.img_height = img_heightdef _calculate_earth_radius_wgs84(self, latitude):"""计算给定纬度的地球半径"""a = 6378137.0  # WGS84 赤道半径f = 1 / 298.257223563  # WGS84 扁率b = a * (1 - f)  # WGS84 极半径lat_rad = np.radians(latitude)R = np.sqrt((a**2 * np.cos(lat_rad))**2 + (b**2 * np.sin(lat_rad))**2) / \np.sqrt((a * np.cos(lat_rad))**2 + (b * np.sin(lat_rad))**2)return Rdef _calculate_internal_parameter_matrix(self, focal_length, apply_coordinate_transform=False):"""计算相机的内参矩阵。Args:focal_length (float): 焦距,单位为米。apply_coordinate_transform (bool): 是否应用坐标系转换。当为True时,使用带负号的形式。Returns:np.ndarray: 内参矩阵。"""# 焦距转换为像素单位fx = focal_length / self.sensor_width * self.img_widthfy = focal_length / self.sensor_height * self.img_heightcx = self.img_width / 2cy = self.img_height / 2if apply_coordinate_transform:  # 使用坐标系转换来处理相机和图像坐标系差异K = np.array([[-fx, 0, cx],[0, -fy, cy],[0, 0, 1]])else:  # 不使用坐标系转换K = np.array([[fx, 0, cx],[0, fy, cy],[0, 0, 1]])return Kdef _calculate_rotation_matrix(self, yaw, pitch, roll):"""计算旋转矩阵。Args:yaw: 偏航角pitch: 俯仰角roll: 翻滚角Returns:R: 旋转矩阵"""yaw_rad, pitch_rad, roll_rad = np.radians(yaw), np.radians(pitch), np.radians(roll)# 基本旋转矩阵Rz = np.array([[np.cos(yaw_rad), -np.sin(yaw_rad), 0],[np.sin(yaw_rad), np.cos(yaw_rad), 0],[0, 0, 1]])Ry = np.array([[np.cos(pitch_rad), 0, np.sin(pitch_rad)],[0, 1, 0],[-np.sin(pitch_rad), 0, np.cos(pitch_rad)]])Rx = np.array([[1, 0, 0],[0, np.cos(roll_rad), -np.sin(roll_rad)],[0, np.sin(roll_rad), np.cos(roll_rad)]])# 注意旋转顺序,这里采用ZYX外旋R = Rz @ Ry @ Rxreturn Rdef pixel_to_gps(self, pixel_x, pixel_y, camera_lat, camera_lon, flight_height, focal_length,yaw_angle=0.0, pitch_angle=0.0, roll_angle=0.0):"""根据无人机相机的参数和位置,计算图像指定像素点的经纬度。Args:pixel_x (int): 目标像素点的横坐标。pixel_y (int): 目标像素点的纵坐标。camera_lat (float): 相机所在的纬度(度)。camera_lon (float): 相机所在的经度(度)。flight_height (float): 飞行高度(米)。focal_length (float): 相机焦距(毫米)。yaw_angle (float): 相机的偏航角(度),默认值为0.0。pitch_angle (float): 相机的俯仰角(度),默认值为0.0。roll_angle (float): 相机的翻滚角(度),默认值为0.0。Returns:tuple: 包含两个元素(lon, lat)的元组,分别表示指定像素点的经度和纬度。"""# 像素点到相机中心的三维坐标转换K_inv = np.linalg.inv(self._calculate_internal_parameter_matrix(focal_length / 1000))camera_coords = K_inv @ np.array([pixel_x, pixel_y, 1])# 设置射线方向,通常将Z方向设为向前(1)或向后(-1)# 具体取值依赖于你后续的计算约定px_x, px_y, px_z = camera_coords[0], camera_coords[1], -1  # 计算旋转矩阵R = self._calculate_rotation_matrix(yaw_angle, pitch_angle, roll_angle)# 应用旋转矩阵,从相机坐标系转到世界坐标系(NED)R_cam_to_ned = R.T  # 从相机到NED需要转置rotated_coords = R_cam_to_ned @ np.array([px_x, px_y, px_z])# 检查是否指向天空if rotated_coords[2] >= 0:  # Z轴向下,小于0才能与地面相交return np.nan, np.nan# 计算与地面的交点scale = flight_height / -rotated_coords[2]  # 使用Z坐标计算缩放比例ground_x = rotated_coords[0] * scale  # Northground_y = rotated_coords[1] * scale  # East# 地球半径R_earth = self._calculate_earth_radius_wgs84(camera_lat)# 计算经纬度偏移delta_lat = (ground_x / R_earth) * (180 / np.pi)delta_lon = (ground_y / (R_earth * np.cos(np.radians(camera_lat)))) * (180 / np.pi)# 计算最终经纬度lat = camera_lat + delta_latlon = camera_lon + delta_lonreturn lon, latdef gps_to_pixel(self, target_lat, target_lon, camera_lat, camera_lon, flight_height, focal_length,yaw_angle=0.0, pitch_angle=0.0, roll_angle=0.0):"""根据无人机相机的参数和位置,计算指定经纬度在图像中的坐标。Args:target_lat (float): 目标点的纬度(度)。target_lon (float): 目标点的经度(度)。camera_lat (float): 相机所在的纬度(度)。camera_lon (float): 相机所在的经度(度)。flight_height (float): 飞行高度(米)。focal_length (float): 相机焦距(毫米)。yaw_angle (float): 相机的偏航角(度),默认值为0.0。pitch_angle (float): 相机的俯仰角(度),默认值为0.0。roll_angle (float): 相机的翻滚角(度),默认值为0.0。Returns:tuple: 包含两个元素(x, y)的元组,分别表示指定经纬度点在图像上的像素坐标。"""# 地球半径R_earth = self._calculate_earth_radius_wgs84(camera_lat)# 计算经纬度差值delta_lat = target_lat - camera_latdelta_lon = target_lon - camera_lon# 将经纬度差值转换为地面坐标系中的米ground_x = delta_lat * (R_earth) * (np.pi / 180)  # Northground_y = delta_lon * (R_earth * np.cos(np.radians(camera_lat))) * (np.pi / 180)  # East# 计算旋转矩阵R = self._calculate_rotation_matrix(yaw_angle, pitch_angle, roll_angle)# 将地面坐标转换为相机坐标系中的坐标# 注意Z坐标是flight_height,因为NED坐标系Z轴向下camera_coords = R @ np.array([ground_x, ground_y, -flight_height])# 使用内参矩阵计算像素坐标# 这里使用apply_coordinate_transform=True来处理坐标系差异K = self._calculate_internal_parameter_matrix(focal_length / 1000, apply_coordinate_transform=True)# 检查点是否在相机前方if camera_coords[2] <= 0:return None, None# 投影到像素坐标系px = K @ camera_coordspx_x = px[0] / px[2]px_y = px[1] / px[2]# 检查是否在图像内if 0 <= px_x < self.img_width and 0 <= px_y < self.img_height:return int(round(px_x)), int(round(px_y))else:return None, None

使用示例

if __name__ == '__main__':# 创建计算器实例img_width = 1920img_height = 1080sensor_width = 7.53   # 传感器宽度(毫米)sensor_height = 5.64  # 传感器高度(毫米)calculator = UAVGeolocationCalculator(img_width, img_height, sensor_width, sensor_height)# 设置无人机和相机参数focal_length = 12.0   # 相机焦距(毫米)camera_lon = 116.3972   # 拍摄位置经度camera_lat = 39.9075    # 拍摄位置纬度flight_height = 100.0   # 飞行高度(米)yaw_angle = 45.0        # 相机偏航角(度)pitch_angle = -30.0     # 相机俯仰角(度)roll_angle = 0.0        # 相机翻滚角(度)# 测试像素坐标到GPS坐标的转换pixel_x, pixel_y = 960, 540  # 图像中心点lon, lat = calculator.pixel_to_gps(pixel_x, pixel_y, camera_lat, camera_lon, flight_height, focal_length, yaw_angle, pitch_angle, roll_angle)print(f"像素坐标 ({pixel_x}, {pixel_y}) 对应的GPS坐标为: 经度={lon:.7f}, 纬度={lat:.7f}")# 测试GPS坐标到像素坐标的转换pixel_x_back, pixel_y_back = calculator.gps_to_pixel(lat, lon, camera_lat, camera_lon, flight_height,focal_length, yaw_angle, pitch_angle, roll_angle)print(f"GPS坐标 (经度={lon:.7f}, 纬度={lat:.7f}) 对应的像素坐标为: ({pixel_x_back}, {pixel_y_back})")

重要考虑与局限性

  1. 坐标系一致性: 这是最容易出错的地方。务必确保你使用的无人机姿态角(Yaw, Pitch, Roll)的定义、旋转顺序与代码中构建旋转矩阵的方式完全匹配。传感器输出的坐标系、相机安装的相对姿态都需要考虑。

  2. 传感器精度: 转换结果的精度直接受限于GPS定位精度、IMU姿态测量精度以及相机内参标定的准确性。

  3. 地球模型: 上述计算使用了WGS84椭球模型的一个半径近似值。对于高精度要求,应使用更精确的地理坐标转换库(如 pyproj)。

  4. 平坦地面假设: 计算假设目标点所在的地面是平坦的,并且位于无人机下方 flight_height 处。对于地形起伏较大的区域,需要引入数字高程模型 (DEM) 数据来获取目标点的实际海拔,从而修正 flight_height 或直接计算射线与地形的交点。

  5. 镜头畸变: 未考虑相机镜头的畸变。对于广角镜头或精度要求高的场景,需要先对像素坐标进行去畸变处理,或在投影模型中加入畸变参数。

结论

实现像素坐标与GPS坐标的准确双向转换是无人机数据处理中的一项基本而关键的技术。理解背后的坐标系变换、相机模型和旋转矩阵是核心。通过仔细处理坐标系约定和利用准确的传感器数据,我们可以有效地将无人机捕捉到的图像信息与现实世界的地理空间联系起来,为各种高级应用提供基础支持。

相关文章:

无人机视觉:连接像素与现实世界 —— 像素与GPS坐标双向转换指南

在无人机航拍应用中&#xff0c;一个核心的需求是将图像上的某个点与现实世界中的地理位置精确对应起来。无论是目标跟踪、地图测绘还是农情监测&#xff0c;理解图像像素与其对应的经纬度&#xff08;GPS坐标&#xff09;之间的关系至关重要。本文将详细介绍如何实现单个像素坐…...

php study 网站出现404 - Page Not Found 未找到

最近在用php study搭建本地网站时&#xff0c;出现了404 - Page Not Found 未找到的情况&#xff0c;解决方式如下&#xff1a; 第一种&#xff1a;在wp 后台固定链接设置中修改链接形式 第二种:没有安装伪静态! 小皮面板中 设置--配置文件--编辑你所搭建的网站 在红色框框处…...

互联网大厂Java求职面试:核心技术点深度解析

互联网大厂Java求职面试&#xff1a;核心技术点深度解析 在互联网大厂的Java岗位面试中&#xff0c;技术总监级别的面试官通常会从实际业务场景出发&#xff0c;层层深入地考察候选人的技术能力。本文通过一个严肃专业的技术总监与搞笑但有技术潜力的程序员郑薪苦之间的互动对…...

【Java idea配置】

IntelliJ IDEA创建类时自动生成注释 /** * program: ${PROJECT_NAME} * * since: jdk1.8 * * description: ${description} * * author: ${USER} * * create: ${YEAR}-${MONTH}-${DAY} ${HOUR}:${MINUTE} **/自动导入和自动移除无用导入 idea彩色日志不生效 调试日志输出 在…...

[GESP202503 四级] 二阶矩阵c++

题目描述 小 A 有一个 n 行 m 列的矩阵 A。 小 A 认为一个 22 的矩阵 D 是好的&#xff0c;当且仅当 。其中 表示矩阵 D 的第 i 行第 j 列的元素。 小 A 想知道 A 中有多少个好的子矩阵。 输入 第一行&#xff0c;两个正整数 n,m。 接下来 n 行&#xff0c;每行 m 个整数…...

PyQt5基本介绍

PyQt5是基于Digia公司强大图形框架Qt5的python接口&#xff0c;由一组python模块构成。是一个用于创建桌面应用程序的Python库&#xff0c;它是Qt图形用户界面工具包的Python绑定。 Qt是一个跨平台的C库&#xff0c;提供了一套丰富的工具和功能&#xff0c;用于开发图形用户界…...

Spring AI 实战:第十章、Spring AI RAG之博学多才

引言:从“博闻强记”到“博学多才” 在人工智能的发展历程中,大语言模型(LLM)已经展现了惊人的“博闻强记”能力——它们能写诗、编码、解答常识问题,甚至模拟人类对话。然而,当面对专业领域知识或实时更新的信息时,这些模型往往会暴露其局限性:要么“一本正经地胡说八…...

Runnable 组件生命周期监听器与使用场景

Runnable 生命周期监听器 1.1 监听机制演进 在 LangChain 框架中&#xff0c;Runnable 组件提供两种监控方案&#xff1a; ​​传统模式​​&#xff1a;通过 config callbacks 参数传递回调配置​​增强模式​​&#xff1a;使用 with_listeners() 方法实现生命周期订阅 …...

五、shell脚本--函数与脚本结构:搭积木,让脚本更有条理

随着我们的脚本越来越长、越来越复杂&#xff0c;直接把所有命令堆在一起会变得难以阅读和维护。这时候&#xff0c;函数 (Function) 就派上大用场了&#xff01; 函数就像一个可以重复使用的代码块&#xff0c;你可以给它起个名字&#xff0c;然后在脚本的任何地方通过名字来…...

单调栈与单调队列(c艹)、可视化Qt?

单调栈和单调队列的区别在于 ChatGLM 单调栈和单调队列都是数据结构中用于处理序列问题的工具&#xff0c;它们在处理问题时具有不同的特性和应用场景。以下是单调栈和单调队列的主要区别&#xff1a; 定义&#xff1a; 单调栈&#xff1a;是一种特殊的栈&#xff0c;其中的元…...

哈夫曼树和哈夫曼编码

哈夫曼编码一般用来对字符串进行编码格式的表示。其中要克服的最大问题&#xff0c;莫过于就是一串由0或者1组成的编码&#xff0c;你无法区分哪些01组成的编码部分是属于哪些字符的&#xff0c;因此哈夫曼编码的出现解决了这个问题。 在介绍哈夫曼编码之前&#xff0c;先介绍…...

基于 AI 的人像修复与编辑技术:CompleteMe 系统的研究与应用

概述 加利福尼亚大学默塞德分校与 Adobe 的新合作在人像补全领域取得了突破性进展——人像补全是一项备受关注的任务&#xff0c;旨在“揭示”人像中被遮挡或隐藏的部分&#xff0c;可用于虚拟试穿、动画制作和照片编辑等场景。 除了修复损坏的图像或根据用户意愿更改图像外&a…...

spring 使用FactoryBean注入bean

spring 使用FactoryBean注入bean 1、介绍 ​ 通常是ApplicationContext&#xff0c;就是IOC容器&#xff0c;ApplicationContext是BeanFactory的实现类&#xff0c;是spring最核心的接口。用getBean来加载bean。BeanFactory相当于是IOC的基础类。而FactoryBean是另一个东西&a…...

AI 编程日报 · 2025 年 5 月 04 日|GitHub Copilot Agent 模式发布,Ultralytics 优化训练效率

1、OpenAI 确认 GPT-4o“谄媚”个性更新已完全回滚 OpenAI 官方已确认&#xff0c;先前推送的一项旨在改进 GPT-4o 模型个性的更新已被完全撤销。该更新最初目标是提升模型的智能与个性&#xff0c;使其交互更直观有效&#xff0c;但实际效果却导致模型表现出过度“谄媚”和“…...

C++ STL简介:构建高效程序的基石

0. 引言 在现代软件开发领域&#xff0c;C语言凭借其强大的性能和灵活性占据着重要地位。而C标准模板库&#xff08;Standard Template Library&#xff0c;简称STL&#xff09;作为C标准库的核心组件&#xff0c;更是开发者手中不可或缺的利器。它犹如一座知识宝库&#xff0…...

大模型(LLMs)RAG 版面分析——文本分块面

大模型&#xff08;LLMs&#xff09;RAG 版面分析——文本分块面 一、为什么需要对文本分块&#xff1f; 二、能不能介绍一下常见的文本分块方法&#xff1f; 2.1 一般的文本分块方法 2.2 正则拆分的文本分块方法 2.3 Spacy Text Splitter 方法 2.4 基于 langchain 的 Cha…...

系统思考:核心价值与竞争力

最近&#xff0c;设计师的小伙伴跟我提到&#xff0c;行业内竞争越来越激烈&#xff0c;大家都开始拼命降价。但从系统思考的角度来看&#xff0c;我想说一句话&#xff1a;“人多的地方&#xff0c;不要去。” 为什么这么说&#xff1f;在竞争愈发激烈的环境中&#xff0c;我…...

【RocketMQ Broker 相关源码】- broker 启动源码(2)

文章目录 1. 前言2. 创建 DefaultMessageStore3. DefaultMessageStore#load3.1 CommitLog#load3.2 loadConsumeQueue 加载 ConsumeQueue 文件3.3 创建 StoreCheckpoint3.4 indexService.load 加载 IndexFile 文件3.5 recover 文件恢复3.6 延时消息服务加载 4. registerProcesso…...

mysql中int(1) 和 int(10) 有什么区别?

困惑 最近遇到个问题&#xff0c;有个表的要加个user_id字段&#xff0c;user_id字段可能很大&#xff0c;于是我提mysql工单​​alter table xxx ADD user_id int(1)​​。领导看到我的sql工单&#xff0c;于是说&#xff1a;这int(1)怕是不够用吧&#xff0c;接下来是一通解…...

jetson orin nano super AI模型部署之路(八)tensorrt C++ api介绍

我们基于tensorrt-cpp-api这个仓库介绍。这个仓库的代码是一个非常不错的tensorrt的cpp api实现&#xff0c;可基于此开发自己的项目。 我们从src/main.cpp开始按顺序说明。 一、首先是声明我们创建tensorrt model的参数。 // Specify our GPU inference configuration optio…...

渗透测试中扫描成熟CMS目录的意义与技术实践

在渗透测试领域&#xff0c;面对一个成熟且“看似安全”的CMS&#xff08;如WordPress、Drupal&#xff09;&#xff0c;许多初级测试者常陷入误区&#xff1a;认为核心代码经过严格审计的CMS无需深入排查。然而&#xff0c;目录扫描&#xff08;Directory Bruteforcing&#x…...

数字信号处理学习笔记--Chapter 1 离散时间信号与系统

1 离散时间信号与系统 包含以下内容&#xff1a; &#xff08;1&#xff09;离散时间信号--序列 &#xff08;2&#xff09;离散时间系统 &#xff08;3&#xff09;常系数线性差分方程 &#xff08;4&#xff09;连续时间信号的抽样 2 离散时间信号--序列 为了便于计算机对信号…...

LeetCode 热题 100 994. 腐烂的橘子

LeetCode 热题 100 | 994. 腐烂的橘子 大家好&#xff0c;今天我们来解决一道经典的算法题——腐烂的橘子。这道题在LeetCode上被标记为中等难度&#xff0c;要求我们计算网格中所有新鲜橘子腐烂所需的最小分钟数&#xff0c;或者返回不可能的情况。下面我将详细讲解解题思路&…...

软考-软件设计师中级备考 11、计算机网络

1、计算机网络的分类 按分布范围分类 局域网&#xff08;LAN&#xff09;&#xff1a;覆盖范围通常在几百米到几千米以内&#xff0c;一般用于连接一个建筑物内或一个园区内的计算机设备&#xff0c;如学校的校园网、企业的办公楼网络等。其特点是传输速率高、延迟低、误码率低…...

NHANES指标推荐:LC9

文章题目&#xff1a;Association between lifes crucial 9 and kidney stones: a population-based study DOI&#xff1a;10.3389/fmed.2025.1558628 中文标题&#xff1a;生命的关键 9 与肾结石之间的关联&#xff1a;一项基于人群的研究 发表杂志&#xff1a;Front Med 影响…...

使用 Azure DevSecOps 和 AIOps 构建可扩展且安全的多区域金融科技 SaaS 平台

引言 金融科技行业有一个显著特点&#xff1a;客户期望能够随时随地即时访问其财务数据&#xff0c;并且对宕机零容忍。即使是短暂的中断也会损害用户的信心和忠诚度。与此同时&#xff0c;对数据泄露的担忧已将安全提升到整个行业的首要地位。 在本文中&#xff0c;我们将探…...

原子单位制换算表

速度 0.12.1880.24.3760.36.5640.48.7520.510.940.613.1280.715.3160.817.5040.919.692121.881.532.82243.762.554.7...

【C++重载操作符与转换】下标操作符

目录 一、下标操作符重载基础 1.1 什么是下标操作符重载 1.2 默认行为与需求 1.3 基本语法 二、下标操作符的核心实现策略 2.1 基础实现&#xff1a;一维数组模拟 2.2 多维数组实现&#xff1a;矩阵类示例 三、下标操作符的高级用法 3.1 自定义索引类型&#xff1a;字…...

文章记单词 | 第62篇(六级)

一&#xff0c;单词释义 noon [nuːn] n. 中午&#xff0c;正午clothes [kləʊz] n. 衣服&#xff0c;衣物reward [rɪˈwɔːd] n. 报酬&#xff0c;奖赏&#xff1b;vt. 奖励&#xff0c;奖赏newly [ˈnjuːli] adv. 最近&#xff0c;新近&#xff1b;以新的方式premier [ˈ…...

《CUDA:解构GPU计算的暴力美学与工程哲学》

《CUDA:解构GPU计算的暴力美学与工程哲学》 ​ CUDA 的诞生,宛如在 GPU 发展史上划下了一道分水岭。它不仅赋予了 GPU 走出图形处理的 “舒适区”,投身通用计算的 “新战场” 的能力,更是一场对计算资源分配与利用逻辑的彻底重构。在这场技术革命中,CUDA 以它犀利的架构设…...

Linux ACPI - ACPI系统描述表架构(2)

ACPI系统描述表架构 1.概要 ACPI defines a hardware register interface that an ACPI-compatible OS uses to control core power management features of a machine, as described in ACPI Hardware Specification ACPI also provides an abstract interface for controlli…...

实时在线状态

以下是一个完整的 OnlineUsers 类实现&#xff0c;包含线程安全的在线用户管理功能&#xff1a; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors;/*** 在线用户管理器&#xff08;线程安全&#xff09;* 功能&#…...

《算法导论(第4版)》阅读笔记:p6-p6

《算法导论(第4版)》学习第 4 天&#xff0c;p6-p6 总结&#xff0c;总计 1 页。 一、技术总结 无。 二、英语总结(生词&#xff1a;1) 1. disposal (1)dispose: dis-(“aprt”) ponere(“to put, place”) vt. dispose literally means “to put apart(to separate sth…...

录播课制作技术指南

1.技术版本选择策略 优先采用长期支持版本作为课程开发基础&#xff0c;此类版本在企业级应用中普及度高且稳定性强。技术选型直接影响课程生命周期&#xff0c;稳定的底层框架可降低后续维护成本&#xff0c;避免因技术迭代导致教学内容快速过时。建议定期查看技术社区官方公告…...

【2025软考高级架构师】——知识脑图总结

摘要 本文是一份关于 2025 年软考高级架构师的知识脑图总结。整体涵盖系统工程与信息系统基础、软件工程、项目管理等众多板块&#xff0c;每个板块又细分诸多知识点&#xff0c;如系统工程部分提及系统工程方法、信息系统生命周期等内容&#xff0c;旨在为备考人员提供系统全…...

Allegro23.1新功能之如何设置高压爬电间距规则操作指导

Allegro23.1新功能之如何设置高压爬电间距规则操作指导 Allegro23.1升级到了23.1之后,新增了一个设置高压爬电间距的规则 如下图,不满足爬电间距要求,以DRC的形式报出来了...

**电商推荐系统设计思路**

互联网大厂Java面试实录&#xff1a;马小帅的生死时速 第一轮提问 面试官&#xff08;严肃地&#xff09;&#xff1a;马小帅&#xff0c;请你先简单介绍一下你过往的项目经验&#xff0c;特别是你在项目中使用的技术栈。 马小帅&#xff08;紧张地搓手&#xff09;&#xff…...

BC19 反向输出一个四位数

题目&#xff1a;BC19 反向输出一个四位数 描述 将一个四位数&#xff0c;反向输出。&#xff08;有前导零的时候保留前导零&#xff09; 输入描述&#xff1a; 一行&#xff0c;输入一个整数n&#xff08;1000 < n < 9999&#xff09;。 输出描述&#xff1a; 针对每组…...

【前端】【面试】在 Vue-React 的迁移重构工作中,从状态管理角度来看,Vuex 迁移到 Redux 最大的挑战是什么,你是怎么应对的?

在从 Vue&#xff08;Vuex&#xff09;迁移到 React&#xff08;Redux&#xff09;时&#xff0c;状态管理无疑是重构中最具挑战性的部分之一。两者虽本质上都实现了全局状态集中式管理&#xff0c;但在思想、结构与实现方式上存在显著差异。 Vuex 到 Redux 状态管理迁移的挑战…...

ActiveMQ 与其他 MQ 的对比分析:Kafka/RocketMQ 的选型参考(一)

消息队列简介 在当今的分布式系统架构中&#xff0c;消息队列&#xff08;Message Queue&#xff0c;MQ&#xff09;扮演着举足轻重的角色&#xff0c;已然成为构建高可用、高性能系统不可或缺的组件。消息队列本质上是一种异步通信的中间件&#xff0c;它允许不同的应用程序或…...

OPENGLPG第九版学习 -视口变换、裁减、剪切与反馈

文章目录 5.1 观察视图5.1.1 视图模型—相机模型OpenGL的整个处理过程中所用到的坐标系统&#xff1a;视锥体视锥体的剪切 5.1.2 视图模型--正交视图模型 5.2 用户变换5.2.1 矩阵乘法的回顾5.2.2 齐次坐标5.2.3 线性变换与矩阵SRT透视投影正交投影 5.2.4 法线变换逐像素计算法向…...

大连理工大学选修课——图形学:第一章 图形学概述

第一章 图形学概述 计算机图形学及其研究内容 计算机图形学&#xff1a;用数学算法将二维或三维图形转化为计算机显示器的格栅形式的科学。 图形 计算机图形学的研究对象为图形广义来说&#xff0c;能在人的视觉系统形成视觉印象的客观对象都可称为图形。 既包括了各种几何…...

雅思听力--75个重点单词/词组

文章目录 1. in + 一段时间2. struggle with + doing sth.3. due to + n. / doing sth.4. all kinds of + n.5. supply6. get sb. down7. sth. be a hit8. ups and downs1. in + 一段时间 “in ten minutes”表示“10分钟内”,“in + 一段时间”表示“在一段时间之内”。 You…...

dubbo 参数校验-ValidationFilter

org.apache.dubbo.rpc.Filter 核心功能 拦截RPC调用流程 Filter是Dubbo框架中实现拦截逻辑的核心接口&#xff0c;作用于服务消费者和提供者的作业链路&#xff0c;支持在方法调用前后插入自定义逻辑。如参数校验、异常处理、日志记录等。扩展性机制 Dubbo通过SPI扩展机制动态…...

Fine Structure-Aware Sampling(AAAI 2024)论文笔记和启发

文章目录 本文解决的问题本文提出的方法以及启发 本文解决的问题 传统的基于Pifu的人体三维重建一般通过采样来进行学习。一般选择的采样方法是空间采样&#xff0c;具体是在surface的表面随机位移进行样本的生成。这里的采样是同时要在XYZ三个方向上进行。所以这导致了一个问…...

股票单因子的检验方法有哪些?

股票单因子的检验方法主要包括以下四类方法及相关指标&#xff1a; 一、统计指标检验 IC值分析法 定义&#xff1a;IC值&#xff08;信息系数&#xff09;衡量因子值与股票未来收益的相关性&#xff0c;包括两种计算方式&#xff1a; Normal IC&#xff1a;基于Pearson相关系数…...

Android第三次面试总结之activity和线程池篇(补充)

一、线程池高频面试题 1. 为什么 Android 中推荐使用线程池而非手动创建线程&#xff1f;&#xff08;字节跳动 / 腾讯真题&#xff09; 核心考点&#xff1a;线程池的优势、资源管理、性能优化答案要点&#xff1a; 复用线程&#xff1a;避免重复创建 / 销毁线程的开销&…...

【Trae+LucidCoder】三分钟编写专业Dashboard页面

AI辅助编码作为一项革命性技术&#xff0c;正在改变开发者的工作方式。本文将深入探讨如何利用Trae的AI Coding功能构建专业的Dashboard页面&#xff0c;同时向您推荐一个极具价值的工具——Lucids.top&#xff0c;它能够将页面截图转换为AI IDE的prompt&#xff0c;从而生成精…...

CUDA Toolkit 12.9 与 cuDNN 9.9.0 发布,带来全新特性与优化

NVIDIA 近日发布了 CUDA Toolkit 12.9&#xff0c;为开发者提供了一系列新功能和改进&#xff0c;旨在进一步提升 GPU 加速应用的性能和开发效率。CUDA Toolkit 是创建高性能 GPU 加速应用的关键开发环境&#xff0c;广泛应用于从嵌入式系统到超级计算机的各种计算平台。 新特…...

chrome 浏览器怎么不自动提示是否翻译网站

每次访问外国语网页都会弹出这个对话框&#xff0c;很是麻烦&#xff0c;每次都得手动关闭一下。 不让他弹出来方法&#xff1a; 设置》语言》首选语言》添加语言&#xff0c;搜索英语添加上 如果需要使用翻译&#xff0c;就点击三个点&#xff0c;然后选择翻译...