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

Eliminate skewing effect in combined track and zoom

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

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

执行此操作时,可以观察到纸张在 returns 居中之前滑出框架。这可能是最好的视觉解释,并保持二维:

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

我想要的效果是目标物体只靠近画面中心,不会后退。我想答案是通过某种方式改变变焦率(或移动速度,尽管我不喜欢这样)可能是所涉及距离的函数,或者人为调整缩放比例以使页面保持在框架中。我更愿意按照前一种方法帮助解决问题。


更新:

我认为一个答案可能是将操作的缩放部分分成两个阶段。让问题的参数通知导数函数,该函数产生渲染输出上目标中心和视口中心之间的距离,并找到最大的时间。对两个轴执行此操作并选择两者之间的时间:这是缩放阶段的边界。在第一阶段,缩放以适合图像边界内的纸张。在第二阶段,放大纸张以得到与之前相同的结果。

这在直觉上似乎更好,但我仍然有两个问题。毫无疑问,我可以在 t 处找到 d 的方程,但我的微积分很弱,我最终可能会采样最大​​值而不是生成逆找到它的功能,这是我真正喜欢的。我也不确定如何在两个最大值之间进行选择以找到边界时间(尽管这个问题可能没有 'right' 答案,但我并不担心)。任何对这两个问题的帮助,或对更广泛挑战的任何其他见解,我们都将非常感激。

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

我指的是真正的偏斜效果,英文叫做Rolling shutter: if you are obtaining image by moving real HW scanline camera (without TDI technology) 然后出现偏斜+模糊效果滑动扫描线...尝试制作从行驶中的汽车侧面 window 拍摄的照片图像会歪斜。

您描述的效果与偏斜无关,它只是一个数学问题"singularity"抱歉,我没有任何名称。

因为你的相机是 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 是您的视野非变焦相机...

[edit1] 将纸张滑入动画...

我最终得到了这个:

这里是 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(这就是它如此不稳定的原因)