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)按下面方式转换为球面上的

当f=0时,

3D-2D变换,球面上的按下面方式转换为2D平面上的点(m,n),

当f=0时,

 

 当f=1时,

 

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的主要内容,如果未能解决你的问题,请参考以下文章

360视频:旋转球面投影RSP

使用全景创建 360° x 180° 球面投影

360视频:正八面体投影OHP

360视频:CMP和ACP投影

360视频:赤道圆柱投影ECP

PCL:投影滤波将点云投影至球面