|
|
@ -9,9 +9,9 @@
|
|
|
|
using namespace std;
|
|
|
|
using namespace std;
|
|
|
|
using namespace cv;
|
|
|
|
using namespace cv;
|
|
|
|
|
|
|
|
|
|
|
|
API_UnderStitch* API_UnderStitch::Create(SINT32 nWidth, SINT32 nHeight)
|
|
|
|
API_UnderStitch* API_UnderStitch::Create(std::string cachedir)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return new UnderStitch(nWidth,nHeight);
|
|
|
|
return new UnderStitch(cachedir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -21,14 +21,15 @@ void API_UnderStitch::Destroy(API_UnderStitch* obj)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UnderStitch::UnderStitch(SINT32 nWidth, SINT32 nHeight)
|
|
|
|
UnderStitch::UnderStitch(std::string cachedir)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// 创建缓存对象
|
|
|
|
|
|
|
|
_cache = new FileCache<FrameCache>(50, cachedir);
|
|
|
|
|
|
|
|
|
|
|
|
_GeoSolver = new GeoSolver();
|
|
|
|
_GeoSolver = new GeoSolver();
|
|
|
|
|
|
|
|
|
|
|
|
_FeaMatcher = new FeatureMatcher(DetectorType::SIFT, MatcherType::FLANN);
|
|
|
|
_FeaMatcher = new FeatureMatcher(DetectorType::SIFT, MatcherType::FLANN);
|
|
|
|
|
|
|
|
|
|
|
|
_cache = new FileCache<FrameCache>(50,"./cache");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_BATask = new BA_Task(_cache);
|
|
|
|
_BATask = new BA_Task(_cache);
|
|
|
|
|
|
|
|
|
|
|
|
_BlendTask = new MapBlend(_cache);
|
|
|
|
_BlendTask = new MapBlend(_cache);
|
|
|
@ -63,9 +64,8 @@ UPanInfo UnderStitch::InitMap(FrameInfo info)
|
|
|
|
UPanInfo panPara = { 0 };
|
|
|
|
UPanInfo panPara = { 0 };
|
|
|
|
panPara.m_pan_width = MIN(info.nWidth * 5,2000);//全景宽
|
|
|
|
panPara.m_pan_width = MIN(info.nWidth * 5,2000);//全景宽
|
|
|
|
panPara.m_pan_height = MIN(info.nWidth * 5,2000);//全景高
|
|
|
|
panPara.m_pan_height = MIN(info.nWidth * 5,2000);//全景高
|
|
|
|
panPara.scale = gsd /5;//比例尺,1m = ?pix
|
|
|
|
panPara.scale = gsd / 2;//比例尺,1m = ?pix
|
|
|
|
|
|
|
|
|
|
|
|
int zoom = _googleProduct.getZoomLevel(panPara.scale);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 直接无平移解算
|
|
|
|
// 直接无平移解算
|
|
|
|
cv::Mat H_0 = getAffineFromGeo2Pan(panPara);
|
|
|
|
cv::Mat H_0 = getAffineFromGeo2Pan(panPara);
|
|
|
@ -82,6 +82,30 @@ UPanInfo UnderStitch::InitMap(FrameInfo info)
|
|
|
|
// 获取全景图的投影矩阵,全景图配置更新前保持不变
|
|
|
|
// 获取全景图的投影矩阵,全景图配置更新前保持不变
|
|
|
|
_H_pan = getAffineFromGeo2Pan(panPara);
|
|
|
|
_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 panPara;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -90,6 +114,7 @@ UPanInfo UnderStitch::InitMap(FrameInfo info)
|
|
|
|
|
|
|
|
|
|
|
|
UPanInfo UnderStitch::Init(FrameInfo info)
|
|
|
|
UPanInfo UnderStitch::Init(FrameInfo info)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
_panPara = InitMap(info);
|
|
|
|
_panPara = InitMap(info);
|
|
|
|
|
|
|
|
|
|
|
|
_panImage = cv::Mat::zeros(_panPara.m_pan_height, _panPara.m_pan_width, CV_8UC4);
|
|
|
|
_panImage = cv::Mat::zeros(_panPara.m_pan_height, _panPara.m_pan_width, CV_8UC4);
|
|
|
@ -100,6 +125,15 @@ UPanInfo UnderStitch::Init(FrameInfo info)
|
|
|
|
return _panPara;
|
|
|
|
return _panPara;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UnderStitch::SetOutput(std::string filename, std::string outdir)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_filename = filename;
|
|
|
|
|
|
|
|
_outDir = outdir;
|
|
|
|
|
|
|
|
_kmlPath = _outDir + "/" + _filename + ".kml";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//BYTE8 UnderStitch::GeoStitch(GD_VIDEO_FRAME_S img, FrameInfo para)
|
|
|
|
//BYTE8 UnderStitch::GeoStitch(GD_VIDEO_FRAME_S img, FrameInfo para)
|
|
|
|
//{
|
|
|
|
//{
|
|
|
|
// Proj t_Proj = _GeoStitcher->AnlayseTform(para);
|
|
|
|
// Proj t_Proj = _GeoStitcher->AnlayseTform(para);
|
|
|
@ -168,19 +202,76 @@ BYTE8 UnderStitch::GeoStitch(GD_VIDEO_FRAME_S img, FrameInfo para)
|
|
|
|
|
|
|
|
|
|
|
|
cv::warpPerspective(src, imagetmp, H, imagetmp.size(), cv::INTER_LINEAR, cv::BORDER_TRANSPARENT);
|
|
|
|
cv::warpPerspective(src, imagetmp, H, imagetmp.size(), cv::INTER_LINEAR, cv::BORDER_TRANSPARENT);
|
|
|
|
|
|
|
|
|
|
|
|
cv::Mat mask = cv::Mat::ones(src.size(), CV_8UC1) * 255;
|
|
|
|
cv::Mat mask = cv::Mat::ones(src.size(), CV_8UC1);
|
|
|
|
|
|
|
|
|
|
|
|
mask.colRange(0, 200).setTo(0);
|
|
|
|
mask.colRange(0, 200).setTo(0);
|
|
|
|
|
|
|
|
|
|
|
|
cv::Mat warped_mask;
|
|
|
|
cv::Mat warped_mask;
|
|
|
|
cv::warpPerspective(mask, warped_mask, H, imagetmp.size(), cv::INTER_LINEAR);
|
|
|
|
cv::warpPerspective(mask, warped_mask, H, imagetmp.size(), cv::INTER_LINEAR);
|
|
|
|
imagetmp.copyTo(_panImage, warped_mask);
|
|
|
|
imagetmp.copyTo(_panImage, warped_mask);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 覆盖区域掩码更新
|
|
|
|
|
|
|
|
_panMask = _panMask | warped_mask;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 生产快拼瓦片
|
|
|
|
|
|
|
|
CutTileRealTime();
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UnderStitch::CutTileRealTime()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 在4倍降采样图上计算瓦片覆盖情况
|
|
|
|
|
|
|
|
int downSampleR = 4;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::Mat panMasksmall;
|
|
|
|
|
|
|
|
cv::resize(_panMask, panMasksmall, cv::Size(_panMask.cols / downSampleR, _panMask.rows / downSampleR));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算覆盖图的积分图
|
|
|
|
|
|
|
|
cv::Mat integralMask;
|
|
|
|
|
|
|
|
cv::integral(panMasksmall, integralMask, CV_32S);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 遍历已经在初始化阶段得到的瓦片划分
|
|
|
|
|
|
|
|
auto tiles = _taskTilesVec;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cnt = 0;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < tiles.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
TileInfo* ptile = &_taskTilesVec[i];
|
|
|
|
|
|
|
|
RECT32S box = ptile->boxInPan;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 跳过已输出块
|
|
|
|
|
|
|
|
if (ptile->nStatus > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//cnt++;
|
|
|
|
|
|
|
|
//continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SINT32 x1 = box.x/ downSampleR;
|
|
|
|
|
|
|
|
SINT32 y1 = box.y/ downSampleR;
|
|
|
|
|
|
|
|
SINT32 x2 = box.x/ downSampleR + box.w/ downSampleR;
|
|
|
|
|
|
|
|
SINT32 y2 = box.y/ downSampleR + box.h/ downSampleR;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 使用积分图快速计算区域和
|
|
|
|
|
|
|
|
float maskSum = integralMask.at<int>(y2, x2)
|
|
|
|
|
|
|
|
- integralMask.at<int>(y1, x2)
|
|
|
|
|
|
|
|
- integralMask.at<int>(y2, x1)
|
|
|
|
|
|
|
|
+ integralMask.at<int>(y1, x1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算瓦片影像覆盖率
|
|
|
|
|
|
|
|
float Coverage = maskSum * downSampleR * downSampleR / (box.w * box.h);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (Coverage > 0.95)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 输出并标记
|
|
|
|
|
|
|
|
ptile->nStatus = 1;
|
|
|
|
|
|
|
|
_googleProduct.ExportOneTile(_panImage, *ptile, _outDir, _filename);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SINT32 UnderStitch::ReceiveFrame(GD_VIDEO_FRAME_S img, FrameInfo para)
|
|
|
|
SINT32 UnderStitch::ReceiveFrame(GD_VIDEO_FRAME_S img, FrameInfo para)
|
|
|
@ -191,8 +282,6 @@ SINT32 UnderStitch::ReceiveFrame(GD_VIDEO_FRAME_S img, FrameInfo para)
|
|
|
|
_t_frame_cache->_para = para;
|
|
|
|
_t_frame_cache->_para = para;
|
|
|
|
_t_frame_cache->_frame_info = img;
|
|
|
|
_t_frame_cache->_frame_info = img;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int imgSize = 0;
|
|
|
|
int imgSize = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if(img.enPixelFormat == GD_PIXEL_FORMAT_GRAY_Y8)
|
|
|
|
if(img.enPixelFormat == GD_PIXEL_FORMAT_GRAY_Y8)
|
|
|
@ -261,7 +350,7 @@ SINT32 UnderStitch::ProcessFrame()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool UnderStitch::ExportGeoPng(std::string dir, std::string name)
|
|
|
|
bool UnderStitch::ExportGeoPng()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// 计算全景图的坐标范围
|
|
|
|
// 计算全景图的坐标范围
|
|
|
|
auto P1 = getBLHFromPan(cv::Point2f(0, 0), _H_pan);
|
|
|
|
auto P1 = getBLHFromPan(cv::Point2f(0, 0), _H_pan);
|
|
|
@ -278,50 +367,27 @@ bool UnderStitch::ExportGeoPng(std::string dir, std::string name)
|
|
|
|
|
|
|
|
|
|
|
|
TileInfo info = { 0 };
|
|
|
|
TileInfo info = { 0 };
|
|
|
|
|
|
|
|
|
|
|
|
info.box.north = maxB;
|
|
|
|
info.boxLatLon.north = maxB;
|
|
|
|
info.box.south = minB;
|
|
|
|
info.boxLatLon.south = minB;
|
|
|
|
info.box.west = minL;
|
|
|
|
info.boxLatLon.west = minL;
|
|
|
|
info.box.east = maxL;
|
|
|
|
info.boxLatLon.east = maxL;
|
|
|
|
info.tileName = name;
|
|
|
|
info.tileName = _filename;
|
|
|
|
info.href = name + ".png";
|
|
|
|
info.href = _filename + ".png";
|
|
|
|
|
|
|
|
|
|
|
|
// 输出谷歌地图产品
|
|
|
|
// 输出谷歌地图产品
|
|
|
|
_googleProduct.ExportGeoPng(_panImage, info, dir);
|
|
|
|
_googleProduct.ExportGeoPng(_panImage, info, _outDir);
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool UnderStitch::ExportGoogleTile(std::string dir, std::string name)
|
|
|
|
bool UnderStitch::ExportGoogleTile()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// 计算全景图的坐标范围
|
|
|
|
_googleProduct.ExportTileSet(_panImage, _taskTilesVec, _outDir, _filename);
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TileInfo info = { 0 };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
info.box.north = maxB;
|
|
|
|
|
|
|
|
info.box.south = minB;
|
|
|
|
|
|
|
|
info.box.west = minL;
|
|
|
|
|
|
|
|
info.box.east = maxL;
|
|
|
|
|
|
|
|
info.ind.z = _googleProduct.getZoomLevel(_panPara.scale);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_googleProduct.ExportTile(_panImage, info, dir, name);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GD_VIDEO_FRAME_S UnderStitch::ExportPanAddr()
|
|
|
|
GD_VIDEO_FRAME_S UnderStitch::ExportPanAddr()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
GD_VIDEO_FRAME_S pan_out;
|
|
|
|
GD_VIDEO_FRAME_S pan_out;
|
|
|
|