|
|
|
@ -10,9 +10,9 @@
|
|
|
|
|
using namespace std;
|
|
|
|
|
using namespace cv;
|
|
|
|
|
|
|
|
|
|
API_FrontStitch* API_FrontStitch::Create(SINT32 nWidth, SINT32 nHeight)
|
|
|
|
|
API_FrontStitch* API_FrontStitch::Create(std::string cachedir)
|
|
|
|
|
{
|
|
|
|
|
return new FrontStitch(nWidth, nHeight);
|
|
|
|
|
return new FrontStitch(cachedir);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -21,9 +21,18 @@ void API_FrontStitch::Destroy(API_FrontStitch* obj)
|
|
|
|
|
delete obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FrontStitch::FrontStitch(SINT32 nWidth, SINT32 nHeight)
|
|
|
|
|
FrontStitch::FrontStitch(std::string cachedir)
|
|
|
|
|
{
|
|
|
|
|
// 创建缓存对象
|
|
|
|
|
_cache = new FileCache<FrameCache>(50, cachedir);
|
|
|
|
|
|
|
|
|
|
_GeoSolver = new GeoSolver();
|
|
|
|
|
|
|
|
|
|
_FeaMatcher = new FeatureMatcher(DetectorType::SIFT, MatcherType::FLANN);
|
|
|
|
|
|
|
|
|
|
_BATask = new BA_Task(_cache);
|
|
|
|
|
|
|
|
|
|
_FBlendTask = new FrontMapBlend(_cache);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FrontStitch::~FrontStitch()
|
|
|
|
@ -88,7 +97,7 @@ FPanInfo FrontStitch::Init(FrameInfo info, ScanRange stAzRange, ScanRange stPtRa
|
|
|
|
|
_panPara.m_pan_height = DEGLIM360(Pole_up.alpha - Pole_bottom.alpha) / _panPara.fAglRes;
|
|
|
|
|
|
|
|
|
|
_panImage = cv::Mat::zeros(_panPara.m_pan_height, _panPara.m_pan_width, CV_8UC3);
|
|
|
|
|
|
|
|
|
|
_panMask = cv::Mat::zeros(_panPara.m_pan_height, _panPara.m_pan_width, CV_8UC1);
|
|
|
|
|
|
|
|
|
|
cudaMalloc((void**)&_cuda_mem.global_cuda_Frame, info.nWidth * info.nHeight * 3);//rgb
|
|
|
|
|
cudaMalloc((void**)&_cuda_mem.global_cuda_Pan, _panPara.m_pan_width * _panPara.m_pan_height * 3);//rgb
|
|
|
|
@ -99,6 +108,27 @@ FPanInfo FrontStitch::Init(FrameInfo info, ScanRange stAzRange, ScanRange stPtRa
|
|
|
|
|
return _panPara;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BYTE8 FrontStitch::Run(GD_VIDEO_FRAME_S img, FrameInfo info)
|
|
|
|
|
{
|
|
|
|
|
// 极坐标拼接
|
|
|
|
|
PoleStitch(img, info);
|
|
|
|
|
|
|
|
|
|
//ReceiveFrame(img, info);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SINT32 FrontStitch::OptAndOutCurrPan()
|
|
|
|
|
{
|
|
|
|
|
// 优化所有帧 效果不佳,放弃
|
|
|
|
|
//ProcessFrame(_recvFrameKey);
|
|
|
|
|
|
|
|
|
|
// 重绘所有帧
|
|
|
|
|
//_FBlendTask->DirectMap(_recvFrameKey, _panPara, _panImage, _panMask, _cuda_mem);
|
|
|
|
|
|
|
|
|
|
return SINT32();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BYTE8 FrontStitch::PoleStitch(GD_VIDEO_FRAME_S img, FrameInfo info)
|
|
|
|
|
{
|
|
|
|
|
cv::Mat H = _GeoSolver->findHomography(info);
|
|
|
|
@ -107,13 +137,13 @@ BYTE8 FrontStitch::PoleStitch(GD_VIDEO_FRAME_S img, FrameInfo info)
|
|
|
|
|
// 获取rgb源图像
|
|
|
|
|
cv::Mat rgb = getRGBMatFromGDFrame(img, img.u64VirAddr[0]);
|
|
|
|
|
|
|
|
|
|
Pole CT_map = getPoleFromImgWithH(H, cv::Point2f(img.u32Width/2, img.u32Height/2), info.nEvHeight);
|
|
|
|
|
//Pole CT_map = getPoleFromImgWithH(H, cv::Point2f(img.u32Width/2, img.u32Height/2), info.nEvHeight);
|
|
|
|
|
|
|
|
|
|
// 计算帧的map四至,注意这里不是线性变化,不能完全保证四至约束下的原图能完全覆盖,即反采样后图像可能不完整
|
|
|
|
|
Pole leftTop_map = getPoleFromImgWithH(H,cv::Point2f(0,0), info.nEvHeight);
|
|
|
|
|
Pole rightTop_map = getPoleFromImgWithH(H, cv::Point2f(img.u32Width,0), info.nEvHeight);
|
|
|
|
|
Pole rightBottom_map = getPoleFromImgWithH(H, cv::Point2f(img.u32Width,img.u32Height), info.nEvHeight);
|
|
|
|
|
Pole leftBottom_map = getPoleFromImgWithH(H, cv::Point2f(0,img.u32Height), info.nEvHeight);
|
|
|
|
|
Pole leftTop_map = getPoleFromImgWithH(H, cv::Point2f(0, 0), info.nEvHeight);
|
|
|
|
|
Pole rightTop_map = getPoleFromImgWithH(H, cv::Point2f(img.u32Width, 0), info.nEvHeight);
|
|
|
|
|
Pole rightBottom_map = getPoleFromImgWithH(H, cv::Point2f(img.u32Width, img.u32Height), info.nEvHeight);
|
|
|
|
|
Pole leftBottom_map = getPoleFromImgWithH(H, cv::Point2f(0, img.u32Height), info.nEvHeight);
|
|
|
|
|
|
|
|
|
|
//leftTop_map.beta = DEGLIM360(leftTop_map.beta);
|
|
|
|
|
//rightTop_map.beta = DEGLIM360(rightTop_map.beta);
|
|
|
|
@ -121,21 +151,21 @@ BYTE8 FrontStitch::PoleStitch(GD_VIDEO_FRAME_S img, FrameInfo info)
|
|
|
|
|
//leftBottom_map.beta = DEGLIM360(leftBottom_map.beta);
|
|
|
|
|
|
|
|
|
|
// 转全景图的像方
|
|
|
|
|
cv::Point2f p_leftTop_map = getFPanFromPole(leftTop_map,_panPara);
|
|
|
|
|
cv::Point2f p_leftTop_map = getFPanFromPole(leftTop_map, _panPara);
|
|
|
|
|
cv::Point2f p_rightTop_map = getFPanFromPole(rightTop_map, _panPara);
|
|
|
|
|
cv::Point2f p_rightBottom_map = getFPanFromPole(rightBottom_map, _panPara);
|
|
|
|
|
cv::Point2f p_leftBottom_map = getFPanFromPole(leftBottom_map, _panPara);
|
|
|
|
|
|
|
|
|
|
// 计算全景图上范围
|
|
|
|
|
int right = max(max(max(p_leftTop_map.x, p_rightTop_map.x), p_rightBottom_map.x), p_leftBottom_map.x);
|
|
|
|
|
int left = min(min(min(p_leftTop_map.x, p_rightTop_map.x), p_rightBottom_map.x), p_leftBottom_map.x);
|
|
|
|
|
int top = min(min(min(p_leftTop_map.y, p_rightTop_map.y), p_rightBottom_map.y), p_leftBottom_map.y);
|
|
|
|
|
int bottom = max(max(max(p_leftTop_map.y, p_rightTop_map.y), p_rightBottom_map.y), p_leftBottom_map.y);
|
|
|
|
|
// 计算全景图上范围
|
|
|
|
|
int right = max(max(max(p_leftTop_map.x, p_rightTop_map.x), p_rightBottom_map.x), p_leftBottom_map.x);
|
|
|
|
|
int left = min(min(min(p_leftTop_map.x, p_rightTop_map.x), p_rightBottom_map.x), p_leftBottom_map.x);
|
|
|
|
|
int top = min(min(min(p_leftTop_map.y, p_rightTop_map.y), p_rightBottom_map.y), p_leftBottom_map.y);
|
|
|
|
|
int bottom = max(max(max(p_leftTop_map.y, p_rightTop_map.y), p_rightBottom_map.y), p_leftBottom_map.y);
|
|
|
|
|
|
|
|
|
|
int xRange = right - left;
|
|
|
|
|
int yRnage = bottom - top;
|
|
|
|
|
int yRnage = bottom - top;
|
|
|
|
|
|
|
|
|
|
//反映射到像素坐标
|
|
|
|
|
//反映射到像素坐标
|
|
|
|
|
MINMAXRECT32S RANGES = { 0 };
|
|
|
|
|
RANGES.minY = std::max(0, top);
|
|
|
|
|
RANGES.maxY = std::min(_panImage.rows - 1, bottom);
|
|
|
|
@ -143,8 +173,8 @@ BYTE8 FrontStitch::PoleStitch(GD_VIDEO_FRAME_S img, FrameInfo info)
|
|
|
|
|
RANGES.minX = std::max(0, left);
|
|
|
|
|
RANGES.maxX = std::min(_panImage.cols - 1, right);
|
|
|
|
|
|
|
|
|
|
cv::Rect2d roi(RANGES.minX , RANGES.minY, RANGES.maxX - RANGES.minX, RANGES.maxY- RANGES.minY);
|
|
|
|
|
|
|
|
|
|
cv::Rect2d roi(RANGES.minX, RANGES.minY, RANGES.maxX - RANGES.minX, RANGES.maxY - RANGES.minY);
|
|
|
|
|
|
|
|
|
|
if (roi.width < 0)
|
|
|
|
|
{
|
|
|
|
|
int a = 0;
|
|
|
|
@ -152,7 +182,7 @@ BYTE8 FrontStitch::PoleStitch(GD_VIDEO_FRAME_S img, FrameInfo info)
|
|
|
|
|
|
|
|
|
|
cv::Mat H_inv = H.inv();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//UpdatePan_CPU(rgb, _panImage, roi, H_inv, _panPara, dep);
|
|
|
|
|
|
|
|
|
|
UpdatePan_CUDA(rgb, _panImage, roi, H_inv, _panPara, dep, _cuda_mem);
|
|
|
|
@ -164,12 +194,74 @@ BYTE8 FrontStitch::PoleStitch(GD_VIDEO_FRAME_S img, FrameInfo info)
|
|
|
|
|
|
|
|
|
|
SINT32 FrontStitch::ReceiveFrame(GD_VIDEO_FRAME_S img, FrameInfo para)
|
|
|
|
|
{
|
|
|
|
|
return SINT32();
|
|
|
|
|
// 构造单帧缓存
|
|
|
|
|
auto _t_frame_cache = std::make_shared<FrameCache>();
|
|
|
|
|
|
|
|
|
|
_t_frame_cache->_para = para;
|
|
|
|
|
_t_frame_cache->_frame_info = img;
|
|
|
|
|
|
|
|
|
|
int imgSize = 0;
|
|
|
|
|
|
|
|
|
|
if (img.enPixelFormat == GD_PIXEL_FORMAT_GRAY_Y8)
|
|
|
|
|
{
|
|
|
|
|
imgSize = img.u32Height * img.u32Width;
|
|
|
|
|
}
|
|
|
|
|
if (img.enPixelFormat == GD_PIXEL_FORMAT_RGB_PACKED)
|
|
|
|
|
{
|
|
|
|
|
imgSize = img.u32Height * img.u32Width * 3;
|
|
|
|
|
}
|
|
|
|
|
if (img.enPixelFormat == GD_PIXEL_FORMAT_NV12)
|
|
|
|
|
{
|
|
|
|
|
imgSize = img.u32Height * img.u32Width * 1.5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 深拷贝图像数据
|
|
|
|
|
memcpy(_t_frame_cache->_data, img.u64VirAddr[0], imgSize);
|
|
|
|
|
|
|
|
|
|
// 提取特征点
|
|
|
|
|
std::vector<cv::KeyPoint> keypoints;
|
|
|
|
|
cv::Mat descriptors;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::Mat src = getRGBAMatFromGDFrame(img, img.u64VirAddr[0]);
|
|
|
|
|
_FeaMatcher->extractFeatures(src, keypoints, descriptors);
|
|
|
|
|
|
|
|
|
|
size_t keyNum = MIN(keypoints.size(), FEA_NUM_MAX);
|
|
|
|
|
|
|
|
|
|
_t_frame_cache->ptNum = keyNum;
|
|
|
|
|
|
|
|
|
|
// 保存特征点
|
|
|
|
|
memcpy(_t_frame_cache->_pt, keypoints.data(), sizeof(cv::KeyPoint) * keyNum);
|
|
|
|
|
|
|
|
|
|
// 保存描述子
|
|
|
|
|
memcpy(_t_frame_cache->_desp, descriptors.data, sizeof(float) * keyNum * FEA_DES_SIZE);
|
|
|
|
|
|
|
|
|
|
cv::Mat_<double> H0 = _GeoSolver->findHomography(para);
|
|
|
|
|
|
|
|
|
|
// 保存初始H
|
|
|
|
|
memcpy(_t_frame_cache->H, H0.data, sizeof(double) * 9);
|
|
|
|
|
|
|
|
|
|
// 预处理结果加入文件缓存
|
|
|
|
|
_cache->set(para.nFrmID, _t_frame_cache);
|
|
|
|
|
|
|
|
|
|
_recvFrameKey.push_back(para.nFrmID);
|
|
|
|
|
|
|
|
|
|
_totalFrameCnt++;
|
|
|
|
|
|
|
|
|
|
return _totalFrameCnt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SINT32 FrontStitch::ProcessFrame()
|
|
|
|
|
SINT32 FrontStitch::ProcessFrame(vector<KeyType> keys)
|
|
|
|
|
{
|
|
|
|
|
return SINT32();
|
|
|
|
|
if (keys.size() == 0)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 优化所有帧
|
|
|
|
|
_BATask->OptFrame(keys, cv::Mat::zeros(cv::Size(3,3),CV_8UC1));
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GD_VIDEO_FRAME_S FrontStitch::ExportPanAddr()
|
|
|
|
@ -208,61 +300,3 @@ void UpdatePan_CPU(cv::Mat rgbFrame, cv::Mat pan, cv::Rect2d roi, cv::Mat H_inv,
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Pole getPoleFromImgWithH(cv::Mat H, cv::Point2f pt, float dep)
|
|
|
|
|
{
|
|
|
|
|
// 投影到地面坐标,这一步可以利用前面优化成果
|
|
|
|
|
cv::Point2f grdPt = warpPointWithH(H, pt);
|
|
|
|
|
|
|
|
|
|
// 补深度信息并转为常用的NUE坐标系
|
|
|
|
|
PointXYZ grdPtXYZ = { 0 };
|
|
|
|
|
grdPtXYZ.X = grdPt.y;
|
|
|
|
|
grdPtXYZ.Y = -dep;
|
|
|
|
|
grdPtXYZ.Z = grdPt.x;
|
|
|
|
|
|
|
|
|
|
// 地面点转极坐标
|
|
|
|
|
Pole pole = getPoleFromXYZ(grdPtXYZ);
|
|
|
|
|
|
|
|
|
|
return pole;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cv::Point2f getImgPosFromPole(cv::Mat H_inv, Pole _pole, float dep)
|
|
|
|
|
{
|
|
|
|
|
PointXYZ virPt = getXYZFromPole(_pole);
|
|
|
|
|
|
|
|
|
|
//虚拟点投影到地面
|
|
|
|
|
float ratio = -dep / virPt.Y;
|
|
|
|
|
PointXYZ realPt = { 0 };
|
|
|
|
|
realPt.X = virPt.X * ratio;
|
|
|
|
|
realPt.Y = virPt.Y * ratio;
|
|
|
|
|
realPt.Z = virPt.Z * ratio;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 转东北地
|
|
|
|
|
PointXYZ realPtGeo = { 0 };
|
|
|
|
|
realPtGeo.X = realPt.Z;
|
|
|
|
|
realPtGeo.Y = realPt.X;
|
|
|
|
|
realPtGeo.Z = -realPt.Y;
|
|
|
|
|
|
|
|
|
|
// 投影回像方
|
|
|
|
|
cv::Point2f px = warpPointWithH(H_inv, cv::Point2f(realPtGeo.X, realPtGeo.Y));
|
|
|
|
|
|
|
|
|
|
return px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Pole getPoleFromFPan(cv::Point2f pt, FPanInfo _panPara)
|
|
|
|
|
{
|
|
|
|
|
Pole _pole = { 0 };
|
|
|
|
|
_pole.beta = DEGLIM(_panPara.centerGeo.fAz + (pt.x - _panPara.m_pan_width / 2) * _panPara.fAglRes);
|
|
|
|
|
_pole.alpha = DEGLIM(_panPara.centerGeo.fPt + (_panPara.m_pan_height / 2 - pt.y) * _panPara.fAglRes);
|
|
|
|
|
return _pole;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cv::Point2f getFPanFromPole(Pole _pole, FPanInfo _panPara)
|
|
|
|
|
{
|
|
|
|
|
cv::Point2f pt = { 0 };
|
|
|
|
|
pt.x = DEGLIM(_pole.beta - _panPara.centerGeo.fAz) / _panPara.fAglRes + _panPara.m_pan_width / 2;
|
|
|
|
|
pt.y = DEGLIM(_panPara.centerGeo.fPt - _pole.alpha) / _panPara.fAglRes + _panPara.m_pan_height / 2;
|
|
|
|
|
return pt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|