|
|
|
|
@ -20,17 +20,18 @@
|
|
|
|
|
#define MKDIR(dir) mkdir(dir, 0777)
|
|
|
|
|
#define ACCESS access
|
|
|
|
|
#endif
|
|
|
|
|
#include <filesystem>
|
|
|
|
|
|
|
|
|
|
using std::string;
|
|
|
|
|
#if (__cplusplus < 201703L)
|
|
|
|
|
#include <experimental/filesystem>
|
|
|
|
|
namespace fs = std::experimental::filesystem;
|
|
|
|
|
#else
|
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "Logger.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <gdal.h>
|
|
|
|
|
#include <gdal_priv.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void saveAsGeoTIFF(const cv::Mat& img, double minL, double maxL, double minB, double maxB, const char* filename);
|
|
|
|
|
#include "Arith_GDALUtils.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -139,7 +140,7 @@ UPanInfo UnderStitch::InitMap(FrameInfo para)
|
|
|
|
|
auto geo_pro_rect = warpRectWithH_2Rect(H0,cv::Size(para.nWidth, para.nHeight));
|
|
|
|
|
|
|
|
|
|
// 计算目标比例(单帧投影后占全景图的0.25)
|
|
|
|
|
float target_ratio = 0.08;
|
|
|
|
|
float target_ratio = 0.2;
|
|
|
|
|
float current_ratio = MAX(geo_pro_rect.width / (target_ratio*panPara.m_pan_width), geo_pro_rect.height / (target_ratio*panPara.m_pan_height));
|
|
|
|
|
|
|
|
|
|
// 调整scale参数
|
|
|
|
|
@ -253,8 +254,8 @@ UPanInfo UnderStitch::InitMap_SCAN(FrameInfo para, float ptRange)
|
|
|
|
|
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.3;
|
|
|
|
|
float N_range = (max_y - min_y) * 1.3;
|
|
|
|
|
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;
|
|
|
|
|
@ -390,6 +391,8 @@ void UnderStitch::run_test(FrameInfo para)
|
|
|
|
|
UPanInfo UnderStitch::Init(FrameInfo info)
|
|
|
|
|
{
|
|
|
|
|
// 以向下零位初始化
|
|
|
|
|
info.craft.stAtt.fPitch = 0;
|
|
|
|
|
info.craft.stAtt.fRoll = 0;
|
|
|
|
|
info.servoInfo.fServoPt = 0;
|
|
|
|
|
|
|
|
|
|
// 设置拼接原点:地理计算的基准点
|
|
|
|
|
@ -397,7 +400,7 @@ UPanInfo UnderStitch::Init(FrameInfo info)
|
|
|
|
|
|
|
|
|
|
// 摆扫45度初始化地图尺寸
|
|
|
|
|
#ifdef SCAN_MODE
|
|
|
|
|
_panPara = InitMap_SCAN(info,42);
|
|
|
|
|
_panPara = InitMap_SCAN(info,15);
|
|
|
|
|
#else
|
|
|
|
|
// 常规初始化全景图(基于内存限制)
|
|
|
|
|
_panPara = InitMap(info);
|
|
|
|
|
@ -543,6 +546,8 @@ SINT32 UnderStitch::Run(GD_VIDEO_FRAME_S frame, FrameInfo para)
|
|
|
|
|
printf("--------------------\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//// 视频帧筛选
|
|
|
|
|
if (!FilterFrame(para))
|
|
|
|
|
{
|
|
|
|
|
@ -558,6 +563,7 @@ SINT32 UnderStitch::Run(GD_VIDEO_FRAME_S frame, FrameInfo para)
|
|
|
|
|
RtK rtk;
|
|
|
|
|
cv::Mat H_geo = _GeoSolver->findHomography(para, rtk);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_frameRtkAll[para.nFrmID] = rtk;
|
|
|
|
|
_frameGeoHAll[para.nFrmID] = H_geo;
|
|
|
|
|
|
|
|
|
|
@ -566,19 +572,28 @@ SINT32 UnderStitch::Run(GD_VIDEO_FRAME_S frame, FrameInfo para)
|
|
|
|
|
cv::Size(_panPara.m_pan_width, _panPara.m_pan_height)))
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
cv::Mat pan_ds;
|
|
|
|
|
Mat pan_rgb_ds(cv::Size(panImage.cols / 2, panImage.rows / 2),CV_8UC3);
|
|
|
|
|
// 输出局部全景图tiff
|
|
|
|
|
if (_config.bOutLocalPanGeoTIFF)
|
|
|
|
|
{
|
|
|
|
|
// 计算经纬度范围
|
|
|
|
|
auto P1 = getBLHFromPan(cv::Point2f(0, 0), _H_pan);
|
|
|
|
|
auto P2 = getBLHFromPan(cv::Point2f(panImage.cols, 0), _H_pan);
|
|
|
|
|
auto P3 = getBLHFromPan(cv::Point2f(panImage.cols, panImage.rows), _H_pan);
|
|
|
|
|
auto P4 = getBLHFromPan(cv::Point2f(0, panImage.rows), _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);
|
|
|
|
|
|
|
|
|
|
cv::resize(panImage, pan_ds, cv::Size(panImage.cols / 2, panImage.rows / 2));
|
|
|
|
|
cv::cvtColor(pan_ds, pan_rgb_ds, cv::COLOR_BGRA2BGR);
|
|
|
|
|
imwrite(_outDir + "/" + _filename + std::to_string(_lastFrameKey) + "_z" + "_pan.png", pan_rgb_ds);
|
|
|
|
|
// 保存为GeoTIFF,使用经纬度范围
|
|
|
|
|
char filename[1024] = {0};
|
|
|
|
|
sprintf(filename, "%s/PAN_%s_%04d.tif", _outDir.c_str(), _filename.c_str(), para.nFrmID);
|
|
|
|
|
saveAsGeoTIFF(panImage, minL, maxL, minB, maxB, filename);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//OptAndOutCurrPan(_baCurrViewKey);
|
|
|
|
|
|
|
|
|
|
// cv::resize(panImage, pan_ds, cv::Size(panImage.cols / 2, panImage.rows / 2));
|
|
|
|
|
//cv::cvtColor(pan_ds, pan_rgb_ds, cv::COLOR_BGRA2BGR);
|
|
|
|
|
// imwrite(_outDir + "/" + _filename + std::to_string(_lastFrameKey) + "_z" + "_pan_AFTER.png", pan_rgb_ds);
|
|
|
|
|
|
|
|
|
|
LOG_INFO("Frame {} is out of pan view, reinitializing projection parameters", para.nFrmID);
|
|
|
|
|
|
|
|
|
|
@ -600,7 +615,10 @@ SINT32 UnderStitch::Run(GD_VIDEO_FRAME_S frame, FrameInfo para)
|
|
|
|
|
// 重新初始化投影参数
|
|
|
|
|
int shift_x = 0, shift_y = 0;
|
|
|
|
|
|
|
|
|
|
// 以向下初始化
|
|
|
|
|
|
|
|
|
|
// 以向下零位初始化
|
|
|
|
|
para.craft.stAtt.fPitch = 0;
|
|
|
|
|
para.craft.stAtt.fRoll = 0;
|
|
|
|
|
para.servoInfo.fServoPt = 0;
|
|
|
|
|
_panPara = ShiftMap(para, shift_x, shift_y);
|
|
|
|
|
|
|
|
|
|
@ -649,6 +667,21 @@ SINT32 UnderStitch::Run(GD_VIDEO_FRAME_S frame, FrameInfo para)
|
|
|
|
|
_googleProduct.ExportGeoPng(Orth_Image, info, _outDir + "/FrameTile");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 输出tiff
|
|
|
|
|
if(_config.bOutFrameGeoTIFF)
|
|
|
|
|
{
|
|
|
|
|
TileInfo info = { 0 };
|
|
|
|
|
cv::Mat Orth_Image = getOrthImage(src, para, info);
|
|
|
|
|
|
|
|
|
|
// 保存为GeoTIFF,使用经纬度范围
|
|
|
|
|
string name = _filename + "_" + std::to_string(para.nFrmID) + ".tif";
|
|
|
|
|
|
|
|
|
|
saveAsGeoTIFF(Orth_Image, info.boxLatLon.west, info.boxLatLon.east,
|
|
|
|
|
info.boxLatLon.south, info.boxLatLon.north, (_outDir + "/FrameTiff/" + name).c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 投影帧到全景
|
|
|
|
|
_MapBlender->FrameMap(src, H_geo, _H_pan);
|
|
|
|
|
|
|
|
|
|
@ -666,6 +699,8 @@ SINT32 UnderStitch::Run(GD_VIDEO_FRAME_S frame, FrameInfo para)
|
|
|
|
|
"BA_Optimization"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOG_INFO("stitch total times:{}", sw.elapsed_ms());
|
|
|
|
|
@ -734,20 +769,40 @@ bool UnderStitch::FilterFrame(FrameInfo para)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 扫描角过大,跳过
|
|
|
|
|
if (ABS(para.servoInfo.fServoPt) > 40)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
RtK rtk;
|
|
|
|
|
cv::Mat H = _GeoSolver->findHomography(para,rtk);
|
|
|
|
|
|
|
|
|
|
// 计算光轴综合指向与地面法线夹角
|
|
|
|
|
// rtk.R是从ENG(东北地)到相机系的旋转矩阵
|
|
|
|
|
// 光轴在相机系中是(0,0,1),转换到ENG系后是rtk.R的第三列
|
|
|
|
|
// 地面法线在ENG系中是(0,0,1)
|
|
|
|
|
// 点积 = rtk.R[2][2],即旋转矩阵的(2,2)元素
|
|
|
|
|
double cos_angle = rtk.R.at<double>(2, 2);
|
|
|
|
|
// 限制在有效范围内,避免数值误差
|
|
|
|
|
cos_angle = std::max(-1.0, std::min(1.0, cos_angle));
|
|
|
|
|
double angle_rad = acos(cos_angle);
|
|
|
|
|
double angle_deg = angle_rad * 180.0 / CV_PI;
|
|
|
|
|
//LOG_INFO("Optical axis angle with ground normal: {:.2f} deg", angle_deg);
|
|
|
|
|
|
|
|
|
|
// // 扫描角过大,跳过
|
|
|
|
|
// if (ABS(para.servoInfo.fServoPt) > 40)
|
|
|
|
|
// {
|
|
|
|
|
// return false;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// // 姿态不稳定,跳过
|
|
|
|
|
// if(ABS(para.craft.stAtt.fRoll) > 5)
|
|
|
|
|
// {
|
|
|
|
|
// return false;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// 姿态不稳定,跳过
|
|
|
|
|
if(ABS(para.craft.stAtt.fRoll) > 5)
|
|
|
|
|
// 光轴偏离地面法线过大,跳过
|
|
|
|
|
if(ABS(angle_deg) > 45)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取当前帧的Geo覆盖
|
|
|
|
|
cv::Mat H = _GeoSolver->findHomography(para);
|
|
|
|
|
std::vector<cv::Point2f> currCorners = warpRectWithH(H, cv::Size(para.nWidth, para.nHeight));
|
|
|
|
|
|
|
|
|
|
// 获取上一帧的Geo覆盖
|
|
|
|
|
@ -782,7 +837,7 @@ bool UnderStitch::FilterFrame(FrameInfo para)
|
|
|
|
|
bool UnderStitch::TriggerBA(FrameInfo para)
|
|
|
|
|
{
|
|
|
|
|
// 1. 固定帧间隔触发
|
|
|
|
|
const int FIXED_FRAME_INTERVAL = 25;
|
|
|
|
|
const int FIXED_FRAME_INTERVAL = 5;
|
|
|
|
|
if (_totalFrameCnt % FIXED_FRAME_INTERVAL == 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_INFO("TriggerBA: Fixed frame interval {} reached",FIXED_FRAME_INTERVAL);
|
|
|
|
|
@ -1018,7 +1073,7 @@ SINT32 UnderStitch::ReceiveFrame(GD_VIDEO_FRAME_S img, FrameInfo para)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 保持滑动窗口大小
|
|
|
|
|
const size_t WINDOW_SIZE = 60; // 滑动窗口大小
|
|
|
|
|
const size_t WINDOW_SIZE = 10; // 滑动窗口大小
|
|
|
|
|
if (_baWindowKey.size() > WINDOW_SIZE)
|
|
|
|
|
{
|
|
|
|
|
_baWindowKey.erase(_baWindowKey.begin());
|
|
|
|
|
@ -1113,8 +1168,8 @@ cv::Mat UnderStitch::getOrthImage(cv::Mat src, FrameInfo para,TileInfo& tile)
|
|
|
|
|
tile.boxLatLon.south = minB;
|
|
|
|
|
tile.boxLatLon.west = minL;
|
|
|
|
|
tile.boxLatLon.east = maxL;
|
|
|
|
|
tile.tileName = _filename + std::to_string(para.nFrmID);
|
|
|
|
|
tile.href = _filename + std::to_string(para.nFrmID) + ".png";
|
|
|
|
|
tile.tileName = _filename + "_"+std::to_string(para.nFrmID);
|
|
|
|
|
tile.href = tile.tileName + ".png";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1199,7 +1254,7 @@ cv::Mat UnderStitch::getHomography(FrameInfo info)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void exportGeoTIFF(cv::Mat src,FrameInfo info, const char* filename)
|
|
|
|
|
void exportFrameGeoTIFF(cv::Mat src,FrameInfo info, const char* filename)
|
|
|
|
|
{
|
|
|
|
|
TransPitch(info);
|
|
|
|
|
|
|
|
|
|
@ -1253,138 +1308,3 @@ void exportGeoTIFF(cv::Mat src,FrameInfo info, const char* filename)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void saveAsGeoTIFF(const cv::Mat& img, double minL, double maxL, double minB, double maxB, const char* filename)
|
|
|
|
|
{
|
|
|
|
|
// 注册GDAL驱动
|
|
|
|
|
GDALAllRegister();
|
|
|
|
|
|
|
|
|
|
// 检查图像类型和通道数
|
|
|
|
|
if (img.empty()) {
|
|
|
|
|
std::cerr << "Error: Empty image, cannot save GeoTIFF" << std::endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nBands = img.channels();
|
|
|
|
|
int width = img.cols;
|
|
|
|
|
int height = img.rows;
|
|
|
|
|
|
|
|
|
|
// 确定GDAL数据类型
|
|
|
|
|
GDALDataType dataType;
|
|
|
|
|
if (img.depth() == CV_8U) {
|
|
|
|
|
dataType = GDT_Byte;
|
|
|
|
|
} else if (img.depth() == CV_16U) {
|
|
|
|
|
dataType = GDT_UInt16;
|
|
|
|
|
} else if (img.depth() == CV_32F) {
|
|
|
|
|
dataType = GDT_Float32;
|
|
|
|
|
} else {
|
|
|
|
|
std::cerr << "Error: Unsupported image depth" << std::endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建输出文件名(基于帧ID和时间戳)
|
|
|
|
|
std::string outputPath = string(filename);
|
|
|
|
|
|
|
|
|
|
// 创建GeoTIFF驱动
|
|
|
|
|
GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
|
|
|
|
|
if (poDriver == nullptr) {
|
|
|
|
|
std::cerr << "Error: GTiff driver not available" << std::endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建数据集
|
|
|
|
|
char** papszOptions = nullptr;
|
|
|
|
|
papszOptions = CSLSetNameValue(papszOptions, "COMPRESS", "LZW");
|
|
|
|
|
papszOptions = CSLSetNameValue(papszOptions, "TILED", "YES");
|
|
|
|
|
|
|
|
|
|
GDALDataset* poDataset = poDriver->Create(outputPath.c_str(), width, height, nBands, dataType, papszOptions);
|
|
|
|
|
CSLDestroy(papszOptions);
|
|
|
|
|
|
|
|
|
|
if (poDataset == nullptr) {
|
|
|
|
|
std::cerr << "Error: Failed to create GeoTIFF file: " << outputPath << std::endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 计算GeoTransform参数
|
|
|
|
|
// 根据经纬度范围计算像素分辨率(度/像素)
|
|
|
|
|
double pixelSizeX = (maxL - minL) / width; // 经度方向像素分辨率
|
|
|
|
|
double pixelSizeY = (minB - maxB) / height; // 纬度方向像素分辨率(注意:图像Y轴向下,所以是minB-maxB)
|
|
|
|
|
|
|
|
|
|
// 设置GeoTransform (6个参数)
|
|
|
|
|
double adfGeoTransform[6];
|
|
|
|
|
adfGeoTransform[0] = minL; // 左上角经度(最小经度)
|
|
|
|
|
adfGeoTransform[1] = pixelSizeX; // 经度方向像素分辨率
|
|
|
|
|
adfGeoTransform[2] = 0.0; // 旋转参数(通常为0)
|
|
|
|
|
adfGeoTransform[3] = maxB; // 左上角纬度(最大纬度,因为图像Y轴向下)
|
|
|
|
|
adfGeoTransform[4] = 0.0; // 旋转参数(通常为0)
|
|
|
|
|
adfGeoTransform[5] = pixelSizeY; // 纬度方向像素分辨率(负值,因为Y轴向下)
|
|
|
|
|
|
|
|
|
|
poDataset->SetGeoTransform(adfGeoTransform);
|
|
|
|
|
|
|
|
|
|
// 设置WGS84投影
|
|
|
|
|
const char* pszWKT = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
|
|
|
|
|
poDataset->SetProjection(pszWKT);
|
|
|
|
|
|
|
|
|
|
// 将OpenCV Mat数据写入GDAL数据集
|
|
|
|
|
// 如果图像不是8位,先转换为8位
|
|
|
|
|
cv::Mat imgToSave;
|
|
|
|
|
if (img.depth() != CV_8U) {
|
|
|
|
|
if (img.depth() == CV_16U) {
|
|
|
|
|
img.convertTo(imgToSave, CV_8U, 1.0 / 256.0);
|
|
|
|
|
} else if (img.depth() == CV_32F) {
|
|
|
|
|
img.convertTo(imgToSave, CV_8U, 255.0);
|
|
|
|
|
} else {
|
|
|
|
|
img.convertTo(imgToSave, CV_8U);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
imgToSave = img;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果图像是多通道,需要分离通道
|
|
|
|
|
std::vector<cv::Mat> channels;
|
|
|
|
|
if (nBands > 1) {
|
|
|
|
|
cv::split(imgToSave, channels);
|
|
|
|
|
} else {
|
|
|
|
|
channels.push_back(imgToSave);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 写入每个通道
|
|
|
|
|
for (int band = 0; band < nBands; band++) {
|
|
|
|
|
GDALRasterBand* poBand = poDataset->GetRasterBand(band + 1);
|
|
|
|
|
|
|
|
|
|
// 设置nodata值(对于8位图像,通常使用0或255,这里使用0)
|
|
|
|
|
double noDataValue = 0.0;
|
|
|
|
|
poBand->SetNoDataValue(noDataValue);
|
|
|
|
|
|
|
|
|
|
cv::Mat bandMat = channels[band];
|
|
|
|
|
|
|
|
|
|
// 如果数据不连续,先复制为连续存储
|
|
|
|
|
if (!bandMat.isContinuous()) {
|
|
|
|
|
bandMat = bandMat.clone();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 使用RasterIO写入数据
|
|
|
|
|
// 参数说明:
|
|
|
|
|
// - nPixelSpace: 每个像素的字节数(单通道8位=1)
|
|
|
|
|
// - nLineSpace: 每行的字节数(连续存储时=width)
|
|
|
|
|
int pixelSpace = 1; // 每个像素1字节
|
|
|
|
|
int lineSpace = bandMat.step[0]; // 使用Mat的实际step
|
|
|
|
|
|
|
|
|
|
CPLErr err = poBand->RasterIO(GF_Write, 0, 0, width, height,
|
|
|
|
|
(void*)bandMat.data, width, height,
|
|
|
|
|
GDT_Byte, pixelSpace, lineSpace);
|
|
|
|
|
if (err != CE_None) {
|
|
|
|
|
std::cerr << "Error: Failed to write band " << (band + 1) << ": " << CPLGetLastErrorMsg() << std::endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 关闭数据集
|
|
|
|
|
GDALClose(poDataset);
|
|
|
|
|
|
|
|
|
|
std::cout << "GeoTIFF saved successfully: " << outputPath << std::endl;
|
|
|
|
|
std::cout << "GeoTransform: [" << adfGeoTransform[0] << ", " << adfGeoTransform[1]
|
|
|
|
|
<< ", " << adfGeoTransform[2] << ", " << adfGeoTransform[3]
|
|
|
|
|
<< ", " << adfGeoTransform[4] << ", " << adfGeoTransform[5] << "]" << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|