消除组合跟踪和缩放中的倾斜效果
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
(这就是它如此不稳定的原因)
我正在为 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
(这就是它如此不稳定的原因)