将捕获的坐标转换为屏幕坐标

Al.*_*Al. 11 math image-processing linear-algebra computer-vision

我认为这可能是一个简单的数学问题,但我不知道现在发生了什么.

我在网络摄像头上捕捉"标记"的位置,我有一个标记及其坐标列表.四个标记是工作表面的外角,第五个(绿色)标记是小部件.像这样:

替代文字http://i37.tinypic.com/308cjtv.jpg

这是一些示例数据:

  • 左上标记(a = 98,b = 86)
  • 右上标记(c = 119,d = 416)
  • 左下标记(e = 583,f = 80)
  • 右下标记(g = 569,h = 409)
  • 小部件标记(x = 452,y = 318)

我想以某种方式将网络摄像头的小部件位置转换为坐标以显示在屏幕上,其中左上角是0,0而不是98,86并且以某种方式考虑了网络摄像头捕获的扭曲角度.

我甚至会从哪里开始?任何帮助赞赏

Jac*_*cob 19

为了计算变形,您需要计算输入矩形和屏幕四个角之间的单应性.

由于您的网络摄像头多边形似乎具有任意形状,因此可以使用完整的透视单应性将其转换为矩形.它并不复杂,您可以使用称为奇异值分解或SVD的数学函数(应该很容易获得)来解决它.

背景资料:

对于像这样的平面变换,您可以使用单应性来轻松地描述它们,这是一个3x3矩阵H,如果您的网络摄像头多边形上或其中的任何点,比如x1乘以H,即H*x1,我们将在屏幕上得到一个点(矩形) ,即x2.

现在,请注意这些点由它们的齐次坐标表示,这只是添加第三个坐标(其原因超出了本文的范围).因此,假设你的坐标X1分别为,(100,100),则齐表示将是一个列向量x1 = [100;100;1](其中,;代表一个新行).

好的,现在我们有8个同类矢量代表网络摄像头多边形上的4个点和屏幕的4个角 - 这就是我们计算单应性所需的全部内容.

计算单应性:

一点点数学: 我不打算进入数学,但简要说明这就是我们如何解决它:

我们知道3x3矩阵H,

H = 

h11 h12 h13
h21 h22 h23
h31 h32 h33

where hij represents the element in H at the ith row and the jth column
Run Code Online (Sandbox Code Playgroud)

可用于获取新的屏幕坐标x2 = H*x1.此外,结果将是这样的,x2 = [12;23;0.1]以便在屏幕坐标中获取它,我们通过第三个元素或者将X2 = (120,230)其标准化(12/0.1,23/0.1).

所以这意味着您的网络摄像头多边形(WP)中的每个点都可以乘以H(然后归一化)以获得您的屏幕坐标(SC),即

SC1 = H*WP1
SC2 = H*WP2
SC3 = H*WP3
SC4 = H*WP4
where SCi refers to the ith point in screen coordinates and 
      WPi means the same for the webcam polygon
Run Code Online (Sandbox Code Playgroud)

计算H :(快速无痛的解释)

伪代码:

for n = 1 to 4
{
    // WP_n refers to the 4th point in the webcam polygon 
    X = WP_n;

    // SC_n refers to the nth point in the screen coordinates
    // corresponding to the nth point in the webcam polygon

    // For example, WP_1 and SC_1 is the top-left point for the webcam
    // polygon and the screen coordinates respectively.

    x = SC_n(1); y = SC_n(2);

    // A is the matrix which we'll solve to get H
    // A(i,:) is the ith row of A

    // Here we're stacking 2 rows per point correspondence on A
    // X(i) is the ith element of the vector X (the webcam polygon coordinates, e.g. (120,230)
    A(2*n-1,:) = [0 0 0 -X(1) -X(2) -1 y*X(1) y*X(2) y];    
    A(2*n,:)   = [X(1) X(2) 1 0 0 0 -x*X(1) -x*X(2) -x];
}
Run Code Online (Sandbox Code Playgroud)

一旦你有了A,只需计算svd(A)哪个会将它分解为U,S,V T(这样A = USV T).对应于最小奇异值的向量是H(一旦将其重新整形为3x3矩阵).

使用H,您可以通过将其与H规范化相乘来检索窗口小部件标记位置的"变形"坐标.

例:

在您的特定示例中,如果我们假设您的屏幕尺寸为800x600,

WP =

    98   119   583   569
    86   416    80   409
     1     1     1     1

SC =

     0   799     0   799
     0     0   599   599
     1     1     1     1

where each column corresponds to corresponding points.
Run Code Online (Sandbox Code Playgroud)

然后我们得到:

H = 
   -0.0155   -1.2525  109.2306
   -0.6854    0.0436   63.4222
    0.0000    0.0001   -0.5692
Run Code Online (Sandbox Code Playgroud)

同样,我不打算进入数学,但如果我们标准化Hh33,也就是将每个元素H通过-0.5692在上面的例子中,

H =
    0.0272    2.2004 -191.9061
    1.2042   -0.0766 -111.4258
   -0.0000   -0.0002    1.0000
Run Code Online (Sandbox Code Playgroud)

这让我们对转型有了很多了解.

  • [-191.9061;-111.4258] 定义点的平移(以像素为单位)
  • [0.0272 2.2004;1.2042 -0.0766]定义仿射变换(基本上是缩放和旋转).
  • 最后1.0000是因为我们缩放H通过它,
  • [-0.0000 -0.0002] 表示网络摄像头多边形的投影变换.

此外,您可以检查H我的乘法是否准确,SC = H*WP并将每列与其最后一个元素标准化:

SC = H*WP    

    0.0000 -413.6395         0 -411.8448
   -0.0000    0.0000 -332.7016 -308.7547
   -0.5580   -0.5177   -0.5554   -0.5155
Run Code Online (Sandbox Code Playgroud)

将每一列中,由它的最后一个元素(例如,在第2栏,-413.6395/-0.51770/-0.5177):

SC
   -0.0000  799.0000         0  799.0000
    0.0000   -0.0000  599.0000  599.0000
    1.0000    1.0000    1.0000    1.0000
Run Code Online (Sandbox Code Playgroud)

这是期望的结果.

小部件坐标:

现在,您的窗口小部件坐标也可以进行转换H*[452;318;1](在规范化之后)(561.4161,440.9433).

所以,这是翘曲后的样子: 扭曲

如您所见,绿色+表示变形后的小部件点.

笔记:

  1. 这篇文章中有一些很好的图片解释了单应性.
  2. 你可以在这里玩转换矩阵

MATLAB代码:

WP =[
    98   119   583   569
    86   416    80   409
     1     1     1     1
     ];

SC =[
     0   799     0   799
     0     0   599   599
     1     1     1     1
     ];    

A = zeros(8,9);  

for i = 1 : 4     
    X = WP(:,i);    
    x = SC(1,i); y = SC(2,i);        
    A(2*i-1,:) = [0 0 0 -X(1) -X(2) -1 y*X(1) y*X(2) y];        
    A(2*i,:)   = [X(1) X(2) 1 0 0 0 -x*X(1) -x*X(2) -x];
end

[U S V] = svd(A);

H = transpose(reshape(V(:,end),[3 3]));
H = H/H(3,3);
Run Code Online (Sandbox Code Playgroud)

一个

       0           0           0         -98         -86          -1           0           0           0
      98          86           1           0           0           0           0           0           0
       0           0           0        -119        -416          -1           0           0           0
     119         416           1           0           0           0      -95081     -332384        -799
       0           0           0        -583         -80          -1      349217       47920         599
     583          80           1           0           0           0           0           0           0
       0           0           0        -569        -409          -1      340831      244991         599
     569         409           1           0           0           0     -454631     -326791        -799
Run Code Online (Sandbox Code Playgroud)


Ben*_*n S 0

由于您的输入区域不是与屏幕具有相同纵横比的矩形,因此您必须应用某种转换来进行映射。

我要做的就是获取内点相对于外侧的比例,并将其映射到屏幕的相同比例。

为此,请计算内部点上方、下方、左侧和右侧的可用空间量,并使用该比率找出该点在屏幕中的位置。

替代文本http://img230.imageshack.us/img230/5301/mapkg.png

获得测量结果后,将内部点放置在:

x = left / (left + right)
y = above / (above + below)
Run Code Online (Sandbox Code Playgroud)

这样,无论网络摄像头框架如何倾斜,您仍然可以映射到屏幕上的完整规则矩形。