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

基于AIS动态数据与AI结合得经纬度标示算法

目标和场景应用

  摄像头可以拍到港口,船舶有ais系统,如何和AI结合起来,在摄像头画面中将每个船得经纬度地址标示在视频上. 使用协议接收AIS船舶动态数据结合,通过AI技术实现在画面上实时标注每艘船的经纬度(甚至船名、航速等),可以用于港口监控、智能海事、船舶调度等场景。

一、系统架构概览

1 [摄像头视频流] → [AI目标检测] → [船舶检测+跟踪]
2 [AIS数据流] → [船舶ID匹配] → [地理坐标→图像坐标映射] → [叠加标注到视频]
3 [输出带标注的实时视频流]

二、关键技术步骤详解

1. 获取并解析AIS数据

AIS数据包含每艘船的:

  • MMSI(船舶唯一ID)
  • 经纬度 航向、
  • 航速 船名、
  • 呼号等

获取方式包括:
本地AIS接收机(如USB AIS dongle + 软件如 OpenCPN, ShipPlotter)
网络AIS服务(如 MarineTraffic API、AISHub、VesselFinder)
自建AIS基站 + 解码器(如 rtl-ais)

//json 数据示例
{"MMSI": "412123456","LAT": 31.2345,"LON": 121.6789,"SOG": 12.5,"COG": 90.0,"NAME": "COSCO SHANGHAI"
}

2. 摄像头视频中检测船舶(AI目标检测)

使用目标检测模型识别画面中的船舶:
使用模型:

1 YOLOv11 (速度快,适合实时)
2 Faster R-CNN(精度高,速度慢)
3 自定义训练 (用港口船舶数据集微调)

标注内容:

检测框(bounding box)
跟踪ID(使用 FASTREID实现跨帧跟踪)
船舶匹配(视频目标 ↔ AIS船舶)
将画面中的“船舶目标”与AIS中的“船舶实体”匹配。

3. 船舶匹配算法(视频目标 ↔ AIS船舶)

算法1 基于位置投影匹配

  • 将AIS经纬度 → 投影到图像坐标(需相机标定)
  • 计算每个AIS船投影点与视频检测框中心的距离
  • 最近邻匹配(可加阈值过滤)
  • 使用排序方法来确定船只之间得关系

算法2 基于运动轨迹匹配 多船、遮挡场景

  • 视频中跟踪船舶运动方向/速度
  • 与AIS船舶的COG/SOG匹配

调试方式

  • 人工校准 + MMSI显示
  • 人工指定某检测框对应某MMSI 调试小范围

4. 相机标定与地理坐标映射

建立 经纬度 → 像素坐标 的映射关系,步骤为:
1 相机标定(内参+外参):
使用棋盘格标定相机内参(OpenCV)
获取相机位置(经纬度、高度、俯仰角、偏航角)

2 建立投影模型:
使用 透视投影 + 地球曲面近似平面
在这里插入图片描述
通过调整俯仰,焦距,偏航,翻滚等角度矫正得矩阵运算以后得到经度拉直得画面
在这里插入图片描述
以上只是示例,实际画面根据摄像头得类型会比较复杂,可以使用我们得工具来进行各种矫正,包括鹰眼矫正

3 地理坐标 → 图像坐标公式(简化平面投影)
代码示例

import mathdef latlon_to_pixel(lat, lon, cam_lat, cam_lon, cam_yaw_deg, cam_height, img_width, img_height, fov_h_deg):# 计算相对位置(米)dy = (lat - cam_lat) * 111320  # 纬度差转米dx = (lon - cam_lon) * 111320 * math.cos(math.radians(cam_lat))  # 经度差转米# 转为相机局部坐标系(假设相机朝向 cam_yaw)angle = math.atan2(dy, dx) - math.radians(cam_yaw_deg)distance = math.sqrt(dx*dx + dy*dy)# 投影到图像平面(简单针孔模型)if distance == 0: return Nonepixel_x = img_width / 2 + (math.tan(angle) * cam_height / distance) * (img_width / 2 / math.tan(math.radians(fov_h_deg)/2))pixel_y = img_height - (cam_height / distance) * (img_height / 2 / math.tan(math.radians(fov_h_deg)/2))return pixel_x, pixel_y

其他
1 可以使用OpenCV + 地理投影库 pyproj + 3D旋转矩阵 加辅助计算翻滚,偏航,俯仰关系

2 校准技巧:
手动选取画面中几艘已知AIS位置的船,反推相机参数
使用 GIS 工具(如 QGIS)辅助标定

5. 实时叠加标注到视频

cv2.putText(frame, f"{ship_name} ({lat:.4f}, {lon:.4f})", (int(x), int(y)-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,255), 2)
cv2.rectangle(frame, (x1,y1), (x2,y2), (0,255,0), 2)

可标注内容:

  • 船名
  • MMSI
  • 经纬度
  • 航速/航向
  • 匹配置信度

三 、开发步骤

1 获取AIS数据并解析(打印到控制台)
2 用YOLO检测视频中的船(不匹配,只画框)
3 手动输入相机经纬度、朝向、高度,写死几个AIS船位置,投影到画面验证
4 实现简单最近邻匹配(距离<50像素则匹配)
5 加入跟踪ID,实现跨帧稳定匹配
6 优化投影模型(考虑镜头畸变、地球曲率)
7 部署为实时系统(flv 输出 或 RTSP输出)

四 、优化方向

1 多摄像头融合(扩大覆盖范围)
2 时间同步(AIS和视频帧时间戳对齐)
3 遮挡处理(预测船舶位置)
4 异常船舶报警(AIS关闭、偏离航道等)
5 3D可视化(结合数字孪生港口)

五 配置

{
“camera_lat”: 31.2345,
“camera_lon”: 121.6789,
“camera_height_m”: 30.0,
“camera_yaw_deg”: 90.0,
“camera_fov_horizontal_deg”: 60.0,
“image_width”: 1920,
“image_height”: 1080
}

ais 数据接收样例
[
{
“MMSI”: “412123456”,
“LAT”: 31.2350,
“LON”: 121.6795,
“SOG”: 12.5,
“COG”: 90.0,
“NAME”: “COSCO SHANGHAI”
},
{
“MMSI”: “412654321”,
“LAT”: 31.2340,
“LON”: 121.6780,
“SOG”: 8.2,
“COG”: 270.0,
“NAME”: “MAERSK HOUSTON”
}
]

import cv2
import numpy as np
import json
import math
from ultralytics import YOLO
from collections import defaultdict# --------------------------
# 1. 加载配置
# --------------------------
with open('camera_config.json', 'r') as f:cam_cfg = json.load(f)with open('ais_data.json', 'r') as f:ais_ships = json.load(f)  # 后续改为实时流# --------------------------
# 2. 初始化YOLO模型(检测船舶)
# --------------------------
# 首次运行会自动下载 yolov8n.pt
model = YOLO("yolov8n.pt")  # 可换为 yolov8s.pt 或自定义训练模型
# 如果你有船舶专用模型,替换为: model = YOLO("ship_yolov8.pt")# --------------------------
# 3. 地理坐标 → 图像像素坐标 转换函数(简化平面投影)
# --------------------------
def latlon_to_pixel(lat, lon, cam_lat, cam_lon, cam_yaw_deg, cam_height, img_w, img_h, fov_h_deg):"""将经纬度投影到图像坐标(简化模型,适合小范围港口)"""# 纬度差 → 米(近似)dy = (lat - cam_lat) * 111320# 经度差 → 米(考虑纬度缩放)dx = (lon - cam_lon) * 111320 * math.cos(math.radians(cam_lat))# 转为相机局部坐标系(相机朝向 cam_yaw_deg)angle_rad = math.atan2(dy, dx) - math.radians(cam_yaw_deg)distance = math.sqrt(dx*dx + dy*dy)if distance < 1:  # 避免除零return None# 简化针孔投影(无畸变)# 水平方向:根据角度和FOV计算像素偏移pixel_x = img_w / 2 + (math.tan(angle_rad) * cam_height / distance) * (img_w / 2 / math.tan(math.radians(fov_h_deg)/2))# 垂直方向:距离越近,y值越大(画面底部)pixel_y = img_h - (cam_height / distance) * (img_h / 2 / math.tan(math.radians(fov_h_deg)/2))return pixel_x, pixel_y# --------------------------
# 4. 匹配函数:AIS船 ↔ 视频检测框(最近邻)
# --------------------------
def match_ais_to_detections(ais_list, detections, frame_shape):"""简单匹配:计算AIS投影点与检测框中心的欧氏距离,取最近且<阈值者"""img_h, img_w = frame_shape[:2]matches = []for ais in ais_list:proj = latlon_to_pixel(ais['LAT'], ais['LON'],cam_cfg['camera_lat'], cam_cfg['camera_lon'],cam_cfg['camera_yaw_deg'], cam_cfg['camera_height_m'],img_w, img_h, cam_cfg['camera_fov_horizontal_deg'])if proj is None:continuepx, py = projbest_dist = float('inf')best_det = Nonefor det in detections:x1, y1, x2, y2 = det['bbox']cx = (x1 + x2) / 2cy = (y1 + y2) / 2dist = math.sqrt((cx - px)**2 + (cy - py)**2)if dist < best_dist:best_dist = distbest_det = det# 设定匹配阈值(像素)if best_dist < 100 and best_det is not None:matches.append({'ais': ais,'detection': best_det,'projected_point': (int(px), int(py)),'distance': best_dist})return matches# --------------------------
# 5. 主循环:视频处理
# --------------------------
def main():# 打开摄像头或视频文件cap = cv2.VideoCapture(0)  # 改为 0 为摄像头,或 'port.mp4' 为视频文件if not cap.isOpened():print("❌ 无法打开摄像头/视频")returnframe_id = 0while True:ret, frame = cap.read()if not ret:break# YOLO检测船舶(class 8 = 'boat' 或 'ship',COCO中船是 class 8)# 注意:COCO数据集中 'boat' 是 class 8,但可能漏检货轮,建议微调模型results = model(frame, classes=[8], conf=0.3, verbose=False)  # 只检测 boat 类detections = []for r in results:boxes = r.boxesfor box in boxes:x1, y1, x2, y2 = map(int, box.xyxy[0].tolist())conf = box.conf[0].item()cls_id = int(box.cls[0].item())detections.append({'bbox': [x1, y1, x2, y2],'conf': conf,'class_id': cls_id})# 画检测框(无匹配时)cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)# 匹配AIS船舶与检测框matches = match_ais_to_detections(ais_ships, detections, frame.shape)# 在画面上标注匹配结果for match in matches:ais = match['ais']det = match['detection']px, py = match['projected_point']x1, y1, x2, y2 = det['bbox']# 画匹配框(蓝色)cv2.rectangle(frame, (x1, y1), (x2, y2), (255, 0, 0), 3)# 标注船名 + 经纬度label = f"{ais['NAME']} ({ais['LAT']:.4f}, {ais['LON']:.4f})"cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 0), 2)# 画投影点(红色圆点)cv2.circle(frame, (px, py), 5, (0, 0, 255), -1)# 显示帧数cv2.putText(frame, f"Frame: {frame_id}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2)cv2.imshow("Ship AIS Overlay", frame)frame_id += 1if cv2.waitKey(1) & 0xFF == ord('q'):breakcap.release()cv2.destroyAllWindows()if __name__ == "__main__":main()

实时AIS流
用socket或requests轮询API,或监听串口/UDP
精确投影
使用 OpenCV solvePnP+ 地面控制点标定
船舶跟踪
加入ByteTrack或DeepSORT,多船稳定匹配 加入匈牙利算法或卡尔曼滤波预测
Web可视化
用 Flask + WebSocket 推流到浏览器
报警功能
检测AIS缺失或位置异常

调试完成以后改成c++


文章转载自:

http://BtBC7MYR.Lkcqz.cn
http://nIqeKOrK.Lkcqz.cn
http://PJThqtDg.Lkcqz.cn
http://7HLmw8Fw.Lkcqz.cn
http://M0uwqgF4.Lkcqz.cn
http://aVoKILdR.Lkcqz.cn
http://N4ScCJQa.Lkcqz.cn
http://9sJiHzoB.Lkcqz.cn
http://hQum2aNQ.Lkcqz.cn
http://Rn0CTEGY.Lkcqz.cn
http://H4EOXm8i.Lkcqz.cn
http://rw1YZGTd.Lkcqz.cn
http://yWuuwijp.Lkcqz.cn
http://5i1oPBVA.Lkcqz.cn
http://CgEUCltI.Lkcqz.cn
http://p4pwwLrx.Lkcqz.cn
http://EqYCIWZT.Lkcqz.cn
http://qGVUraE0.Lkcqz.cn
http://wbE2e0zT.Lkcqz.cn
http://SbeXMEkn.Lkcqz.cn
http://FwQzJiNz.Lkcqz.cn
http://vh9BDPcs.Lkcqz.cn
http://gr77Xqnu.Lkcqz.cn
http://aBFeIzNz.Lkcqz.cn
http://vcyvEJyF.Lkcqz.cn
http://Qrgm2xOq.Lkcqz.cn
http://cxYwaZeQ.Lkcqz.cn
http://FWbjtka7.Lkcqz.cn
http://v05W4qL1.Lkcqz.cn
http://bmtVe3N2.Lkcqz.cn
http://www.dtcms.com/a/376650.html

相关文章:

  • 第5章 HTTPS与安全配置
  • ZYNQ PL端采集AD7606数据与ARM端QT显示实战指南
  • 头条号采集软件V12.2主要更新内容
  • 吱吱企业即时通讯平衡企业通讯安全与协作,提升企业办公效率
  • 中线安防保护器,也叫终端电气综合治理保护设备为现代生活筑起安全防线
  • 从零实现一个简化版string 类 —— 深入理解std::string的底层设计
  • 记一次Cloudflare五秒盾的研究
  • RDMA和RoCE有损无损
  • 大数据毕业设计选题推荐-基于大数据的护肤品店铺运营数据可视化分析系统-Hadoop-Spark-数据可视化-BigData
  • C#,RabbitMQ从入门到精通,.NET8.0(路由/分布式/主题/消费重复问题 /延迟队列和死信队列/消息持久化 )/RabbitMQ集群模式
  • 开源芯片革命的起源与未来
  • 开源的Web服务器管理平台Termix
  • Dify开源AI框架介绍
  • Git 技巧:用 --no-walk 参数 + 别名,精准显示指定提交记录
  • kafka3.8集群搭建
  • 基于 Python + redis + flask 的在线聊天室
  • 35.神经网络:从感知机到多层网络
  • 单元测试-junit5的spy部分mock
  • 新能源汽车车载传感器数据处理系统设计(论文+源码)
  • 基于安全抽象模型(SAM)的汽车网络安全防御与攻击分析
  • 【qt】通过TCP传输json,json里包含图像
  • 力扣每日一刷Day 20
  • 线程池队列与活跃度报警检测器实现详解
  • 【硬件-笔试面试题-80】硬件/电子工程师,笔试面试题(知识点:MOS管与三极管的区别)
  • A股大盘数据-20250910分析
  • 大数据毕业设计-基于大数据的健康饮食推荐数据分析与可视化系统(高分计算机毕业设计选题·定制开发·真正大数据)
  • 墨水屏程序
  • 小米自带浏览器提示“已停止访问该网页”的解决办法以及一些优化
  • 零代码入侵:Kubernetes 部署时自动注入 kube-system UID 到 .NET 9 环境变量
  • Python核心技术开发指南(049)——文件操作综合应用