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.

295 lines
7.9 KiB

5 months ago
#include "Arith_GeoSolver.h"
6 months ago
#include "Arith_VideoStitch.h"
#include "Arith_Utils.h"
#include "Arith_CoordModule.h"
#include "Arith_SysStruct.h"
using namespace cv;
5 months ago
GeoSolver::GeoSolver()
6 months ago
{
}
5 months ago
GeoSolver::~GeoSolver()
6 months ago
{
}
5 months ago
cv::Point2f GeoSolver::project(cv::Point2f pos_pan, Proj m_Proj, PanInfo pan)
6 months ago
{
cv::Point2f pos_geo = Trans_pan2Geo(pos_pan, pan);
cv::Point2f pos_frame = Trans_Geo2uv(pos_geo, m_Proj.tf_g2p);
return pos_frame;
}
5 months ago
cv::Point2f GeoSolver::back_project(cv::Point2f pos_frame, Proj m_Proj, PanInfo pan)
6 months ago
{
cv::Point2f pos_geo = Trans_uv2Geo(pos_frame, m_Proj.tf_p2g);
cv::Point2f pos_pan = Trans_Geo2pan(pos_geo, pan);
return pos_pan;
}
5 months ago
void GeoSolver::SetOriginPoint(FrameInfo info)
6 months ago
{
originPoint = getXYZFromBLH(info.craft.stPos);
6 months ago
}
5 months ago
cv::Point2f GeoSolver::Trans_uv2Geo(cv::Point2f pos_frame, TForm form)
6 months ago
{
Mat point = (Mat_<double>(3, 1) << pos_frame.x, pos_frame.y, 1);
Mat result = form.R * point;
// 转局部地理系
double warpedX = result.at<double>(0, 0) / result.at<double>(2, 0);
double warpedY = result.at<double>(1, 0) / result.at<double>(2, 0);
// 平移到原点地理系
warpedX += form.T.at<double>(0, 0);
warpedY += form.T.at<double>(1, 0);
return cv::Point2f(warpedX, warpedY);
}
5 months ago
cv::Point2f GeoSolver::Trans_Geo2uv(cv::Point2f pos_geo, TForm form_inv)
6 months ago
{
// 先平移到当前相机位置
cv::Point2f pos_cam = pos_geo;
pos_cam.x = pos_geo.x + form_inv.T.at<double>(0, 0);
pos_cam.y = pos_geo.y + form_inv.T.at<double>(1, 0);
Mat point = (Mat_<double>(3, 1) << pos_cam.x, pos_cam.y, 1);
Mat result = form_inv.R * point;
// 转像方
double warpedX = result.at<double>(0, 0) / result.at<double>(2, 0);
double warpedY = result.at<double>(1, 0) / result.at<double>(2, 0);
return cv::Point2f(warpedX, warpedY);
}
5 months ago
cv::Point2f GeoSolver::Trans_pan2Geo(cv::Point2f pos_pan, PanInfo panPara)
6 months ago
{
double x = (pos_pan.x - panPara.map_shiftX) / panPara.scale;
double y = (panPara.m_pan_height - (pos_pan.y - panPara.map_shiftY)) / panPara.scale;
return cv::Point2f(x, y);
}
5 months ago
cv::Point2f GeoSolver::Trans_Geo2pan(cv::Point2f pos_geo, PanInfo panPara)
6 months ago
{
double pan_x = pos_geo.x * panPara.scale + panPara.map_shiftX;
double pan_y = (panPara.m_pan_height - pos_geo.y * panPara.scale) + panPara.map_shiftY;
return cv::Point2f(pan_x, pan_y);
}
5 months ago
Mat GeoSolver::Mat_TransENGMove(FrameInfo info)
6 months ago
{
PointXYZ ptCurr = getXYZFromBLH(info.craft.stPos);
PointXYZ diff = getNUEXYZFromCGCSXYZ(ptCurr, originPoint);
6 months ago
Mat move = Mat::zeros(3, 1, CV_64F);
move.at<double>(0, 0) = diff.Z;
move.at<double>(1, 0) = diff.X;
move.at<double>(2, 0) = diff.Y;
return move;
}
5 months ago
Mat GeoSolver::Mat_TransENG2uv(FrameInfo info)
6 months ago
{
//从地理坐标系转像素坐标
//[u,v,1]'=Z*M*[X,Y,DH]' = Z*M*[1,0,0;0,1,0;0,0,DH]'*[X,Y,1]'
//[u,v,1]'=Z*M(内参)*M(alaph)*M(beta)*M(roll)*M(pitch)*M(yaw)*[X,Y,DH]
// 深度矩阵
Mat M_het = (Mat_<double>(3, 3) << 1, 0, 0,
0, 1, 0,
0, 0, info.nEvHeight
);
float yaw = info.craft.stAtt.fYaw;
Mat M_yaw = (Mat_<double>(3, 3) << cosd(yaw), -sind(yaw), 0,
sind(yaw), cosd(yaw), 0,
0, 0, 1
);
float pit = info.craft.stAtt.fPitch;
Mat M_pitch = (Mat_<double>(3, 3) << 1, 0, 0,
0, cosd(pit), -sind(pit),
0, sind(pit), cosd(pit)
);
/* 1 0 0
0 cos sin
0 -sin cos
*/
float roll = info.craft.stAtt.fRoll;
Mat M_roll = (Mat_<double>(3, 3) << cosd(roll), 0, sind(roll),
0, 1, 0,
-sind(roll), 0, cosd(roll)
);
float beta = info.servoInfo.fServoAz;
Mat M_beta = (Mat_<double>(3, 3) << cosd(beta), -sind(beta), 0,
sind(beta), cosd(beta), 0,
0, 0, 1
);
float alaph = info.servoInfo.fServoPt;
Mat M_alaph = (Mat_<double>(3, 3) << 1, 0, 0,
0, cosd(alaph), -sind(alaph),
0, sind(alaph), cosd(alaph)
);
// 内参
FLOAT32 fd = info.camInfo.nFocus / info.camInfo.fPixelSize * 1000;
Mat M_cam = (Mat_<double>(3, 3) << fd, 0, info.nWidth / 2,
0, -fd, info.nHeight / 2,
0, 0, 1
);
Mat M = M_cam * M_alaph * M_beta * M_roll * M_pitch * M_yaw * M_het;
//cout << M_cam * M_alaph * M_beta * M_roll * M_pitch * M_yaw * M_het;
return M;
}
5 months ago
Proj GeoSolver::AnlayseTform(FrameInfo info)
6 months ago
{
Proj projection;
// 从像方->地理
projection.tf_p2g.R = Mat_TransENG2uv(info).inv();
projection.tf_p2g.T = Mat_TransENGMove(info);
// 从地理->像方
projection.tf_g2p.R = Mat_TransENG2uv(info);
projection.tf_g2p.T = -projection.tf_p2g.T;
return projection;
}
5 months ago
cv::Mat GeoSolver::findHomography(Proj proj, PanInfo pan)
6 months ago
{
// 同名点计算,从像方到全景
cv::Point2f leftTop_map = back_project(cv::Point2f(0,0), proj, pan);
cv::Point2f rightTop_map = back_project(cv::Point2f(1000,0), proj, pan);
cv::Point2f rightBottom_map = back_project(cv::Point2f(1000,1000), proj, pan);
cv::Point2f leftBottom_map = back_project(cv::Point2f(0,1000), proj, pan);
std::vector<cv::Point2f> srcPoints;
srcPoints.push_back(cv::Point2f(0,0));
srcPoints.push_back(cv::Point2f(1000,0));
srcPoints.push_back(cv::Point2f(1000,1000));
srcPoints.push_back(cv::Point2f(0,1000));
// 目标图像(全景图)的四个顶点坐标
std::vector<cv::Point2f> dstPoints;
dstPoints.push_back(leftTop_map); // 左
dstPoints.push_back(rightTop_map); // 右上
dstPoints.push_back(rightBottom_map); // 右下
dstPoints.push_back(leftBottom_map); // 左下
// 计算单应性矩阵 H
cv::Mat H = cv::findHomography(srcPoints, dstPoints);
return H;
}
5 months ago
cv::Mat GeoSolver::findHomography(Proj proj)
{
std::vector<cv::Point2f> srcPoints;
srcPoints.push_back(cv::Point2f(0, 0));
srcPoints.push_back(cv::Point2f(1000, 0));
srcPoints.push_back(cv::Point2f(1000, 1000));
srcPoints.push_back(cv::Point2f(0, 1000));
// 同名点计算,从像方到全景
cv::Point2f leftTop_map = Trans_uv2Geo(srcPoints[0], proj.tf_p2g);
cv::Point2f rightTop_map = Trans_uv2Geo(srcPoints[1], proj.tf_p2g);
cv::Point2f rightBottom_map = Trans_uv2Geo(srcPoints[2], proj.tf_p2g);
cv::Point2f leftBottom_map = Trans_uv2Geo(srcPoints[3], proj.tf_p2g);
// 目标图像(全景图)的四个顶点坐标
std::vector<cv::Point2f> dstPoints;
dstPoints.push_back(leftTop_map); // 左
dstPoints.push_back(rightTop_map); // 右上
dstPoints.push_back(rightBottom_map); // 右下
dstPoints.push_back(leftBottom_map); // 左下
// 计算单应性矩阵 H
cv::Mat H = cv::findHomography(srcPoints, dstPoints);
return H;
}
6 months ago
6 months ago
// 计算多边形的面积
double polygonArea(const vector<cv::Point2f>& points)
{
double area = 0.0;
int n = points.size();
for (int i = 0; i < n; i++) {
int j = (i + 1) % n;
area += points[i].x * points[j].y - points[j].x * points[i].y;
}
return abs(area) / 2.0;
}
// 计算两个四边形的 IOU
double computeQuadrilateralIOU(const vector<cv::Point2f>& quad1, const vector<cv::Point2f>& quad2)
{
// 将四边形转换为多边形
vector<Point2f> poly1 = quad1;
vector<Point2f> poly2 = quad2;
// 计算交集多边形
vector<Point2f> intersectionPolygon;
intersectConvexConvex(poly1, poly2, intersectionPolygon);
// 计算面积
double area1 = polygonArea(poly1);
double area2 = polygonArea(poly2);
double intersectionArea = polygonArea(intersectionPolygon);
double unionArea = area1 + area2 - intersectionArea;
// 计算 IOU
if (unionArea == 0) return 0.0; // 避免除零错误
return intersectionArea / unionArea;
6 months ago
}
cv::Point2f warpPointWithH(cv::Mat H, cv::Point2f srcPt)
{
Mat point = (Mat_<double>(3, 1) << srcPt.x, srcPt.y, 1);
Mat result = H * point;
// 转局部地理系
double warpedX = result.at<double>(0, 0) / result.at<double>(2, 0);
double warpedY = result.at<double>(1, 0) / result.at<double>(2, 0);
return cv::Point2f(warpedX,warpedY);
}
vector<cv::Point2f> warpRectWithH(cv::Mat H,cv::Size size)
{
vector<cv::Point2f> _res;
_res.push_back(warpPointWithH(H, cv::Point2f(0,0)));
_res.push_back(warpPointWithH(H, cv::Point2f(size.width,0)));
_res.push_back(warpPointWithH(H, cv::Point2f(size.width,size.height)));
_res.push_back(warpPointWithH(H, cv::Point2f(0,size.height)));
return _res;
6 months ago
}