Matlab 将单应性应用于一组点(不是图像)
Matlab applying homography to an set of points (not an image)
我想做的是将给定的单应性应用于一组点 (x,y)(而不是将其应用于图像的通常用例。)
我将单应性存储为 3x3 维矩阵:
H =
1.06 -0.56 77.55
-0.02 0.74 28.34
0.02 -0.01 1.00
我有一套要点。例如:
pts = [x1,y1 ; x2,y2 ; x3,y3 ;x4,y4 ; ...];
如何将 H
应用到 pts
?
我知道将它应用于图像非常简单,例如:
img = imread('pathtofile\file.png');
tform = projective2d(H);
img2 = imwarp(img, tform);
但是点列表是否有等同于 imwrap
的东西?
使用 projective2d
class 中的 transformPointsForward
函数。但是,请注意,您指定的单应性假定您将单应性与输入点预乘。这是显而易见的,因为最后一列看起来像翻译向量。也就是说,给定矩阵 H
和点矩阵 P
,其中每个 列 是增广形式的一个点,其中第三行的值为1、可以通过以下方式实现点的翘曲:
out = H * P;
您最终将获得扭曲点 - 每列一个点。注意坐标是齐次的形式,所以你必须取第三个坐标,将每列中对应的第一个和第二个值除以它们的第三个坐标。
out(1,:) = out(1,:) ./ out(3,:);
out(2,:) = out(2,:) ./ out(3,:);
out = out(1:2,:);
但是,使用 transformPointsForward
假设您正在 post-乘以 矩阵,因此您必须转置单应矩阵。这是由于 MATLAB 的列优先偏好,因此单应矩阵的系数按列优先顺序读出。但是,您可以保留点矩阵不变。
因此,当您指定单应性 H
时,您必须先 转置 它,然后再创建 projective2d
实例。完成后,您可以使用 transformPointsForward
.
tform = projective2d(H.');
out = transformPointsForward(tform, pts);
函数的第一个输入是您创建的投影变换,第二个输入是点矩阵 - 每行一个。输出将是一个与 pts
大小相同的矩阵,但每一行都是给定 tform
.
每个输入点的转换版本
但是,如果您想弄清楚这是如何在幕后完成的,那么您可以在没有 transformPointsForward
的情况下自己实现同样的事情。这是通过首先转置 pts
,用 ones
的行向量增加它,乘以 H
然后将结果转置为相同大小来完成的。但是,您应该注意这些扭曲坐标是齐次形式的,因此您必须按照我们之前指定的方式进行除法:
pts_aug = [pts.'; ones(1, size(pts, 1))];
out = (H * pts_aug).';
out = bsxfun(@rdivide, out(:,1:2), out(:,3));
第一行执行增强,第二行执行扭曲,最后第三行执行我们谈到的除法。我决定使用 bsxfun
在一行中进行除法。但是在 MATLAB R2016b 及以后的版本中,我们可以利用广播:
out = out(:,1:2) ./ out(:,3);
作为一个简单的例子,让我们在 MATLAB 中定义您的 H
,然后让我们定义一堆随机点:
H =[1.06 -0.56 77.55; -0.02 0.74 28.34; 0.02 -0.01 1.00];
rng(123);
pts = randi(20, 4, 2);
我们将 H
定义为单应性,我为随机生成器播种,以便生成四个 2D 随机点,其中预期的最大值为 20。一行是一个点,就像您在问题中指定的那样。现在让我们确保此行为在两种方法之间是一致的:
% Method #1
tform = projective2d(H.');
out = transformPointsForward(tform, pts);
% Method #2
pts_aug = [pts.'; ones(1, size(pts, 1))];
out2 = (H * pts_aug).';
out2 = bsxfun(@rdivide, out2(:,1:2), out2(:,3));
out
和 out2
是输出扭曲点,显示它们我们得到:
>> format long g
>> out
out =
74.3274336283186 34.6548672566372
76.5728155339806 33.8640776699029
79.6111111111111 47.8222222222222
74.9363636363636 34.9636363636364
>> out2
out2 =
74.3274336283186 34.6548672566372
76.5728155339806 33.8640776699029
79.6111111111111 47.8222222222222
74.9363636363636 34.9636363636364
我想做的是将给定的单应性应用于一组点 (x,y)(而不是将其应用于图像的通常用例。)
我将单应性存储为 3x3 维矩阵:
H =
1.06 -0.56 77.55
-0.02 0.74 28.34
0.02 -0.01 1.00
我有一套要点。例如:
pts = [x1,y1 ; x2,y2 ; x3,y3 ;x4,y4 ; ...];
如何将 H
应用到 pts
?
我知道将它应用于图像非常简单,例如:
img = imread('pathtofile\file.png');
tform = projective2d(H);
img2 = imwarp(img, tform);
但是点列表是否有等同于 imwrap
的东西?
使用 projective2d
class 中的 transformPointsForward
函数。但是,请注意,您指定的单应性假定您将单应性与输入点预乘。这是显而易见的,因为最后一列看起来像翻译向量。也就是说,给定矩阵 H
和点矩阵 P
,其中每个 列 是增广形式的一个点,其中第三行的值为1、可以通过以下方式实现点的翘曲:
out = H * P;
您最终将获得扭曲点 - 每列一个点。注意坐标是齐次的形式,所以你必须取第三个坐标,将每列中对应的第一个和第二个值除以它们的第三个坐标。
out(1,:) = out(1,:) ./ out(3,:);
out(2,:) = out(2,:) ./ out(3,:);
out = out(1:2,:);
但是,使用 transformPointsForward
假设您正在 post-乘以 矩阵,因此您必须转置单应矩阵。这是由于 MATLAB 的列优先偏好,因此单应矩阵的系数按列优先顺序读出。但是,您可以保留点矩阵不变。
因此,当您指定单应性 H
时,您必须先 转置 它,然后再创建 projective2d
实例。完成后,您可以使用 transformPointsForward
.
tform = projective2d(H.');
out = transformPointsForward(tform, pts);
函数的第一个输入是您创建的投影变换,第二个输入是点矩阵 - 每行一个。输出将是一个与 pts
大小相同的矩阵,但每一行都是给定 tform
.
但是,如果您想弄清楚这是如何在幕后完成的,那么您可以在没有 transformPointsForward
的情况下自己实现同样的事情。这是通过首先转置 pts
,用 ones
的行向量增加它,乘以 H
然后将结果转置为相同大小来完成的。但是,您应该注意这些扭曲坐标是齐次形式的,因此您必须按照我们之前指定的方式进行除法:
pts_aug = [pts.'; ones(1, size(pts, 1))];
out = (H * pts_aug).';
out = bsxfun(@rdivide, out(:,1:2), out(:,3));
第一行执行增强,第二行执行扭曲,最后第三行执行我们谈到的除法。我决定使用 bsxfun
在一行中进行除法。但是在 MATLAB R2016b 及以后的版本中,我们可以利用广播:
out = out(:,1:2) ./ out(:,3);
作为一个简单的例子,让我们在 MATLAB 中定义您的 H
,然后让我们定义一堆随机点:
H =[1.06 -0.56 77.55; -0.02 0.74 28.34; 0.02 -0.01 1.00];
rng(123);
pts = randi(20, 4, 2);
我们将 H
定义为单应性,我为随机生成器播种,以便生成四个 2D 随机点,其中预期的最大值为 20。一行是一个点,就像您在问题中指定的那样。现在让我们确保此行为在两种方法之间是一致的:
% Method #1
tform = projective2d(H.');
out = transformPointsForward(tform, pts);
% Method #2
pts_aug = [pts.'; ones(1, size(pts, 1))];
out2 = (H * pts_aug).';
out2 = bsxfun(@rdivide, out2(:,1:2), out2(:,3));
out
和 out2
是输出扭曲点,显示它们我们得到:
>> format long g
>> out
out =
74.3274336283186 34.6548672566372
76.5728155339806 33.8640776699029
79.6111111111111 47.8222222222222
74.9363636363636 34.9636363636364
>> out2
out2 =
74.3274336283186 34.6548672566372
76.5728155339806 33.8640776699029
79.6111111111111 47.8222222222222
74.9363636363636 34.9636363636364