From c5abb82899fe00a631b0f9f3ba3569a3a4e92fbe Mon Sep 17 00:00:00 2001 From: wangchongwu <759291707@qq.com> Date: Thu, 13 Feb 2025 11:14:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=9E=8D=E5=90=88=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=88=B0=E6=A1=86=E6=9E=B6=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ReadMe.md | 10 ++- ...于吊舱产品态势感知能力构建.md | 19 ++++++ main.cpp | 9 ++- stitch/src/Arith_FeaMatch.h | 3 + stitch/src/Arith_FusionMap.cpp | 60 ++++++++++++++++++ stitch/src/Arith_FusionMap.h | 37 +++++++++++ stitch/src/Arith_GeoSolver.h | 7 ++- stitch/src/Arith_VideoStitch.cpp | 63 ++----------------- stitch/src/Arith_VideoStitch.h | 6 +- stitch/src/GoogleTile.cpp | 15 ++++- stitch/src/GoogleTile.h | 7 ++- 11 files changed, 163 insertions(+), 73 deletions(-) create mode 100644 doc/关于吊舱产品态势感知能力构建.md create mode 100644 stitch/src/Arith_FusionMap.cpp create mode 100644 stitch/src/Arith_FusionMap.h diff --git a/ReadMe.md b/ReadMe.md index 606e7a6..dcf9145 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -9,4 +9,12 @@ - 2 20250205 -上述开发计划存在问题,拼接算法应是后台服务,应当生成标准产品,而不随着显示更改逻辑,这里考虑生成谷歌瓦片,并通过流传输到显示端,由显控处理显示逻辑。 \ No newline at end of file +上述开发计划存在问题,拼接算法应是后台服务,应当生成标准产品,而不随着显示更改逻辑,这里考虑生成谷歌瓦片,并通过流传输到显示端,由显控处理显示逻辑。 + + +- 20250213 + +已初步完成地理快拼、BA、谷歌瓦片输出等核心功能开发,能够输出符合谷歌标准的256瓦片。整理以下遗留问题: +【1】全景图的分辨率和尺寸应当根据硬件水平自适应,目前是人工指定的 +【2】长时间推扫导致成像区域离开预设的全景范围,如何自适应处理。 +【3】一定要提供边扫描边输出瓦片能力 \ No newline at end of file diff --git a/doc/关于吊舱产品态势感知能力构建.md b/doc/关于吊舱产品态势感知能力构建.md new file mode 100644 index 0000000..c0be5a4 --- /dev/null +++ b/doc/关于吊舱产品态势感知能力构建.md @@ -0,0 +1,19 @@ +1. 主要目的 + 针对光电吊舱产品单帧视场覆盖小,侦察效率低的问题,在全景拼接技术的基础上设计态势融合识别的设想。 + +2.主要功能 + +2.1 扫描视场全景栅格 +提供扫描场景下基于地理位置的实时快拼能力,处理频率不低于25Hz。后台自动根据外参精度进行精拼接,并自动更新快拼成果。 +栅格层是整个态势的基础层。且具备空间测量能力。 + +2.2 地形地貌识别 +在凝视视角下对ROI区域进行地形地貌识别,叠加道路、水体、森林等识别结果。地形层为矢量层,能够开展GIS空间分析。支持追击导航等中级作战应用。 + +2.3 目标智能识别 +扫描视角/凝视视角下进行目标智能识别,将识别结果按照类型叠加在全景栅格上。形成最重要的实时态势。 + +2.4 协同作战/沙盘更新 +支持协同目标信息叠加,动态标识我方及敌方目标位置和行进方向 + + diff --git a/main.cpp b/main.cpp index d67d4d5..905e191 100644 --- a/main.cpp +++ b/main.cpp @@ -120,9 +120,8 @@ void ProcessIR() cv::Mat mat_pan;//全景显示 - //FILE* file = fopen("/media/wang/WORK/wangchongwu_gitea_2023/20241219152917_4.xraw","rb"); - FILE* file = fopen("D:/wangchongwu_gitea_2023/20241219152917_4.xraw", "rb"); - //FILE* file = fopen("/home/wang/data62/729dataset/ir_1280_1024_para40_y16/5.xraw","rb"); + + FILE* file = fopen("F:/S729/20241219152917_4.xraw", "rb"); GaussianRandom gr(0.0, 1, 0.0); @@ -233,8 +232,8 @@ void ProcessVL() cv::Mat mat_pan;//全景显示 - FILE* file = fopen("D:/wangchongwu_gitea_2023/20241219152643_1.video", "rb"); - //FILE* file = fopen("H:/21.video", "rb"); + FILE* file = fopen("F:/S729/20241219152643_1.video", "rb"); + GaussianRandom gr(0.0, 1, 0.0); diff --git a/stitch/src/Arith_FeaMatch.h b/stitch/src/Arith_FeaMatch.h index 91bd9b2..9e92b6c 100644 --- a/stitch/src/Arith_FeaMatch.h +++ b/stitch/src/Arith_FeaMatch.h @@ -1,6 +1,9 @@ #ifndef FEATURE_MATCHER_H #define FEATURE_MATCHER_H +#pragma once + + #include #include #include diff --git a/stitch/src/Arith_FusionMap.cpp b/stitch/src/Arith_FusionMap.cpp new file mode 100644 index 0000000..c8ed0a0 --- /dev/null +++ b/stitch/src/Arith_FusionMap.cpp @@ -0,0 +1,60 @@ +#include "Arith_FusionMap.h" +#include "Arith_Utils.h" +MapFusion::MapFusion(FileCache* cache) +{ + _cache = cache; +} + +MapFusion::~MapFusion() +{ +} + +void MapFusion::DirectMap(vector frameInd, cv::Mat mapH, cv::Mat pan, cv::Mat pan_mask) +{ + pan.setTo(0); + + // 从文件缓存获取帧 + auto _t_frame_cache = std::make_shared(); + for (size_t i = 0; i < frameInd.size(); i++) + { + KeyType key = frameInd[i]; + bool flag = _cache->get(key, _t_frame_cache); + + if (!flag) + { + continue; + } + + // 读取当前H + cv::Mat H1 = cv::Mat(3, 3, CV_64FC1, _t_frame_cache->H); + + // 与全景图的H相乘 + cv::Mat H = mapH * H1; + + // 利用H投影当前帧到全景 + cv::Mat imagetmp(pan.size(), CV_8UC3, cv::Scalar(0, 0, 0)); + + // 获取图像数据 + cv::Mat src = getRGBAMatFromGDFrame(_t_frame_cache->_frame_info, _t_frame_cache->_data); + + cv::warpPerspective(src, imagetmp, H, imagetmp.size(), cv::INTER_LINEAR, cv::BORDER_TRANSPARENT); + + cv::Mat mask = cv::Mat::ones(cv::Size(src.cols - 200, src.rows - 200), CV_8UC1) * 255; + cv::Mat warped_mask; + cv::warpPerspective(mask, warped_mask, H, imagetmp.size(), cv::INTER_LINEAR); + imagetmp.copyTo(pan, warped_mask); + + // 保存遮罩 + warped_mask.copyTo(pan_mask, warped_mask); + + //imshow("mask", pan_mask); + //waitKey(1); + + } + + +} + +void MapFusion::FusionMap(vector frameInd, cv::Mat mapH, cv::Mat pan, cv::Mat pan_mask) +{ +} diff --git a/stitch/src/Arith_FusionMap.h b/stitch/src/Arith_FusionMap.h new file mode 100644 index 0000000..441b114 --- /dev/null +++ b/stitch/src/Arith_FusionMap.h @@ -0,0 +1,37 @@ +/*********版权所有(C)2025,武汉高德红外股份有限公司*************************************** +* 文件名称:Arith_FusionMap.h +* 文件标识:拼接融合,提升全景图质量 +* 内容摘要: +* 其它说明: +* 当前版本:V0.5 +* 创建作者:04046wcw +* 创建日期:2025/02/13 +* 包含关系: +*****************************************************************************************/ +#pragma once + +#ifndef FUSION_MAP_H +#define FUSION_MAP_H + + +#include "FileCache.h" + +class MapFusion +{ +public: + MapFusion(FileCache* cache); + ~MapFusion(); + +public: + void DirectMap(vector frameInd, cv::Mat mapH, cv::Mat pan, cv::Mat pan_mask); //直接投影 + + void FusionMap(vector frameInd, cv::Mat mapH, cv::Mat pan, cv::Mat pan_mask);//融合投影 + +private: + + FileCache* _cache; +}; + + + +#endif \ No newline at end of file diff --git a/stitch/src/Arith_GeoSolver.h b/stitch/src/Arith_GeoSolver.h index 8046b06..18d15b2 100644 --- a/stitch/src/Arith_GeoSolver.h +++ b/stitch/src/Arith_GeoSolver.h @@ -39,10 +39,10 @@ public: GeoSolver(); ~GeoSolver(); - // 建立全景图与归一化地理系的H矩阵 + // 建立全景图与归一化地理系的H矩阵,解析出H cv::Mat findHomography(FrameInfo info); - // 解析出H + // 测试 cv::Mat findHomography2(FrameInfo info); // 设置起始拼接点外参 @@ -54,9 +54,10 @@ public: // 计算局部地理系下目标的经纬度 PointBLH getBLHFromGeo(cv::Point2f ptInGeo); - // 经纬度转换为局部地理系坐 + // 经纬度转换为局部地理系坐标 cv::Point2f getGeoFromBLH(PointBLH ptPos); + private: // 计算当前帧像方-地理坐标系R t(反投影关系) Proj AnlayseTform(FrameInfo info); diff --git a/stitch/src/Arith_VideoStitch.cpp b/stitch/src/Arith_VideoStitch.cpp index 96388e8..12aff99 100644 --- a/stitch/src/Arith_VideoStitch.cpp +++ b/stitch/src/Arith_VideoStitch.cpp @@ -31,6 +31,8 @@ VideoStitch::VideoStitch(SINT32 nWidth, SINT32 nHeight) _BATask = new BA_Task(_cache); + _fusionTask = new MapFusion(_cache); + _panPara = { 0 }; _totalFrameCnt = 0; @@ -246,70 +248,13 @@ SINT32 VideoStitch::ProcessFrame() //_BATask->OptFrame(_recvFrameKey, _H_pan); // 重投影所有帧到全景 - mapFrame(_recvFrameKey); - - - // 正反算验证 - // auto _t_frame_cache = std::make_shared(); - //bool flag = _cache->get(10, _t_frame_cache); + _fusionTask->DirectMap(_recvFrameKey, _H_pan, _panImage,_panMask); - //// 读取当前H - //cv::Mat H1 = cv::Mat(3, 3, CV_64FC1, _t_frame_cache->H); - - //// 与全景图的H相乘 - //cv::Mat H = _H_pan * H1; - - //PointBLH res = getBLHFromPan(warpPointWithH(H, cv::Point2f(519, 483)), _H_pan); - //PointBLH BLHpT = _GeoSolver->getBLHFromFrame(H1, cv::Point2f(519, 483)); return 0; } -void VideoStitch::mapFrame(vector frameInd) -{ - _panImage.setTo(0); - - // 从文件缓存获取帧 - auto _t_frame_cache = std::make_shared(); - for (size_t i = 0; i < frameInd.size(); i++) - { - KeyType key = frameInd[i]; - bool flag = _cache->get(key, _t_frame_cache); - - if (!flag) - { - continue; - } - - // 读取当前H - cv::Mat H1 = cv::Mat(3,3,CV_64FC1,_t_frame_cache->H); - // 与全景图的H相乘 - cv::Mat H = _H_pan * H1; - - // 利用H投影当前帧到全景 - cv::Mat imagetmp(_panImage.size(), CV_8UC3, cv::Scalar(0, 0, 0)); - - // 获取图像数据 - cv::Mat src = getRGBAMatFromGDFrame(_t_frame_cache->_frame_info, _t_frame_cache->_data); - - cv::warpPerspective(src, imagetmp, H, imagetmp.size(), cv::INTER_LINEAR, cv::BORDER_TRANSPARENT); - - cv::Mat mask = cv::Mat::ones(cv::Size(src.cols - 200,src.rows - 200), CV_8UC1) * 255; - cv::Mat warped_mask; - cv::warpPerspective(mask, warped_mask, H, imagetmp.size(), cv::INTER_LINEAR); - imagetmp.copyTo(_panImage, warped_mask); - - // 保存遮罩 - warped_mask.copyTo(_panMask, warped_mask); - - //imshow("mask", _panMask); - //waitKey(1); - - } - - -} bool VideoStitch::ExportGeoPng(std::string dir, std::string name) { @@ -364,7 +309,7 @@ bool VideoStitch::ExportGoogleTile(std::string dir, std::string name) info.box.south = minB; info.box.west = minL; info.box.east = maxL; - info.ind.z = 17; + info.ind.z = 16; _googleProduct.ExportTile(_panImage, info, dir); return 0; diff --git a/stitch/src/Arith_VideoStitch.h b/stitch/src/Arith_VideoStitch.h index 642f08f..c62a6c2 100644 --- a/stitch/src/Arith_VideoStitch.h +++ b/stitch/src/Arith_VideoStitch.h @@ -6,6 +6,7 @@ #include "Arith_BATask.h" #include "FileCache.h" #include "GoogleTile.h" +#include "Arith_FusionMap.h" class VideoStitch:public API_VideoStitch { @@ -23,8 +24,6 @@ public: // 处理帧 SINT32 ProcessFrame(); - // 投影到全景图 - void mapFrame(vector frameInd); // 输出地理产品:kml png全景 bool ExportGeoPng(std::string dir, std::string name); @@ -60,6 +59,9 @@ private: BA_Task* _BATask;//BA + MapFusion* _fusionTask;// 融合模块 + + PanInfo _panPara;//全景图配置 cv::Mat _H_pan;//全景图投影矩阵:从地理系到全景地图 diff --git a/stitch/src/GoogleTile.cpp b/stitch/src/GoogleTile.cpp index 0a51354..a73cc0e 100644 --- a/stitch/src/GoogleTile.cpp +++ b/stitch/src/GoogleTile.cpp @@ -66,7 +66,7 @@ void googleTile::ExportTile(cv::Mat _pan, TileInfo panInfo, std::string dir) { for (size_t j = xStart; j < xEnd; j++) { - TileIndex id = {j,i,17}; + TileIndex id = {j,i,zoom}; TileBox tilebox = GetTileBox(id); // 填充 @@ -126,6 +126,19 @@ void googleTile::ExportTile(cv::Mat _pan, TileInfo panInfo, std::string dir) } +int googleTile::getZoomLevel(float mp) +{ + int nLev = 0; + // 计算单位瓦片的实际覆盖 + int meters_cover = TILE_SIZE * mp; + + int earthLen = 40075017; + + nLev = std::round(std::log2(earthLen / meters_cover)); + + return nLev; +} + TileIndex googleTile::LatLonToTile(double latitude, double longitude, int zoomLevel) { // 将纬度转换为墨卡托投影 diff --git a/stitch/src/GoogleTile.h b/stitch/src/GoogleTile.h index 4216741..1d7dd22 100644 --- a/stitch/src/GoogleTile.h +++ b/stitch/src/GoogleTile.h @@ -31,6 +31,7 @@ struct TileInfo TileBox box; }; +const int TILE_SIZE = 256; class googleTile { @@ -45,10 +46,12 @@ public: // 输出tile void ExportTile(cv::Mat _pan, TileInfo info, std::string dir); -public: - TileIndex LatLonToTile(double latitude, double longitude, int zoomLevel); + // 计算给定分辨率最接近的瓦片等级,mp单位 米/像素 + int getZoomLevel(float mp); + private: + TileIndex LatLonToTile(double latitude, double longitude, int zoomLevel); // 瓦片编号对应的信息 TileBox GetTileBox(TileIndex ind);