You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
5.8 KiB

#include "googleTile.h"
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <fstream>
#include <cmath>
#include <filesystem>
using std::string;
googleTile::googleTile()
{
}
googleTile::~googleTile()
{
}
void googleTile::ExportGeoPng(cv::Mat _pan, TileInfo info, std::string dir, std::string name)
{
// 保存全景图
string png_path = dir + "/" + name + ".png";
cv::imwrite(png_path, _pan);
// 写入kml
string kml_path = dir + "/" + name + ".kml";
std::ofstream kml_file(kml_path);
// 写入 KML 文件的头部
kml_file << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
kml_file << "<kml xmlns=\"http://www.opengis.net/kml/2.2\">" << std::endl;
kml_file << "<Document>" << std::endl;
// 写入 GroundOverlay 元素
kml_file << "<GroundOverlay>" << std::endl;
kml_file << " <name>My Panoramic Image</name>" << std::endl;
kml_file << " <Icon>" << std::endl;
kml_file << " <href>" << name + ".png" << "</href>" << std::endl;
kml_file << " </Icon>" << std::endl;
// 使用四个角点计算 LatLonBox
kml_file << " <LatLonBox>" << std::endl;
kml_file << " <north>" << info.north << "</north>" << std::endl; // 经度范围
kml_file << " <south>" << info.south << "</south>" << std::endl;
kml_file << " <east>" << info.east << "</east>" << std::endl; // 纬度范围
kml_file << " <west>" << info.west << "</west>" << std::endl;
kml_file << " </LatLonBox>" << std::endl;
// 写入 KML 文件的尾部
kml_file << "</GroundOverlay>" << std::endl;
kml_file << "</Document>" << std::endl;
kml_file << "</kml>" << std::endl;
kml_file.close();
}
void googleTile::ExportTile(cv::Mat _pan, TileInfo info, std::string dir, std::string name)
{
}
cv::Point2f googleTile::latLonToGlobal(double lat, double lon)
{
double tileSize = 256.0;
double n = std::pow(2.0, zoom_);
double x = (lon + 180.0) / 360.0 * tileSize * n;
double latRad = lat * CV_PI / 180.0;
double y = (1 - std::log(std::tan(latRad) + 1 / std::cos(latRad)) / CV_PI) / 2 * tileSize * n;
return cv::Point2f(static_cast<float>(x), static_cast<float>(y));
}
std::pair<double, double> googleTile::globalToLatLon(const cv::Point2f& pt)
{
double tileSize = 256.0;
double n = std::pow(2.0, zoom_);
double lon = pt.x / (tileSize * n) * 360.0 - 180.0;
double latRad = std::atan(std::sinh(CV_PI * (1 - 2 * pt.y / (tileSize * n))));
double lat = latRad * 180.0 / CV_PI;
return std::make_pair(lat, lon);
}
cv::Mat googleTile::computeHomography()
{
std::vector<cv::Point2f> srcPts;
std::vector<cv::Point2f> dstPts;
for (const auto& corner : geoCorners_)
{
srcPts.push_back(latLonToGlobal(corner.first, corner.second));
}
dstPts.push_back(cv::Point2f(0.0f, 0.0f));
dstPts.push_back(cv::Point2f(static_cast<float>(image_.cols), 0.0f));
dstPts.push_back(cv::Point2f(static_cast<float>(image_.cols), static_cast<float>(image_.rows)));
dstPts.push_back(cv::Point2f(0.0f, static_cast<float>(image_.rows)));
return cv::getPerspectiveTransform(srcPts, dstPts);
}
void googleTile::generateTiles()
{
//std::filesystem::create_directories(outputDir_);
//cv::Mat H = computeHomography();
//std::vector<cv::Point2f> globalCorners;
//for (const auto& corner : geoCorners_)
//{
// globalCorners.push_back(latLonToGlobal(corner.first, corner.second));
//}
//float minX = globalCorners[0].x, maxX = globalCorners[0].x;
//float minY = globalCorners[0].y, maxY = globalCorners[0].y;
//for (const auto& p : globalCorners)
//{
// minX = std::min(minX, p.x);
// maxX = std::max(maxX, p.x);
// minY = std::min(minY, p.y);
// maxY = std::max(maxY, p.y);
//}
//int tileSize = 256;
//int xTileMin = static_cast<int>(std::floor(minX / tileSize));
//int xTileMax = static_cast<int>(std::floor(maxX / tileSize));
//int yTileMin = static_cast<int>(std::floor(minY / tileSize));
//int yTileMax = static_cast<int>(std::floor(maxY / tileSize));
//std::vector<TileInfo> tileInfos;
//for (int tx = xTileMin; tx <= xTileMax; tx++)
//{
// for (int ty = yTileMin; ty <= yTileMax; ty++)
// {
// std::vector<cv::Point2f> tileGlobalPts = {
// {cv::Point2f(tx * tileSize, ty * tileSize)},
// {cv::Point2f((tx + 1) * tileSize, ty * tileSize)},
// {cv::Point2f((tx + 1) * tileSize, (ty + 1) * tileSize)},
// {cv::Point2f(tx * tileSize, (ty + 1) * tileSize)} };
// std::vector<cv::Point2f> tileImgPts;
// cv::perspectiveTransform(tileGlobalPts, tileImgPts, H);
// //cv::Mat tileTransform = cv::getPerspectiveTransform(tileImgPts, {
// // {0, 0}, {tileSize, 0}, {tileSize, tileSize}, {0, tileSize} });
// cv::Mat tileImg;
// //cv::warpPerspective(image_, tileImg, tileTransform, cv::Size(tileSize, tileSize));
// std::string tileDir = outputDir_ + "/" + std::to_string(zoom_) + "/" + std::to_string(tx);
// std::filesystem::create_directories(tileDir);
// std::string tilePath = tileDir + "/" + std::to_string(ty) + ".png";
// cv::imwrite(tilePath, tileImg);
// tileInfos.push_back({ tx, ty, globalToLatLon({cv::Point2f(tx * tileSize, ty * tileSize)}).first,
// globalToLatLon({cv::Point2f((tx + 1) * tileSize, (ty + 1) * tileSize)}).first,
// globalToLatLon({cv::Point2f((tx + 1) * tileSize, (ty + 1) * tileSize)}).second,
// globalToLatLon({cv::Point2f(tx * tileSize, ty * tileSize)}).second });
// }
//}
//generateKML(tileInfos);
}