diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3e7ad9f..1612362 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
IF(WIN32)
# ======== OpenCV 配置 ========
- set(OpenCV_DIR "C:/Lib/opencv455/build/x64/vc14/lib")
+ set(OpenCV_DIR "C:/opencv/build/x64/vc14/lib")
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
link_libraries(${OpenCV_LIBS})
@@ -71,7 +71,7 @@ IF(WIN32)
# ======== FFMPEG配置 ========
set(FFMPEG_DIR "C:/Lib/ffmpeg4")
set(FFMPEG_INCLUDE_DIRS ${FFMPEG_DIR}/include)
- set(FFMPEG_LIBS_DIR ${FFMPEG_DIR}/lib)
+ set(FFMPEG_LIBS_DIR ${FFMPEG_DIR}/lib/x64)
include_directories(${FFMPEG_DIR})
include_directories(${FFMPEG_INCLUDE_DIRS})
diff --git a/doc/API_MANUAL.pdf b/README.pdf
similarity index 98%
rename from doc/API_MANUAL.pdf
rename to README.pdf
index 31b7644..5b89879 100644
Binary files a/doc/API_MANUAL.pdf and b/README.pdf differ
diff --git a/ReadMe.md b/ReadMe.md
index dcf9145..79e8362 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -1,20 +1,206 @@
-# 航拍图像拼接系统
+# 航拍拼接模块接口说明
-## 日志
-- 1 2025/1/26
-完成了基础的外参拼接+BA优化过程,目前不支持动态调整拼接大小位置比例尺等功能。当载体持续运动扫描时,无法支持连续拼接以及回溯。因此要求必须加入文件缓存机制,并使用瓦片对数据进行管理,这样可以极大扩展拼接范围,且输出内容更为标准化。
+本模块用于吊舱的扫描全景图拼接,包含前视、下视以及特征拼接三个模式。前视与下视投影面和效果均不同。二者接口大部分相同。
-【初步设想】:建立二级文件缓存,其中第一级存储原始帧(图像+H矩阵等),第二级存储生成的标准瓦片。当系统工作时,根据当前视野范围和XYZ瓦片等级(X),开始从2级缓存搜索瓦片,如果存在瓦片则直接加载,如果不存在则从1级缓存读取原始帧生成瓦片,并将瓦片加入2级缓存。
-【关键技术】:文件缓存技术、标准瓦片转换技术
+特征拼接是完全基于特征的图像算法,本身存在较大的累计误差,仅用于测试和对比出图,暂时没有应用价值。
-- 2 20250205
-
-上述开发计划存在问题,拼接算法应是后台服务,应当生成标准产品,而不随着显示更改逻辑,这里考虑生成谷歌瓦片,并通过流传输到显示端,由显控处理显示逻辑。
-- 20250213
+下视拼接是最广泛使用的拼接方式,可以随着载体飞行进行连续长时拼接,并生成含有地理信息
+
+
+
+
+
+前视拼接的效果接近360°全景。
+
+
+
+
+
+
+
+## 1. 依赖
+本模块依赖ceres优化库(包含gflag、glog)以及cuda支持,opencv 455支持。
+除cuda库外,其余库均以vc14动态库文件形式提供。
+
+使用cuda将极大加速前视极坐标拼接模块。
+
+
+## 2. 下视接口
+
+
+```C++
+static API_UnderStitch* Create(std::string cachedir = "./cache");
+```
+模块创建接口,其中默认参数为使用cache的路径,cache将缓存需要处理的帧原始数据。
+
+```C++
+static void Destroy(API_UnderStitch* obj);
+```
+模块析构接口,使用完毕后释放内存。
+
+```C++
+virtual UPanInfo Init(FrameInfo info) = 0;
+```
+初始化接口,请使用拼接时刻的内外参信息进行初始化。初始化完成后返回全景图的参数
+
+
+```C++
+ virtual void SetOutput(std::string name, std::string outdir) = 0;
+```
+设置输出路径,下视模块按照通用谷歌瓦片生成标准256*256瓦片,提前设置好输出文件夹。
+
+```C++
+ virtual void SetConfig(UPanConfig config) = 0;
+```
+设置运行参数。
+
+
+
+```C++
+ virtual BYTE8 Run(GD_VIDEO_FRAME_S img, FrameInfo para) = 0;
+```
+运行拼接流程,在该过程中程序自动将当前图像重新投影到全景图上,可以通过访问全景图内存进行实时显示。
+
+
+```C++
+ virtual GD_VIDEO_FRAME_S ExportPanAddr() = 0;
+```
+获取全景图接口,其中GD_VIDEO_FRAME_S是高德研发中心通用帧接口,内部维护了图像类型和指针等信息。具体参见GD_VIDEO_FRAME_S接口说明
+
+
+```C++
+ virtual SINT32 OptAndOutCurrPan() = 0;
+```
+全景投影完毕后,可以调用该接口进行优化,主要是精细对齐帧以及拼接缝消除等,暂未实现。
+
+
+
+## 前视接口
+
+```C++
+static API_FrontStitch* Create(std::string cachedir = "./cache");
+```
+
+模块创建接口,其中默认参数为使用cache路径,前视模块不使用cache。
+```C++
+static void Destroy(API_FrontStitch* obj);
+```
+模块析构接口,使用完毕后释放内存。
+
+```C++
+virtual FPanInfo Init(FrameInfo info, ScanRange stAzRange, ScanRange stPtRange) = 0;
+```
+初始化接口,使用拼接时刻的内外参信息进行初始化,
+
+```C++
+ virtual BYTE8 Run(GD_VIDEO_FRAME_S img, FrameInfo para) = 0;
+```
+运行拼接流程,在该过程中程序自动将当前图像重新投影到全景图上,可以通过访问全景图内存进行实时显示。
+
+
+
+```C++
+ virtual GD_VIDEO_FRAME_S ExportPanAddr() = 0;
+```
+获取全景图接口,其中GD_VIDEO_FRAME_S是高德研发中心通用帧接口,内部维护了图像类型和指针等信息。具体参见GD_VIDEO_FRAME_S接口说明
+
+
+```C++
+ virtual SINT32 OptAndOutCurrPan() = 0;
+```
+全景投影完毕后,可以调用该接口进行优化,主要是精细对齐帧以及拼接缝消除等,暂未实现。
+
+
+
+
+
+# 附 下视拼接的标准地理产品
+
+下视拼接过程目前是功能最为完善的,主要分为粗拼接+优化两个过程。
+>**粗拼接** 是指利用外部参数信息直接利用无源定位技术对帧进行地理纠正,纠正后的数据天然具备地理属性,只需要简单的仿射变换即可显示为空间一致的底图。
+
+>**优化** 是指利用帧间同名点匹配关系建立误差方程,迭代优化映射关系的过程。
+
+
+粗拼接是整个工作流的核心,形成任意场景均有高可用性的拼接实现。而优化过程是可以关闭的,用于对拼接质量要求较高的场景或者外参误差较大的设备。
+
+
+如API说明所示,SDK提供了全景图的显示接口。**但我们不建议使用该全景图**,主要原因是全景显示策略与逻辑是为了便于展示算法效果和内部切瓦片使用的。对图层叠加以及漫游、回溯等高级功能难以支持。
+
+相反的,在下视算法执行期间,还生成了两种标准地理数据,具有通用的行业接口。能够轻松支持各类地理web、桌面端应用。
+
+1. 单帧纠正产品
+
+帧输入后,算法利用外参信息对图像进行地理纠正,简单说就是正北+下视校正。且给出帧的kml信息(谷歌地球标准数据层)。
+
+```xml
+
+
+
+
+ DJI6830
+
+ DJI6830.png
+
+
+ 30.267059
+ 30.264926
+ 114.446180
+ 114.443523
+
+
+
+
+```
+
+2. 谷歌瓦片
+
+视频输入过程中,算法根据外参变化情况自行判断执行优化时机,优化完成后会将拼接好的信息切成标准谷歌瓦片。
+
+谷歌瓦片按照{Z}-{X}-{Y}.png形式进行命名,能够被gis前端正确显示。下图是cesiumjs的可视化效果。
+**因此整个执行流程可以概括为实时显示基于kml的帧,并周期性的或者触发式的读取瓦片覆盖显示。**
+
+
+
+
+
+
+
+
+## 变更说明
+
+### 20250919
+1. 修复了长焦初始化崩溃问题,限制了全景图分辨率,最大水平方向像素个数不多于1万。
+2. 增加前视扫描换向判断,内部自动初始化拼接地面起始点,连续拼接不至于畸变。
+3. 俯仰方向的零位由竖直向下改为水平为0,更符合使用习惯。
+4. 新增日志支持,日志为可执行程序下“StitchLog”文件夹。
+5. 原先使用1080p测试可见光,改为720p后,除图像宽高不同外,像元尺寸应乘以1.5
+
+
+
+
+
+
+### 20250924
+1. 按照外场要求,扫描方向切换不进行全景图初始化,改为多扫描几个条带后,根据位移路径大小初始化,这样可以尽可能保留更多的条带。
+
+
+### 20250925
+1. 补充 前视扫描全景图像方<->经纬高<->伺服导引角的关系计算
+
+
+### 20251015
+根据领导指示,前视拼接技术不再进一步研究
+
+
+
+### 20251030
+近期完成下视算法的改进:
+1. 新增了基于se3李代数优化,降低了优化参数量,优化结果更有物理意义
+2. 对工程结构进行重构,前视/纯特征与下视分开,所有测试代码进入./test目录
+3. map/Cesium 离线下载js文件,现已支持调试网内看瓦片和kml
+4. 其他小改动
+
-已初步完成地理快拼、BA、谷歌瓦片输出等核心功能开发,能够输出符合谷歌标准的256瓦片。整理以下遗留问题:
-【1】全景图的分辨率和尺寸应当根据硬件水平自适应,目前是人工指定的
-【2】长时间推扫导致成像区域离开预设的全景范围,如何自适应处理。
-【3】一定要提供边扫描边输出瓦片能力
\ No newline at end of file
diff --git a/doc/API_MANUAL.md b/doc/API_MANUAL.md
deleted file mode 100644
index af91b3f..0000000
--- a/doc/API_MANUAL.md
+++ /dev/null
@@ -1,193 +0,0 @@
-# 航拍拼接模块接口说明
-
-本模块用于吊舱的扫描全景图拼接,包含前视、下视以及特征拼接三个模式。前视与下视投影面和效果均不同。二者接口大部分相同。
-
-特征拼接是完全基于特征的图像算法,本身存在较大的累计误差,仅用于测试和对比出图,暂时没有应用价值。
-
-
-
-下视拼接是最广泛使用的拼接方式,可以随着载体飞行进行连续长时拼接,并生成含有地理信息
-
-
-
-
-
-前视拼接的效果接近360°全景。
-
-
-
-
-
-
-
-## 1. 依赖
-本模块依赖ceres优化库(包含gflag、glog)以及cuda支持,opencv 455支持。
-除cuda库外,其余库均以vc14动态库文件形式提供。
-
-使用cuda将极大加速前视极坐标拼接模块。
-
-
-## 2. 下视接口
-
-
-```C++
-static API_UnderStitch* Create(std::string cachedir = "./cache");
-```
-模块创建接口,其中默认参数为使用cache的路径,cache将缓存需要处理的帧原始数据。
-
-```C++
-static void Destroy(API_UnderStitch* obj);
-```
-模块析构接口,使用完毕后释放内存。
-
-```C++
-virtual UPanInfo Init(FrameInfo info) = 0;
-```
-初始化接口,请使用拼接时刻的内外参信息进行初始化。初始化完成后返回全景图的参数
-
-
-```C++
- virtual void SetOutput(std::string name, std::string outdir) = 0;
-```
-设置输出路径,下视模块按照通用谷歌瓦片生成标准256*256瓦片,提前设置好输出文件夹。
-
-```C++
- virtual void SetConfig(UPanConfig config) = 0;
-```
-设置运行参数。
-
-
-
-```C++
- virtual BYTE8 Run(GD_VIDEO_FRAME_S img, FrameInfo para) = 0;
-```
-运行拼接流程,在该过程中程序自动将当前图像重新投影到全景图上,可以通过访问全景图内存进行实时显示。
-
-
-```C++
- virtual GD_VIDEO_FRAME_S ExportPanAddr() = 0;
-```
-获取全景图接口,其中GD_VIDEO_FRAME_S是高德研发中心通用帧接口,内部维护了图像类型和指针等信息。具体参见GD_VIDEO_FRAME_S接口说明
-
-
-```C++
- virtual SINT32 OptAndOutCurrPan() = 0;
-```
-全景投影完毕后,可以调用该接口进行优化,主要是精细对齐帧以及拼接缝消除等,暂未实现。
-
-
-
-## 前视接口
-
-```C++
-static API_FrontStitch* Create(std::string cachedir = "./cache");
-```
-
-模块创建接口,其中默认参数为使用cache路径,前视模块不使用cache。
-```C++
-static void Destroy(API_FrontStitch* obj);
-```
-模块析构接口,使用完毕后释放内存。
-
-```C++
-virtual FPanInfo Init(FrameInfo info, ScanRange stAzRange, ScanRange stPtRange) = 0;
-```
-初始化接口,使用拼接时刻的内外参信息进行初始化,
-
-```C++
- virtual BYTE8 Run(GD_VIDEO_FRAME_S img, FrameInfo para) = 0;
-```
-运行拼接流程,在该过程中程序自动将当前图像重新投影到全景图上,可以通过访问全景图内存进行实时显示。
-
-
-
-```C++
- virtual GD_VIDEO_FRAME_S ExportPanAddr() = 0;
-```
-获取全景图接口,其中GD_VIDEO_FRAME_S是高德研发中心通用帧接口,内部维护了图像类型和指针等信息。具体参见GD_VIDEO_FRAME_S接口说明
-
-
-```C++
- virtual SINT32 OptAndOutCurrPan() = 0;
-```
-全景投影完毕后,可以调用该接口进行优化,主要是精细对齐帧以及拼接缝消除等,暂未实现。
-
-
-
-
-
-# 附 下视拼接的标准地理产品
-
-下视拼接过程目前是功能最为完善的,主要分为粗拼接+优化两个过程。
->**粗拼接** 是指利用外部参数信息直接利用无源定位技术对帧进行地理纠正,纠正后的数据天然具备地理属性,只需要简单的仿射变换即可显示为空间一致的底图。
-
->**优化** 是指利用帧间同名点匹配关系建立误差方程,迭代优化映射关系的过程。
-
-
-粗拼接是整个工作流的核心,形成任意场景均有高可用性的拼接实现。而优化过程是可以关闭的,用于对拼接质量要求较高的场景或者外参误差较大的设备。
-
-
-如API说明所示,SDK提供了全景图的显示接口。**但我们不建议使用该全景图**,主要原因是全景显示策略与逻辑是为了便于展示算法效果和内部切瓦片使用的。对图层叠加以及漫游、回溯等高级功能难以支持。
-
-相反的,在下视算法执行期间,还生成了两种标准地理数据,具有通用的行业接口。能够轻松支持各类地理web、桌面端应用。
-
-1. 单帧纠正产品
-
-帧输入后,算法利用外参信息对图像进行地理纠正,简单说就是正北+下视校正。且给出帧的kml信息(谷歌地球标准数据层)。
-
-```xml
-
-
-
-
- DJI6830
-
- DJI6830.png
-
-
- 30.267059
- 30.264926
- 114.446180
- 114.443523
-
-
-
-
-```
-
-2. 谷歌瓦片
-
-视频输入过程中,算法根据外参变化情况自行判断执行优化时机,优化完成后会将拼接好的信息切成标准谷歌瓦片。
-
-谷歌瓦片按照{Z}-{X}-{Y}.png形式进行命名,能够被gis前端正确显示。下图是cesiumjs的可视化效果。
-**因此整个执行流程可以概括为实时显示基于kml的帧,并周期性的或者触发式的读取瓦片覆盖显示。**
-
-
-
-
-
-
-
-
-## 变更说明
-
-### 20250919
-1. 修复了长焦初始化崩溃问题,限制了全景图分辨率,最大水平方向像素个数不多于1万。
-2. 增加前视扫描换向判断,内部自动初始化拼接地面起始点,连续拼接不至于畸变。
-3. 俯仰方向的零位由竖直向下改为水平为0,更符合使用习惯。
-4. 新增日志支持,日志为可执行程序下“StitchLog”文件夹。
-5. 原先使用1080p测试可见光,改为720p后,除图像宽高不同外,像元尺寸应乘以1.5
-
-
-
-
-
-
-### 20250924
-1. 按照外场要求,扫描方向切换不进行全景图初始化,改为多扫描几个条带后,根据位移路径大小初始化,这样可以尽可能保留更多的条带。
-
-
-### 20250925
-1. 补充 前视扫描全景图像方<->经纬高<->伺服导引角的关系计算
-
-
diff --git a/map/Cesium/templates/index.html b/map/Cesium/templates/index.html
index 1d29c9b..5a79a8b 100644
--- a/map/Cesium/templates/index.html
+++ b/map/Cesium/templates/index.html
@@ -50,7 +50,7 @@
new Cesium.UrlTemplateImageryProvider({
url: 'https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',
minimumLevel: 1,
- maximumLevel: 20,
+ maximumLevel: 22,
credit: new Cesium.Credit('Google Maps')
})
);
@@ -63,7 +63,7 @@
// 添加数据源
viewer.dataSources.add(
- Cesium.KmlDataSource.load("/kml/DJI7990_z19.kml", options)
+ Cesium.KmlDataSource.load("/kml/DJI12670_z19.kml", options)
).then((dataSource) => {
console.log("KML数据加载完成:", dataSource);
// 自动飞到数据范围
@@ -80,7 +80,7 @@
const customTiles = viewer.imageryLayers.addImageryProvider(
new Cesium.UrlTemplateImageryProvider({
url: '/tiles/{z}/{x}/{y}.png', // 修改为X_Y.png格式
- maximumLevel: 19, // 根据你的瓦片层级修改
+ maximumLevel: 22, // 根据你的瓦片层级修改
minimumLevel: 0,
credit: new Cesium.Credit('Custom Tiles'),
// 添加错误处理
@@ -128,10 +128,11 @@
// 设置相机位置到瓦片区域
viewer.camera.setView({
destination: Cesium.Rectangle.fromDegrees(
- 114.623397, // west
- 30.328361, // south
- 114.623397, // east
- 30.328361 // north
+114.445953,
+30.267963,
+114.445953,
+30.267963,
+
),
orientation: {
heading: 0,
@@ -181,10 +182,10 @@
const lastDataSource = dataSources[dataSources.length - 1];
// 使用最后一个KML文件的经纬度范围
const rectangle = Cesium.Rectangle.fromDegrees(
- 114.623397, // west
- 30.328361, // south
- 114.623397, // east
- 30.328361 // north
+114.445953,
+30.267963,
+114.445953,
+30.267963,
);
// 设置相机位置
@@ -239,7 +240,7 @@
addMarker(114.623397, 30.328361, '熊司一起飞点', '这是一个测试标记点
点击查看详细信息');
// 初始加载KML文件(设置为false可以禁用KML加载)
- loadKMLFiles(true);
+