保留原始分辨率的地图初始化。耗时增长

main
wangchongwu 4 weeks ago
parent e69c9d1cde
commit 9387fc3586

@ -26,6 +26,7 @@
using namespace std;
using namespace cv;
@ -170,16 +171,130 @@ UPanInfo UnderStitch::InitMap(FrameInfo para)
return panPara;
}
double getLocalScaleFromH(const cv::Mat& H, double u, double v)
{
CV_Assert(H.rows == 3 && H.cols == 3 && H.type() == CV_64F);
// 提取矩阵元素
double h00 = H.at<double>(0, 0), h01 = H.at<double>(0, 1), h02 = H.at<double>(0, 2);
double h10 = H.at<double>(1, 0), h11 = H.at<double>(1, 1), h12 = H.at<double>(1, 2);
double h20 = H.at<double>(2, 0), h21 = H.at<double>(2, 1), h22 = H.at<double>(2, 2);
// 原始点的齐次坐标
double X = h00 * u + h01 * v + h02;
double Y = h10 * u + h11 * v + h12;
double W = h20 * u + h21 * v + h22;
double W2 = (std::abs(W) > 1e-12) ? W * W : 1e-12;
// 解析求导 —— Jacobian
double dx_du = (h00 * W - h20 * X) / W2;
double dx_dv = (h01 * W - h21 * X) / W2;
double dy_du = (h10 * W - h20 * Y) / W2;
double dy_dv = (h11 * W - h21 * Y) / W2;
// 两个方向的放缩比例(米 / 像素)
double sx = std::hypot(dx_du, dy_du);
double sy = std::hypot(dx_dv, dy_dv);
// 返回平均尺度
return 0.5 * (sx + sy);
}
UPanInfo UnderStitch::InitMap_SCAN(FrameInfo para, float ptRange)
{
UPanInfo panPara = { 0 };
// 地理几何计算
RtK SE3;
cv::Mat H0 = _GeoSolver->findHomography(para, SE3);
// 计算下视中心的地理坐标
para.servoInfo.fServoPt = 0;
cv::Point2f ct_geo = warpPointWithH(H0, cv::Point2f(para.nWidth / 2, para.nHeight / 2));
// 下视最大分辨率估计 m/p
double scale_max = getLocalScaleFromH(H0, para.nWidth / 2, para.nHeight / 2);
// 计算扫描边界的地理坐标
para.servoInfo.fServoPt = -ptRange;
cv::Point2f ct_geo_left = warpPointWithH(_GeoSolver->findHomography(para, SE3), cv::Point2f(para.nWidth / 2, para.nHeight / 2));
para.servoInfo.fServoPt = ptRange;
cv::Point2f ct_geo_right = warpPointWithH(_GeoSolver->findHomography(para, SE3), cv::Point2f(para.nWidth / 2, para.nHeight / 2));
// 载体速度矢量以飞行15s计算载体速度speed = 80m/s*15 = 2400m
double yaw_RAD = para.craft.stAtt.fYaw / 180 * 3.14159;
double dx = 1200 * std::sin(yaw_RAD);
double dy = 1200 * std::cos(yaw_RAD);
cv::Point2f ct_geo_left_fly = cv::Point2f(ct_geo_left.x + dx, ct_geo_left.y + dy);
cv::Point2f ct_geo_right_fly = cv::Point2f(ct_geo_right.x + dx, ct_geo_right.y + dy);
// 计算下个全景地理中心和范围
float min_x = min(min(ct_geo_left.x, ct_geo_right.x), min(ct_geo_left_fly.x, ct_geo_right_fly.x));
float max_x = max(max(ct_geo_left.x, ct_geo_right.x), max(ct_geo_left_fly.x, ct_geo_right_fly.x));
float min_y = min(min(ct_geo_left.y, ct_geo_right.y), min(ct_geo_left_fly.y, ct_geo_right_fly.y));
float max_y = max(max(ct_geo_left.y, ct_geo_right.y), max(ct_geo_left_fly.y, ct_geo_right_fly.y));
float E_range = (max_x - min_x) * 1.2;
float N_range = (max_y - min_y) * 1.2;
// 不损失分辨率的全景图尺寸
panPara.m_pan_width = E_range / scale_max;
panPara.m_pan_height = N_range / scale_max;
// 救救内存
if (panPara.m_pan_width > 12000 || panPara.m_pan_height > 12000)
{
scale_max = E_range / 12000;
panPara.m_pan_width = E_range / scale_max;
panPara.m_pan_height = N_range / scale_max;
}
panPara.scale = 1.0/scale_max;
// 重新计算投影矩阵
cv::Mat mapH0 = getAffineFromGeo2Pan(panPara);
auto cur = warpPointWithH(mapH0, ct_geo);
// 计算平移到全景图固定点的平移量
int planX = panPara.m_pan_width / 2;
int planY = panPara.m_pan_height / 2;
panPara.map_shiftX += planX - (cur.x);
panPara.map_shiftY += planY - (cur.y);
// 获取全景图的投影矩阵
_H_pan = getAffineFromGeo2Pan(panPara);
// 计算全景图瓦片相关
auto P1 = getBLHFromPan(cv::Point2f(0, 0), _H_pan);
auto P2 = getBLHFromPan(cv::Point2f(panPara.m_pan_width, 0), _H_pan);
auto P3 = getBLHFromPan(cv::Point2f(panPara.m_pan_width, panPara.m_pan_height), _H_pan);
auto P4 = getBLHFromPan(cv::Point2f(0, panPara.m_pan_height), _H_pan);
auto minL = min(min(min(P1.L, P2.L), P3.L), P4.L);
auto maxL = max(max(max(P1.L, P2.L), P3.L), P4.L);
auto minB = min(min(min(P1.B, P2.B), P3.B), P4.B);
auto maxB = max(max(max(P1.B, P2.B), P3.B), P4.B);
_panTile.boxLatLon.north = maxB;
_panTile.boxLatLon.south = minB;
_panTile.boxLatLon.west = minL;
_panTile.boxLatLon.east = maxL;
_panTile.ind.z = _googleProduct.ZoomLevel(panPara.scale);
// 生成瓦片划分
_taskTilesVec = _googleProduct.CalcTileOverlayVec(_panTile, panPara.m_pan_width, panPara.m_pan_height);
return panPara;
return UPanInfo();
}
UPanInfo UnderStitch::ShiftMap(FrameInfo para,int& shift_x,int& shift_y)
@ -241,11 +356,13 @@ UPanInfo UnderStitch::Init(FrameInfo info)
// 设置拼接原点:地理计算的基准点
_GeoSolver->SetOriginPoint(info);
// 初始化全景图
_panPara = InitMap(info);
// 摆扫45度初始化地图尺寸
//_panPara = InitMap_SCAN(info,45);
#ifdef SCAN_MODE
_panPara = InitMap_SCAN(info,45);
#else
// 常规初始化全景图(基于内存限制)
_panPara = InitMap(info);
#endif
// 创建blender
_MapBlender = new MapBlend(_cache, _panPara);
@ -343,20 +460,18 @@ SINT32 UnderStitch::Run(GD_VIDEO_FRAME_S frame, FrameInfo para)
_googleProduct.ExportTileSet(mat_pan, mat_mask, tilesvec, outdirpath, filename);
}, "ExportTileSet");
// _googleProduct.ExportTileSet(panImage, panMask, _taskTilesVec, _outDir, _filename + std::to_string(_lastFrameKey));
// 重新初始化投影参数
int shift_x = 0, shift_y = 0;
// 以向下初始化
para.servoInfo.fServoPt = 0;
_panPara = ShiftMap(para, shift_x, shift_y);
// 清空全景视场
_MapBlender->ClearPan();
// 将BatchMap操作放入线程池中后台处理
_threadPool.commit([this, recvFrameKeys=_recvFrameKey, h_pan=_H_pan, Hgeos = _frameGeoHAll]() {
_MapBlender->BatchMapWithH(recvFrameKeys, h_pan, Hgeos);
@ -384,6 +499,7 @@ SINT32 UnderStitch::Run(GD_VIDEO_FRAME_S frame, FrameInfo para)
// 投影帧到全景
_MapBlender->FrameMap(src, H_geo, _H_pan);
// 预处理+缓存
ReceiveFrame(frame, para);

@ -13,6 +13,10 @@
#include "Logger.h"
// 定义扫描模式,使用扫描专用的拼接地图策略
#define SCAN_MODE
// 关键帧间邻接信息
struct EdgeInfo
{

@ -46,9 +46,10 @@ void googleTile::ExportGeoPng(cv::Mat _pan, TileInfo info, std::string dir)
}
#include "Log/Logger.h"
#include "utils/Arith_timer.h"
void googleTile::ExportTileSet(cv::Mat _pan, cv::Mat _panMask, vector<TileInfo> taskTilesVec, std::string dir,std::string fileString)
{
stopWatch sw;
int panWidth = _pan.cols;
int panHeight = _pan.rows;
@ -57,8 +58,7 @@ void googleTile::ExportTileSet(cv::Mat _pan, cv::Mat _panMask, vector<TileInfo>
// 过滤掉无效瓦片
vector<TileInfo> vaildTilesVec;
for (size_t i = 0; i < taskTilesVec.size(); i++)
for (int i = 0; i < taskTilesVec.size(); i++)
{
TileInfo tile = taskTilesVec[i];
@ -120,10 +120,13 @@ void googleTile::ExportTileSet(cv::Mat _pan, cv::Mat _panMask, vector<TileInfo>
}
LOG_INFO("taskTilesVec : {}{}", fileString, taskTilesVec.size());
// 输出KML
WriteKml(vaildTilesVec,dir + "/" + fileString + "_z" + std::to_string(zoom) + ".kml");
LOG_INFO("ExportTileSet TIME:{}", sw.elapsed_ms());
}
void googleTile::ExportOneTile(cv::Mat _pan, TileInfo tile, std::string dir, std::string fileString)

@ -2,5 +2,5 @@
#pragma once
#include <string>
std::string BUILD_TIME = "BUILD_TIME 2025_11_10-17.19.53";
std::string BUILD_TIME = "BUILD_TIME 2025_11_11-09.47.45";
std::string VERSION = "BUILD_VERSION 1.0.1";

@ -135,7 +135,7 @@ void ProcessVL(string filePath)
mat_pan = cv::Mat(pan.u32Height, pan.u32Width, CV_8UC4, pan.u64VirAddr[0]);
output.open("output.mp4", VideoWriter::fourcc('M', 'P', '4', 'V'), 50, Size(pan.u32Width / 8, pan.u32Height / 8), true);
output.open("output.mp4", VideoWriter::fourcc('M', 'P', '4', 'V'), 50, Size(pan.u32Width / 16, pan.u32Height / 16), true);
if (!output.isOpened())
{
cout << "打开视频失败" << endl;
@ -160,8 +160,8 @@ void ProcessVL(string filePath)
}
Mat pan_ds;
Mat pan_rgb_ds(cv::Size(mat_pan.cols / 8, mat_pan.rows / 8),CV_8UC3);
cv::resize(mat_pan, pan_ds, cv::Size(mat_pan.cols / 8, mat_pan.rows / 8));
Mat pan_rgb_ds(cv::Size(mat_pan.cols / 16, mat_pan.rows / 16),CV_8UC3);
cv::resize(mat_pan, pan_ds, cv::Size(mat_pan.cols / 16, mat_pan.rows / 16));
cv::cvtColor(pan_ds, pan_rgb_ds, cv::COLOR_BGRA2BGR);

Loading…
Cancel
Save