消除组合跟踪和缩放中的倾斜效果

问题描述 投票:0回答:1

我正在为 HTML5 Canvas 编写内容,将其用作视口,在其中保持中心原点和缩放级别。我想要跟踪并缩放到一个区域,但遇到了自然发生的效果,破坏了我试图获得的外观。这个问题涉及我如何在保持自然效果的同时减轻这种情况。

想象我在天花板上安装了一个向下的摄像头,而地板上的某个地方有一张纸。我沿着天花板以恒定的速度移动相机,直到它位于纸张上方,同时以线性速率缩放,以便纸张最终填充渲染的图像。这些动作同时发生。

执行此操作时,可以观察到纸张在返回中心之前滑出框架的效果。这可能最好用视觉来解释,并保持二维:

img

这看起来不太好看。考虑用户请求专注于某件事。他们的概念是,实体正在进入视野,奇怪的是,它似乎在靠近之前先离开了。

我希望的效果是目标物体只接近画面的中心,并且永远不会后退。我想答案是以某种方式改变缩放速率(或移动速率,尽管我不喜欢这个) )大概是所涉及距离的函数,或者人为调整缩放以使页面保持在框架中。我更希望获得与前一种方法类似的解决方案的帮助。

graphics image-rendering
1个回答
0
投票

哦,所以你得到了一个不涉及硬件相机的软件实现....

我指的是真正的倾斜效果,英文称为滚动快门:如果您通过移动真实的硬件扫描线相机获取图像(没有TDI技术),那么滑动扫描时会出现倾斜+模糊效果线条...尝试从行驶中的汽车的侧窗拍摄照片,图像会倾斜。

您所描述的效果与偏斜无关,它只是一个数学“奇点”,抱歉我没有任何名称。

由于您的相机是 SW,只有您可以根据自己的喜好影响平移和缩放,因此我只需根据相机

FOV
zoom 位置计算
pan
。我看是这样的:

所以:

 I. a = FOV / zoom
II. tan(0.5*a) = (x1-x0) / h
------------------------
zoom = 0.5*FOV/atan( (x1-x0) / h )

其中

h
是天花板高度,
x0
是相机(平移)位置,
x0
是纸张边缘位置,
FOV
是非变焦相机的视野...

[编辑1]将纸张滑入并动画...

我最终得到了这个:

这里是 C++/VCL 代码:

//---------------------------------------------------------------------------
double x0,x1,w=50,h=200,FOVx=60.0*M_PI/180.0,zoom,pan;
double t=0; // animation parameter <0,1>
//---------------------------------------------------------------------------
void TMain::draw()
    {
    if (!_redraw) return;

    // clear buffer
    bmp->Canvas->Brush->Color=clBlack;
    bmp->Canvas->FillRect(TRect(0,0,xs,ys));

    double y0,y1,dx;

    // position side view onto screen based on its size xs,ys
    y0=0.5*(ys-h);
    y1=y0+h;
    x0=0.5*xs;
    x1=x0+(h*tan(0.5*FOVx));
    // compute zoom,pan from t
    pan=(x1-x0+(0.5*w))*t;
    zoom=0.5*FOVx/atan(((1.0-t)*(x1-x0)+(0.5*w*t))/h);
    // scene
    bmp->Canvas->Pen->Color=clBlue;
    bmp->Canvas->MoveTo( 0,y0);
    bmp->Canvas->LineTo(xs,y0);
    bmp->Canvas->MoveTo( 0,y1);
    bmp->Canvas->LineTo(xs,y1);
    // paper
    bmp->Canvas->Pen->Color=clRed;
    bmp->Canvas->MoveTo(x1,y1);
    bmp->Canvas->LineTo(x1+w,y1);
    // FOVx
    dx=h*tan(0.5*FOVx/zoom);
    bmp->Canvas->Pen->Color=clAqua;
    bmp->Canvas->MoveTo(x0+pan-dx,y1);
    bmp->Canvas->LineTo(x0+pan,y0);
    bmp->Canvas->LineTo(x0+pan+dx,y1);
    // points
    dx=4;
    bmp->Canvas->Pen->Color=clAqua;
    bmp->Canvas->Brush->Color=clBlue;
    bmp->Canvas->Ellipse(x0-dx,y0-dx,x0+dx,y0+dx);
    bmp->Canvas->Ellipse(x0+pan-dx,y0-dx,x0+pan+dx,y0+dx);
    bmp->Canvas->Ellipse(x1-dx,y1-dx,x1+dx,y1+dx);
    bmp->Canvas->Font->Color=clYellow;
    bmp->Canvas->Brush->Style=bsClear;
    bmp->Canvas->TextOutA(x0,y0-20,"x0");
    bmp->Canvas->TextOutA(x0+pan+20,y0+5,"x0+pan");
    bmp->Canvas->TextOutA(x1,y1+5,"x1");
    bmp->Canvas->Brush->Style=bsSolid;

    // render backbuffer
    Main->Canvas->Draw(0,0,bmp);
    _redraw=false;
    }
//---------------------------------------------------------------------------

如果您忽略渲染内容,这对您来说很重要:

pan=(x1-x0+(0.5*w))*t;
zoom=0.5*FOVx/atan(((1.0-t)*(x1-x0)+(0.5*w*t))/h);

所以我稍微改变了

x1
(它是纸张的另一边)的含义,而不是上面原始方程中的
x1
,我使用了
x1+w*t
,这意味着纸张在开始时不在视图中(
t=0
) )但是它从外面接触它并且当
(t=1)
时它完全在视野中。剩下的只是替换的结果...

w
是纸张宽度,
t=<0.0,1.0>
是动画参数,其他值没有改变意义...

动画只是在我的 GIF 编码器记录的 150 毫秒计时器中将

t
增加
0.02
(这就是它如此不稳定的原因)

© www.soinside.com 2019 - 2024. All rights reserved.