|
|
|
#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);
|
|
|
|
}
|