平面在球面上的投影
相机的,像素坐标,图像坐标,相机坐标,世界坐标如下示意图,是一个右手坐标系
假设在世界坐标系有一个观察平面,和对应到相机坐标系,像素坐标的示意图。
假定观察者垂直视角宽度为2β,水平视角宽度为2α,初始状态下P0,P1,P2,P3,P4各点坐标如下:
用户需设置显示分辨率(水平分辨率/垂直分辨率),设置完分辨率后,可对世界坐标系中的点 构成的平面进行图像输出,为了求得整个平面上的坐标点在世界坐标系的坐标,需要对每一个坐标点进行换算,由于在cpu里,三角计算,乘法和除法相对于加减运算运行,比较耗时浪费资源。可对 四点间按照 进行等间隔采样,进行量化,求得平面内所有点的世界坐标。
假设设置输出分辨率为800 x 600,则
= |(Px3 – Px1)|/600
= |(Py2 – Py1)|/ 800
Pxn = Px1+ n.
Pyn = Py1+ n.
Pzn = r
最后将平面坐标投影到球面,
公式为啥是这样的,
外切平面与圆交点0,距离半径就是r,
根据r /R比例关系,对x,y,z进行比例计算, 求得圆面坐标。
实现算法
//
double viewAngleDegV = 0;
double viewAngleDegH = 0;
double arfa = 0;
double berta = 0;
viewAngleDegV = 96; //deg
viewAngleDegH = 80; //deg
arfa = (viewAngleDegV /2) *PI/180; //c++ deg
berta = (viewAngleDegH /2) *PI/180; //c++ deg
//
double r = 0; //mm
int w = 0, h = 0;
r = 2000; //mm
w = 480; //pix
h = 480; //pix
if((w % 2) != 0)
w = w -1;
if((h % 2) != 0)
h = h -1;
//
//先用opcv读取一张照片,如果没有opcv,就是自己写读取像素值。
cv::Mat Im0 = cv::imread("E:\\zcb_work\\2113\\pic\\ch1\\left01.jpg", 0);
cv::Mat Im1 = cv::imread("E:\\zcb_work\\2113\\pic\\ch2\\right01.jpg", 0);
if (Im0.empty())
return -1;
if (Im1.empty())
return -1;
printf("++++ open image succesful +++\r\n");
cv::Mat Im2 = cv::Mat::zeros(h, w, CV_8UC1);
cv::Mat Im3 = cv::Mat::zeros(h, w, CV_8UC1);
//
double *Wxyz = (double *)malloc(sizeof(double)* w * h * 3);
double *Cxyz1 = (double *)malloc(sizeof(double)* w * h * 3);
double *Pxy1 = (double *)malloc(sizeof(double)* w * h * 2);
//
double fx1 = 534.10766364;//