立体渲染

来自CGTWiki
Xingshujun讨论 | 贡献2021年5月22日 (六) 13:44的版本 子像素级视点排布代码
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳转至:导航搜索

请区别VR中的立体渲染。 根据目前实验室的三维显示器结构可大致分类为柱镜式三维显示器透镜式三维显示器,区别于悬浮立体显示器


目录

同行[编辑]

  1. LEIA 3D
  2. HoloPlayer Looking Glasses Factory
  3. 成都斯斐德科技有限公司
  4. 宁波维真
  5. dimenco

立体显示器[编辑]

实验室主要涉及以下几种显示器:

狭缝光栅立体显示器[编辑]

显示组主要用来做实验,用菲林打印狭缝光栅。

狭缝光栅位于2D显示屏与观看者之间,如图1所示。狭缝光栅的透光条和挡光条相间排列,由于挡光条对光的遮挡作用和透光条对光的透光作用,结合2D显示屏上与之对应排列的左右视差图像,实现了左右视差图像的光线在空间的分离。以两视点3D显示为例,由于狭缝光栅挡光条的遮挡,观看者的一只眼睛透过一条狭缝只能观看到一列像素。如果左眼只能看到奇(偶)列像素,右眼只能看到偶(奇)列像素,且2D显示屏奇、偶列像素分别显示了左右视差图像,那么,观看者就可以观看到立体图像。

图1 狭缝光栅立体显示器示意图
图2 柱透镜光栅3D显示器示意图





柱镜光栅立体显示器[编辑]

市场上能买到,和狭缝光栅立体显示器有着相同的像素排布。 结构如图2所示。2D显示屏位于柱透镜光栅的焦平面上,在柱透镜单元的排列方向上,每个柱透镜单元将置于其焦平面上不同位置的各幅视差图像光折射到不同方向。同样,以两视点3D显示为例,显示屏的奇、偶列像素分别显示左右眼两幅视差图像,柱透镜光栅的折射作用使左右视差图像的光线向不同方向传播,观看者位于合适的观看位置就可观看到立体图像。

光栅密度与观察距离编辑[编辑]

所谓光栅密度,一般指英寸宽度中光栅线的数目,用符号“lpi”来表示。光栅材料的lpi数值越高, 表示光栅线越细。

许多人受平面制作观念的影响,认为光栅密度越高,立体图像画面就越完美。其实,这是一种误解。作为立体画面,画面的细致度只是考量的一个方面,更主要的是在相应观察距离上的立体效果。

一般来讲,不同密度的光栅材料,其最佳观察距离是不同的:光栅密度越高,观察距离越近;光栅密度越低,其观察距离越远

下表列出了不同密度范围的光栅材料的最佳观察距离参考值:

光栅密度范围最佳观察距离

15 lpi 及以下500 cm以上

21 lpi ~ 30 lpi300cm左右

35 lpi ~ 40 lpi200cm左右

50 lpi ~ 60 lpi100cm左右

60 lpi ~ 80 lpi50cm左右

5 lpi 及以上30cm左右

设计者应根据画面的实际观察距离,选择相应密度的光栅材料。

集成成像光场立体显示器[编辑]

集成成像光场立体显示器由LCD面板,透镜阵列和扩散膜构成。

水平光场立体显示器[编辑]

水平光场立体显示器主要由LCD面板,柱透镜光栅,扩散膜和特殊光源组成。对于我们组来说,它的视点排布规律和普通的裸眼显示器没有多大区别。

悬浮立体显示器[编辑]

显示组研发的悬浮立体显示器,可以将一个显示平面投射到三维空间中。

对于我们组来说,它就是一个二维显示屏,背景是黑色的。

基本原理[编辑]

视点排布与立体图的合成[编辑]

将多幅视差图像合成单幅立体图像,使得合成图像中的子像素值或像素值来自多幅视差图像的过程,称为像素排布与合成。

自由立体显示器、水平光场立体显示器视点排布[编辑]

线数(_LineNum):(对于狭缝光栅自由立体显示器)指一组透光条 + 挡光条一共覆盖的子像素数量。

(对于柱透镜光栅自由立体显示器)指一个透镜覆盖的子像素数量。

倾斜角度(_IncAngle ):将光栅倾斜放置可减轻莫尔条纹的影响,并且有效地平衡3D分辨率在水平方向和垂直方向的损失。显示组默认垂直方向的倾斜角度为0,向右倾斜为正方向。

视点总数(_ViewNum ): 视点总数

最简UNITY光栅测线数

公式推导[编辑]
子像素级视点排布代码[编辑]
int getViewNUM(int row, int col, int k)
{
	float step_value = 1.0 / _ViewNum * _LineNum;
	float value_pixel = col * 3 + 3 * row * _IncAngle + k;

	float judge_value = value_pixel - int(value_pixel / _LineNum) * _LineNum;

	if (0 > judge_value)    
	{
		judge_value = judge_value + _LineNum;
	}

	int view_point_number = floor(judge_value / step_value);
	return view_point_number;
}

子像素视点排布公式以左上角为(0,0)点,x 轴水平向右,y 轴水平向下。 row 代表行号, col 代表列号,k 代表第几个子像素,取值为0到2.

double D;
double tanA;
double Nt;

double getViewNum(int i,int j,int k)
{
	int viewnum =int(fmod((3*i+k-koff-3*j*tanA),D/tanA)*Dx/tanA*Nt);
	return viewnum>=0?viewnum:viewnum+Nt;
}

像素级视点排布代码[编辑]
int getViewNUMPixel(float i, float j)
{
	float step_value = 1.0 / _ViewNum * _LineNum;
	float value_pixel = j + i * _IncAngle;

	float judge_value = value_pixel - int(value_pixel / _LineNum) * _LineNum;

	if (0 > judge_value) 
	{
		judge_value = judge_value + _LineNum;
	}

	int view_point_number = floor(judge_value / step_value);
	return view_point_number;
}

像素视点排布公式以左上角为(0,0)点,x 轴水平向右,y 轴水平向下。 i 代表行号, j 代表列号。

集成成像立体显示器、全视差光场立体显示器视点排布[编辑]

集成成像工作的三个模式:虚模式、实模式、平行模式

光栅化渲染[编辑]

光线投射和光线跟踪渲染[编辑]

光线投射(Ray casting)[编辑]

正向投射。从图像的每一个像素,沿视线方向发射光线,光线穿越整个图像序列,并在这个过程中,对图像序列进行采样获取颜色信息,同时依据光线吸收模型将颜色值进行累加,直至光线穿越整个图像序列,最后得到的颜色值就是渲染图像的颜色。

光线跟踪(Ray tracing)[编辑]

逆向跟踪。沿着到达视点的光线的反方向跟踪,经过屏幕上每一个象素,找出与视线相交的物体表面点,并继续跟踪,找出影响点光强的所有光源,从而算出点上精确的光线强度。

递归式光线跟踪[编辑]
路径跟踪(Path tracing)[编辑]

视景体与光线的生成[编辑]

非线性视景体[编辑]

混合渲染[编辑]

混合渲染既可以是光栅化渲染与基于图像渲染的结合,也可以是光栅化渲染与光线跟踪、光线投射渲染的结合。


DIBR[编辑]

基于深度图像渲染(DIBR)方法是目前应用最广泛的虚拟视点合成方法,它可以利用一个视点的参考视点的彩色图像及其相对应的深度信息来生成其余视点的图像,减少了存储空间,进而节省了传输带宽。 基于深度图像渲染的虚拟视点合成方法系统基本框架如图所示,首先以参考视点的彩色图像和其对应处理后的深度图像作为系统的输入,后经过3D变形(3D warping)算法和空洞填补算法,渲染合成最终的虚拟视点图像。

   基于深度图像渲染的虚拟视点合成方法系统基本框架

在利用DIBR算法生成虚拟视点的过程中,出现信息的空洞是不可避免的,另外,还会出现重采样、重叠以及伪影的问题,严重影响虚拟视点图像质量,并且算法重复性高,渲染实时性较差,因此算法效率也是亟待解决的问题之一。

MDBIR[编辑]

Real-Time Rendering Method of Depth-Image-Based Multiple Reference Views for Integral Imaging Display 10.1109/ACCESS.2019.2956102

HRT[编辑]

实验室显示器列表[编辑]

柱镜光栅立体显示器[编辑]

参数[编辑]

地点[编辑]

8k水平光场立体显示器[编辑]

名称
相机阵列到零视差平面的距离 22
相机间距 0.48
中心相机FOV 21.3
光栅线数 26.157
倾角 -0.1655
视点偏移值 25
视点总数 50

4k水平光场立体显示器[编辑]

名称
相机阵列到零视差平面的距离 1m
相机间距 0.02m
中心相机FOV 45
光栅线数 170486
倾角 -0.141
视点偏移值 25
视点总数 50

集成成像光场立体显示器[编辑]

参数[编辑]

名称
相机阵列到零视差平面的距离 2.3m
相机间距 0.0193m
中心相机FOV 12.9
基元图像 83×83
分辨率 3840×2160

地点[编辑]

集成成像光场立体显示器

超多视点立体渲染中存在的问题[编辑]

光场的采集需要设置大量的视点,采集速度与视点数目的增加成反比。视点采集数目越多,还原出来的光场图像越好,而实时性和交互性就会降低。

为了满足光场的实时性,需要新的算法来满足不同显示设备的需求。

传统的解决方案可分为三类:

  • 逐视点的渲染编码方案
  • 逆向光线跟踪渲染编码方案
  • 基于深度绘制的渲染编码方案。

如果对实时性没有要求,逆向光线跟踪渲染编码方案为最优方案,渲染效果最好。
逐视点的渲染编码方案可应用于总分辨率为8k以下,单视点分辨率为1k,视点数目小于100的水平视差立体显示器。
而基于深度绘制的渲染编码方案能够实现10000个视点以内的8k光场显示的实现绘制与编码,但是它存在光照问题,尤其是对具有高光材质的物体。
对于10000个视点以上的8k光场实时渲染与编码,传统的单机算法都无法解决。

光场渲染实时的解决方案:

  • 对于10000个视点以上的8k光场设备,使用部分光线跟踪的方法对移动物体映射的区域进行光线跟踪,而不运动的部分不进行光线跟踪,这样就可以有效地降低计算量,实现实时的光场渲染。
  • 若光场设置的总分辨率超过8k,可使用多机集群渲染的方式实时,需要使用实时同步协议实现场景与摄影机的同步。

逐视点的渲染编码方案性能测试[编辑]

多视点编码[编辑]

光栅倾角

立体相机的设置[编辑]

立体相机的设置

虚拟摄影机的视景体设置主要有以下三种设置方法:

(a)平行式设置 (b)汇聚式设置 (c)错切式设置

对于平行式视景体设置来说,虚拟摄影机的光轴相互平行,但它只能显示出屏立体效果,而且公共区域狭小。
而汇聚式设置方式,只有屏幕的中心线位置没有垂直视差,两边的垂直视差最大。人眼感到两边的立体影响向屏幕内凹陷,造成立体的畸变。
错切式设置方法既能显示出屏立体显示效果,又能显示入屏立体显示效果,并且没有汇聚式设置产生的畸变。
平行式视景体与错切式视景体之间存在三维错切关系。

三维视景体的设置[编辑]

请先查看常用游戏引擎的坐标系

文件:NVIDIA-Turing-Architecture-Whitepaper.pdf

Blender中视景体的错切[编辑]

OSG双目视景体的设置[编辑]

//计算左摄影机模型视图矩阵
osg::Matrixd computeLeftEyeViewMatrix(const osg::Matrixd& view) const
{
    double iod = getEyeSeparation();//两眼间距
    double es = 0.5f*iod;

    return view *
           osg::Matrixd(1.0,0.0,0.0,0.0,
                       0.0,1.0,0.0,0.0,
                       0.0,0.0,1.0,0.0,
                       es,0.0,0.0,1.0);
}

//计算左摄影机模型投影矩阵
osg::Matrixd computeLeftEyeProjectionMatrix(const osg::Matrixd& projection) const
{
    double iod = getEyeSeparation(); //两眼间距
    double sd  = getScreenDistance();//人眼到屏幕间的距离

    return osg::Matrixd(1.0,0.0,0.0,0.0,
                        0.0,1.0,0.0,0.0,
                        iod/(2.0*sd),0.0,1.0,0.0,
                        0.0,0.0,0.0,1.0) *
                        projection;
}

Unity 3D中视景体的错切[编辑]

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShearMatrix : MonoBehaviour
{
    Camera _cam;
    Matrix4x4 centerViewMatrix;
    Matrix4x4 centerProjMatrix;
    public float distNearCam = 0.2f;
    public float distToZeroPlane=100.0f;
    public int ViewNum = 1000;
    public int curView = 0;

    void Start()
    {
        _cam = this.GetComponent<Camera>();
        centerProjMatrix = _cam.projectionMatrix;
        centerViewMatrix = _cam.worldToCameraMatrix;
    }

    void updateMatrix()
    {
        var viewMatrix = centerViewMatrix;
        var projMatrix = centerProjMatrix;

        Matrix4x4 transMatrix = Matrix4x4.identity;
        transMatrix.m03 = (curView - ViewNum / 2.0f) * distNearCam;

        Matrix4x4 shearMatrix = Matrix4x4.identity;
        shearMatrix.m02 = (curView - ViewNum / 2.0f) * distNearCam / distToZeroPlane;
        _cam.worldToCameraMatrix = transMatrix * viewMatrix;
        _cam.projectionMatrix = projMatrix * shearMatrix;
    }


    void Update()
    {
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            curView--;
        }

        if (Input.GetKey(KeyCode.RightArrow))
        {
            curView++;
        }

        curView = Mathf.Clamp(curView, 0, ViewNum);

        updateMatrix();
    }

}

视景体与光线的转换[编辑]

HOLOPLAYER DIBR 代码分析[编辑]

与上一版本先比,HoloplaySDK-1.2.1采用传统单视点 DIBR+空洞填补的方法生成新视点,并且针对后处理等技术做了进一步适配,渲染速度有所提升。

关键代码并行视点插值compute shader文件: ViewInterpolation

  • 像素映射函数
void ReprojectQuiltView(int2 coords, int viewIndex, int prevIndex)
{
	int2 baseCoords = baseViewPositions[prevIndex].xy + coords.xy;
	float4 c = Result.Load(baseCoords.xy);
	float d = ResultDepth.Load(baseCoords.xy);
	float ed = LinearEyeDepth(d);
	float viewAmt = abs(DIR * 0.5 + 0.5) * viewOffsets[viewIndex].y + abs(DIR * 0.5 - 0.5) * -(1.0 - viewOffsets[viewIndex].y);
	float xoff = (ed - focalDist) * viewOffsets[viewIndex].x * viewAmt;
	int2 writeCoords = viewPositions[viewIndex].xy + coords.xy;
	writeCoords.x += int((xoff * viewSize.x) / (perspw * ed)); // times texture width

	float oldDepth = ResultDepth.Load(writeCoords);
#if defined(BLEND_VIEWS)
	if (abs(oldDepth - d) < 0.02) 
        { 
		Result[writeCoords] = c * viewOffsets[viewIndex].y + Result.Load(writeCoords) * (1.0 - viewOffsets[viewIndex].y); 
	} else 
#endif
	if (d > oldDepth &&
		writeCoords.x > viewPositions[viewIndex].x &&
		writeCoords.x < viewPositions[viewIndex].x + viewSize.x)
	{
		Result[writeCoords] = c; 
		// Result[writeCoords] = float4(1,0,0,1); 
		ResultDepth[writeCoords] = d; 
	}
}
  • 空洞填补函数
[numthreads(TX,TY,TZ)]
void FillGaps (uint3 id : SV_DispatchThreadID)
{
	int2 co = viewPositions[id.z].xy + id.xy;
	for (int s = 1; s <= 2; s+=1) 
       {
		float farPortion = 0.1;
		float d  = ResultDepth.Load(co.xy);
		float dl = ResultDepth.Load(co.xy + int2(-s, 0));
		float dr = ResultDepth.Load(co.xy + int2( s, 0));
		if (abs(d - dl) > farPortion && abs(d - dr) > farPortion) 
               {
			Result[co.xy] = Result.Load(co.xy + int2(s, 0));
			return;
		}

		dl = ResultDepth.Load(co.xy + int2( 0, s));
		dr = ResultDepth.Load(co.xy + int2( 0,-s));
		if (abs(d - dl) > farPortion && abs(d - dr) > farPortion)
                {
			Result[co.xy] = Result.Load(co.xy + int2(0, s));
			return;
		}
}

[文件:HoloplaySDK-1.2.1.unitypackage]

体数据立体渲染[编辑]

适应于三维显示的实时体渲染是由邢树军提出,并应用到三维显示设备上。

它的实现过程为:根据光场显示视点编码结果,对光线进行错且变换,然后投射经过错切的光线。光线和体数据的包围盒进行求交运算,得到光线进入和穿出体数据的位置。
然后在进入点和穿出点投射光线用于颜色积分。

QQ截图20200301191257.png

  • 体渲染透镜光场代码实现
void main() {
	vec3 frontPos;
	vec3 backPos;
	//利用modelView矩阵获得
	vec3  posp = vec3(viewMatrix_[3]);//垂直屏幕方向的矢量
	float scale = length(posp) / (23.0 - 3.1);//以为物体中心为基准放大缩小
	vec2  ScreenCoord = gl_FragCoord.xy - vec2(0.5);
	int   scx = int(83 / 2) - int(ScreenCoord.x) % 83; //x方向视点序号-44~44
	int   scy = int(83 / 2) - int(ScreenCoord.y - 20) % 83; //y方向视点序号
	vec2  viewNum = vec2(scx, scy);
	float pitchCam = 0.193*scale;//相机之间的间距 随scale的变化而变化
	vec2  camPosInCamCor = viewNum * pitchCam;//相机起始点的位置的xy坐标
	vec3  RayOrigInCamera = vec3(camPosInCamCor, 0);//视点的位置
	vec2 p = gl_FragCoord.xy * screenDimRCP_;
	vec4 wGeom = vec4(2.0*p - 1.0, -1.0, 1.0);  // ????? NDC ????归一化设备坐标系 -1~1之间
	// reverse perspective division by w (which is equal to the camera-space z)
	float origZG = 2.0*far_*near_ / ((far_ + near_) - wGeom.z*(far_ - near_));
	wGeom *= origZG;
	//把投影坐标系下的点换算到相机坐标系下点的
	vec3 posInCameraCoord = (projectionMatrixInverse_ * wGeom).xyz / near_ *23.0*scale;
	//相机坐标系下终点的位置
	vec3 endposInCam = posInCameraCoord + normalize(posInCameraCoord - RayOrigInCamera);
	//世界坐标系下点和终点的位置
	vec4 posInWorld = viewMatrixInverse_ * vec4(posInCameraCoord, 1.0);
	vec4 endposInWorld = viewMatrixInverse_ * vec4(endposInCam, 1.0);
	vec3 frontPosNew = worldToTex(posInWorld.xyz / posInWorld.w, volumeStruct_);
	vec3 backPosNew = worldToTex(endposInWorld.xyz / endposInWorld.w, volumeStruct_);
	vec3 raydirtmp = normalize(backPosNew - frontPosNew);
	if ((frontPosNew.x > 1.0 || frontPosNew.x<0.0) || (frontPosNew.y>1.0 || frontPosNew.y<0.0) || (frontPosNew.z>1.0 || frontPosNew.z < 0.0))
	{
		frontPosNew = backPosNew;//frontPosNew -3.0*raydirtmp;
	}
	vec3 nearfar = rayIntersectionWithBox(frontPosNew, raydirtmp);
	if (1.0 == nearfar.z)
	{
		frontPos = frontPosNew + raydirtmp*nearfar.x;
		backPos = frontPosNew + raydirtmp*nearfar.y;
	}
	else
	{
		frontPos = frontPosNew;
		backPos = backPosNew;
	}
	// determine whether the ray has to be casted
	if (frontPos == backPos)
		// background needs no raycasting
		discard;
	else
		// fragCoords are lying inside the bounding box
		rayTraversal(frontPos, backPos);
	FragData0 = result;
}

评价指标[编辑]

渲染质量:电影画质,游戏画质。

PSNR[编辑]

RSNR是“Peak Signal to Noise Ratio”的缩写,即峰值信噪比,是一种评价图像的客观标准,它具有局限性,一般是用于最大值信号和背景噪音之间的一个工程项目。

通常在经过影像压缩之后,输出的影像都会在某种程度与原始影像不同。为了衡量经过处理后的影像品质,我们通常会参考PSNR值来衡量某个处理程序能否令人满意。

它是原图像与被处理图像之间的均方误差相对于(2^n-1)^2的对数值(信号最大值的平方,n是每个采样值的比特数),它的单位是dB。

公式如下:

[math]MSE=\frac{1}{mn}\sum\limits_{i=0}^{m-1}{\sum\limits_{j=o}^{n-1}{{{\left\| I(i,j)-K(i,j) \right\|}^{2}}}}[/math]


[math]PSNR=10\cdot {{\log }_{10}}(\frac{MAX_{I}^{2}}{MSE})=20\cdot {{\log }_{10}}(\frac{MAX}{\sqrt{MSE}})[/math]


%matlab PSNR代码

ref = imread('pout.tif');
A = imnoise(ref,'salt & pepper', 0.02);

peaksnr = psnr(A,ref)
// C代码
double getPSNR(const Mat& I1, const Mat& I2)
{
    Mat s1;
    absdiff(I1, I2, s1);       // |I1 - I2|
    s1.convertTo(s1, CV_32F);  // cannot make a square on 8 bits
    s1 = s1.mul(s1);           // |I1 - I2|^2
 
    Scalar s = sum(s1);         // sum elements per channel
 
    double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels
 
    if( sse <= 1e-10) // for small values return zero
        return 0;
    else
    {
        double  mse =sse /(double)(I1.channels() * I1.total());
        double psnr = 10.0*log10((255*255)/mse);
        return psnr;
    }
}

PSNR是最普遍,最广泛使用的评鉴画质的客观量测法,不过许多实验结果都显示,PSNR的分数无法和人眼看到的视觉品质完全一致,有可能PSNR较高者看起来反而比PSNR较低者差。这是因为人眼的视觉对于误差的敏感度并不是绝对的,其感知结果会受到许多因素的影响而产生变化(例如:人眼对空间频率较低的对比差异敏感度较高,人眼对亮度对比差异的敏感度较色度高,人眼对一个区域的感知结果会受到其周围邻近区域的影响)。 在三维显示中能够使用到PSNR的地方就是重建像的和原像之间的差异。此时,就需要拿对应视点的二维渲染结果和在该点视点得到的三维像求PSNR。另一种应用就是:一种采集模式得到的结果和另一种采集模式得到的结果之间的对比。比如,MDIBR中wrap的新视点和此视点真实的采集结果之间的差异。

SSIM[编辑]

SSIM(structural similarity index),结构相似性,是一种衡量两幅图像相似度的指标。该指标首先由德州大学奥斯丁分校的图像和视频工程实验室(Laboratory for Image and Video Engineering)提出。SSIM使用的两张图像中,一张为未经压缩的无失真图像,另一张为失真后的图像。

图像均值、方差和协方差[编辑]

[math]{{\mu }_{X}}=\frac{1}{H\times W}\sum\limits_{i=1}^{H}{\sum\limits_{j=1}^{W}{X(i,j)}}[/math]

[math]{{\mu }_{Y}}=\frac{1}{H\times W}\sum\limits_{i=1}^{H}{\sum\limits_{j=1}^{W}{Y(i,j)}}[/math]

[math]{{\sigma }_{X}}={{(\frac{1}{H\times W-1}\sum\limits_{i=1}^{H}{\sum\limits_{j=1}^{W}{(X(i,j)-{{\mu }_{X}})}})}^{0.5}}[/math]

[math]{{\sigma }_{Y}}={{(\frac{1}{H\times W-1}\sum\limits_{i=1}^{H}{\sum\limits_{j=1}^{W}{(Y(i,j)-{{\mu }_{Y}})}})}^{0.5}}[/math]

[math]{{\sigma }_{XY}}=\frac{1}{H\times W-1}\sum\limits_{i=1}^{H}{\sum\limits_{j=1}^{W}{(X(i,j)-{{\mu }_{X}})(Y(i,j)-{{\mu }_{Y}})}}[/math]

[math]{\mu}_{X}[/math],[math]{\mu}_{Y}[/math]分别代表图像X,图像Y的平均值;

[math]{{\sigma }_{X}}[/math],[math]{{\sigma }_{Y}}[/math]分别代表图像X,图像Y标准差;

[math]{{\sigma }_{XY}}[/math]代表图像X,图像Y的协方差。

三种对比方式[编辑]

亮度对比:[math]l(X,Y)=\frac{2{{\mu }_{X}}{{\mu }_{Y}}+{{C}_{1}}}{\mu _{X}^{2}+\mu _{Y}^{2}+{{C}_{1}}}[/math]

对比度对比:[math]c(X,Y)=\frac{2{{\sigma }_{X}}{{\sigma }_{Y}}+{{C}_{2}}}{\sigma _{X}^{2}+\sigma _{Y}^{2}+{{C}_{2}}}[/math]

结构对比:[math]s(X,Y)=\frac{2{{\sigma }_{XY}}+{{C}_{3}}}{{{\sigma }_{X}}{{\sigma }_{Y}}+{{C}_{3}}}[/math]

[math]{{C}_{1}}[/math],[math]{{C}_{2}}[/math],[math]{{C}_{3}}[/math]为常数,避免分母为0带来的系统错误。

公式推导[编辑]

[math]SSIM(X,Y)={{l}^{\alpha }}(X,Y){{c}^{\beta }}(X,Y){{s}^{\gamma }}(X,Y)[/math]

一般取 [math]\alpha =\beta =\gamma =1,{{C}_{3}}={{C}_{2}}/2[/math],公式可简化为: [math]SSIM(X,Y)=\frac{(2{{\mu }_{X}}{{\mu }_{Y}}+{{C}_{1}})(2{{\sigma }_{xy}}+{{C}_{2}})}{(\mu _{X}^{2}+\mu _{Y}^{2}+{{C}_{1}})(\sigma _{X}^{2}+\sigma _{Y}^{2}+{{C}_{2}})}[/math]

结构相似度指数从图像组成的角度将结构信息定义为独立于亮度、对比度的,反映场景中物体结构的属性,并将失真建模为亮度、对比度和结构三个不同因素的组合。用均值作为亮度的估计,标准差作为对比度的估计,协方差作为结构相似程度的度量。 SSIM侧重的是两个图像之间结构化的差异,是从整体上对图像的一种评价标准。而PSNR则是从图像具体像素之间的差异作为评价标准的。因此,需要根据所需要论证的内容合理选择。

特性[编辑]

  1. SSIM具有对称性,即SSIM(x,y)=SSIM(y,x)
  2. SSIM是一个0到1之间的数,越大表示输出图像和无失真图像的差距越小,即图像质量越好。当两幅图像一模一样时,SSIM=1。

代码[编辑]

%matlab代码
ref = imread('pout.tif');
A = imread('pin.tif');
ssimval = ssim(A,ref) 

立体渲染的知识[编辑]

光栅化渲染[编辑]

光线投射和光线跟踪渲染[编辑]

光线投射(Ray casting)[编辑]

正向投射。从图像的每一个像素,沿视线方向发射光线,光线穿越整个图像序列,并在这个过程中,对图像序列进行采样获取颜色信息,同时依据光线吸收模型将颜色值进行累加,直至光线穿越整个图像序列,最后得到的颜色值就是渲染图像的颜色。

光线跟踪(Ray tracing)[编辑]

逆向跟踪。沿着到达视点的光线的反方向跟踪,经过屏幕上每一个象素,找出与视线相交的物体表面点,并继续跟踪,找出影响点光强的所有光源,从而算出点上精确的光线强度。

递归式光线跟踪[编辑]
路径跟踪(Path tracing)[编辑]

视景体与光线的生成[编辑]

非线性视景体[编辑]

混合渲染[编辑]

混合渲染既可以是光栅化渲染与基于图像渲染的结合,也可以是光栅化渲染与光线跟踪、光线投射渲染的结合。

DIBR[编辑]

基于深度图像渲染(DIBR)方法是目前应用最广泛的虚拟视点合成方法,它可以利用一个视点的参考视点的彩色图像及其相对应的深度信息来生成其余视点的图像,减少了存储空间,进而节省了传输带宽。 基于深度图像渲染的虚拟视点合成方法系统基本框架如图所示,首先以参考视点的彩色图像和其对应处理后的深度图像作为系统的输入,后经过3D变形(3D warping)算法和空洞填补算法,渲染合成最终的虚拟视点图像。

   基于深度图像渲染的虚拟视点合成方法系统基本框架

在利用DIBR算法生成虚拟视点的过程中,出现信息的空洞是不可避免的,另外,还会出现重采样、重叠以及伪影的问题,严重影响虚拟视点图像质量,并且算法重复性高,渲染实时性较差,因此算法效率也是亟待解决的问题之一。

MDBIR[编辑]

Real-Time Rendering Method of Depth-Image-Based Multiple Reference Views for Integral Imaging Display 10.1109/ACCESS.2019.2956102

多机同步渲染[编辑]

相关本子[编辑]

本子