360视频:分段球面投影SSP
Posted Dillon2015
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了360视频:分段球面投影SSP相关的知识,希望对你有一定的参考价值。
分段球面投影(Segmented sphere projection,SSP)将球面分为3个部分:北极、南极、赤道。图1是SSP投影示意图,球面上三个部分的分界线是北纬45度和南纬45度。北极和南极投影后的面是圆,索引分别为0和1,赤道投影方式和ERP相同,赤道投影后被划分为4个相同的正方形面,索引为2到5。投影后面的两极圆的直径和赤道正方形边长相等,因为它们纬度都跨了90度。
图1 SSP投影
Frame Packing
SSP有两者frame packing方式,一种如图1所示,映射后按垂直方向展开。图2是真实图像垂直展开的示例。
图2 SSP垂直展开
SSP还可以按照水平方向展开,如图3所示。
图3 SSP水平展开
展开后各面的定义如表1。
表1 SSP各面的定义
投影变换
2D-3D变换,假设面的直径是A,则2D平面上的点(m,n)按下面方式转换为球面上的,
3D-2D变换,球面上的按下面方式转换为2D平面上的点(m,n),
Void TSegmentedSphere::map2DTo3D(SPos& IPosIn, SPos *pSPosOut)
POSType u, v,
square = m_sVideoInfo.iFaceHeight,
width = m_sVideoInfo.iFaceWidth,
pitch, yaw;
//u = IPosIn.x;
u = IPosIn.x + (POSType)(0.5);
v = IPosIn.y + (POSType)(0.5);
#if SVIDEO_SSP_PADDING_FIX
#else
if ((u < 0 || u >= m_sVideoInfo.iFaceWidth) && (v >= 0 && v < m_sVideoInfo.iFaceHeight * 2 / 3))
u = u < 0 ? m_sVideoInfo.iFaceWidth + u : (u - m_sVideoInfo.iFaceWidth);
else if (v < 0)
v = -v;
u = u + (m_sVideoInfo.iFaceWidth >> 1);
u = u >= m_sVideoInfo.iFaceWidth ? u - m_sVideoInfo.iFaceWidth : u;
else if (v >= m_sVideoInfo.iFaceHeight)
v = (m_sVideoInfo.iFaceHeight * 2 / 3 << 1) - v;
u = u + (m_sVideoInfo.iFaceWidth >> 1);
u = u >= m_sVideoInfo.iFaceWidth ? u - m_sVideoInfo.iFaceWidth : u;
#endif
POSType pole_x, pole_y, pole_d;
if (IPosIn.faceIdx == 0)
pole_x = u - width / 2;
pole_y = v - square / 2;
pole_d = ssqrt(pole_x*pole_x + pole_y*pole_y);
yaw = (pole_d > 0) ? acos(pole_y / pole_d) : 0;
yaw = (pole_x < 0) ? S_PI*2 - yaw : yaw;
pitch = S_PI_2 - pole_d * S_PI_2 / square;
else if (IPosIn.faceIdx == 1)
pole_x = u - width / 2;
pole_y = v - square / 2;
pole_d = ssqrt(pole_x*pole_x + pole_y*pole_y);
yaw = (pole_d > 0) ? satan2(pole_y, pole_x) + S_PI_2 : 0;
pitch = pole_d * S_PI_2 / square - S_PI_2;
else if (IPosIn.faceIdx == 2)
yaw = (POSType)(u*S_PI_2 / m_sVideoInfo.iFaceWidth - S_PI);
pitch = (POSType)(S_PI_2 - (v + square / 2)*S_PI / square / 2);
else if (IPosIn.faceIdx == 3)
yaw = (POSType)((u + square)*S_PI_2 / m_sVideoInfo.iFaceWidth - S_PI);
pitch = (POSType)(S_PI_2 - (v + square / 2)*S_PI / square / 2);
else if (IPosIn.faceIdx == 4)
yaw = (POSType)((u + 2*square)*S_PI_2 / m_sVideoInfo.iFaceWidth - S_PI);
pitch = (POSType)(S_PI_2 - (v + square / 2)*S_PI / square / 2);
else if (IPosIn.faceIdx == 5)
yaw = (POSType)((u + 3*square)*S_PI_2 / m_sVideoInfo.iFaceWidth - S_PI);
pitch = (POSType)(S_PI_2 - (v + square / 2)*S_PI / square / 2);
else
assert(!"Face index Error!\\n");
pSPosOut->faceIdx = IPosIn.faceIdx;
pSPosOut->x = (POSType)(scos(pitch)*scos(yaw));
pSPosOut->y = (POSType)(ssin(pitch));
pSPosOut->z = -(POSType)(scos(pitch)*ssin(yaw));
Void TSegmentedSphere::map3DTo2D(SPos *pSPosIn, SPos *pSPosOut)
POSType x = pSPosIn->x;
POSType y = pSPosIn->y;
POSType z = pSPosIn->z;
POSType len = ssqrt(x*x + y*y + z*z);
POSType square = m_sVideoInfo.iFaceHeight;
POSType yaw = (POSType)(satan2(-z, x)),
pitch = (POSType)(sasin(y / len));
pSPosOut->z = 0;
if (y > len*ssqrt(2) / 2)
pSPosOut->faceIdx = 0;
pSPosOut->x = square * ssin(yaw) * (S_PI_2 - pitch) / S_PI_2 +
m_sVideoInfo.iFaceWidth / 2 - 0.5;
pSPosOut->y = square / 2 * (1 + scos(yaw) * 2 * (S_PI_2 - pitch) / S_PI_2) - 0.5;
else if (y < -len*ssqrt(2) / 2)
pSPosOut->faceIdx = 1;
pSPosOut->x = square * ssin(yaw) * (S_PI_2 + pitch) / S_PI_2 +
m_sVideoInfo.iFaceWidth / 2 - 0.5;
pSPosOut->y = square / 2 * (1 - scos(yaw) * 2 * (S_PI_2 + pitch) / S_PI_2) - 0.5;
else if (z >= 0 && x < 0)
pSPosOut->faceIdx = 2;
pSPosOut->x = (S_PI + yaw)*m_sVideoInfo.iFaceWidth / S_PI_2 - 0.5;
pSPosOut->y = (S_PI_2 - pitch) * square / S_PI_2 - square / 2 - 0.5;
else if (z > 0 && x >= 0)
pSPosOut->faceIdx = 3;
pSPosOut->x = (S_PI + yaw)*m_sVideoInfo.iFaceWidth / S_PI_2 - m_sVideoInfo.iFaceWidth - 0.5;
pSPosOut->y = (S_PI_2 - pitch) * square / S_PI_2 - square / 2 - 0.5;
else if (z <= 0 && x > 0)
pSPosOut->faceIdx = 4;
pSPosOut->x = (S_PI + yaw)*m_sVideoInfo.iFaceWidth / S_PI_2 - 2 * m_sVideoInfo.iFaceWidth - 0.5;
pSPosOut->y = (S_PI_2 - pitch) * square / S_PI_2 - square / 2 - 0.5;
else if (z < 0 && x <= 0)
pSPosOut->faceIdx = 5;
pSPosOut->x = (S_PI + yaw)*m_sVideoInfo.iFaceWidth / S_PI_2 - 3 * m_sVideoInfo.iFaceWidth - 0.5;
pSPosOut->y = (S_PI_2 - pitch) * square / S_PI_2 - square / 2 - 0.5;
感兴趣的请关注微信公众号Video Coding
以上是关于360视频:分段球面投影SSP的主要内容,如果未能解决你的问题,请参考以下文章