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

时间:2019-01-10 00:25:14

标签: graphics image-rendering

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

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

执行此操作时,可以观察到一种效果,使纸张在回到中心之前滑出框架。最好从视觉上进行解释,并保持在两个维度:

img

这不是一个很好的外观。考虑用户要求关注某事。他们的概念化是该实体正在进入视野,然后奇怪的是,它似乎先移开才靠近。

我想要的效果是目标对象仅接近框架的中心,而不会后退。我想答案是使缩放率(或移动率)变形。 ,尽管我不希望这样做),它可能是所涉及的距离的函数,或者人为地调整缩放比例,以使页面保持在框架中。理想情况下,我希望按照前一种方法为解决方案提供帮助。


更新:

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

从直觉上看,这似乎更好,但是我仍然有两个问题。我无疑可以在 t 处找到 d 的方程式,但是我的演算很弱,我可能最终会进行最大采样而不是产生一个反函数来找到它。是我真正想要的。我也不确定如何在两个最大值之间进行选择以找到边界时间(尽管可能对此问题没有“正确”的答案,这对我来说也就不那么麻烦了)。我们将非常感谢您对任何问题的帮助,或对更广泛挑战的任何其他见解。

1 个答案:

答案 0 :(得分:0)

好吧,所以您实现了不涉及硬件摄像机的软件实现....

我指的是英语中的真实偏斜效果,称为Rolling shutter:如果您通过移动真实的硬件扫描线摄像机(没有TDI technology)来获取图像,则偏斜+滑动扫描线时出现模糊效果...尝试从行驶中的汽车的侧窗拍摄照片,图像会偏斜。

您所描述的效果与偏斜无关,只是数学上的“奇异性”,对不起,我对此没有任何名字的建议。

由于您的摄像头是 SW ,因此您只能影响平移和缩放,因此我只需要根据摄像头 FOV 和{{ 1}}位置。我这样看:

overview

所以:

zoom

其中pan是最高高度, I. a = FOV / zoom II. tan(0.5*a) = (x1-x0) / h ------------------------ zoom = 0.5*FOV/atan( (x1-x0) / h ) 是摄像机(平移)位置,h是纸张边缘位置,x0是未缩放的视野相机...

[edit1]滑动纸张并播放动画...

我最终得到了这个

animation

这是 C ++ / VCL 代码:

x0

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

FOV

因此,我略微更改了//--------------------------------------------------------------------------- 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)是动画参数,其他所有值均未改变,表示...

动画只是在我的GIF编码器记录的150毫秒计时器中将w增加t=<0.0,1.0>(这就是为什么它如此断断续续的原因)