如何在平面和三维矩阵之间找到交点平面

时间:2015-05-24 00:03:46

标签: matlab matrix geometry

如果我有一堆图像并且尺寸正在跟随,

size(M) = [256 256 124];

我有3个点,它们的坐标是,

coor_a = [100,100,124];
coor_b = [256,156,0];
coor_c = [156,256,0];

如何从由3个点定义的平面相交的M创建点的图像?

2 个答案:

答案 0 :(得分:3)

首先,你可以注意到,如果你在(三维)欧几里德(代数)空间中,那么你要做的就是找到一个平面和一个格子之间的交点。

你所拥有的是你的矩阵(M),其大小定义了格子。

然后,因为3个非共线点定义了一个独特的平面(在3维空间中),所以你有一个独特的平面,但你必须想出一个更好的平面描述来找到它与晶格。

注意:在其他任何事情之前,您需要将您的点重新定义为正确的列向量:

coor_a = [100 ; 100 ; 124];
coor_b = [256 ; 156 ; 0];
coor_c = [156 ; 256 ; 0];

现在,首先,我们可以通过使用您提供的3个平面点中的两对点,为3-D平面的2-D表面定义任意一对矢量基数:

u = (corr_b - corr_a);
v = (corr_c - corr_b);

现在,uv定义了平面的流形空间的基矢量。所以,从概念上讲,你要做的就是找到你得到的格子点。来自uv的线性组合。这是因为一个平面实际上是一个基本的线性流形,这意味着它也可以被认为是一个函数:

P = f(u, v) = au + bv

其中P是飞机上的任何一点。

现在,因为您知道M是具有以下域集的矩阵点阵(Set Notation):

e1 = [0, 255]
e2 = [0, 255]
e3 = [0, 123]

你实际上可以将格子中的所有点都作为(MATLAB代码):

X, Y, Z = meshgrid( 0:1:255, 0:1:255, 0:1:123 );

获得meshgrid索引后,您可以将矩阵展平为带有冒号索引的向量,然后您可以创建一个A的新矩阵3 x (m • n • p),我们已经拥有M { {1}}大小为m x n x p

A = [ X(:); Y(:); Z(:) ];

因为您的矩阵M不大,所以这不会造成内存问题。

我们现在可以回顾P并将P定义为矢量符号中的线性方程式(MATLAB表示法):

P = ( (a * u) + (b * v) );

我们想要的是i的所有值,其中以下是真实的:

A(i) = ( (a * u) + (b * v) );

但这是MATLAB,所以我们希望利用线性代数运算并避免迭代进行矢量化。

我们正在构建的内容被称为" Hesse Normal Form"平面的代数方程:

http://en.wikipedia.org/wiki/Hesse_normal_form

我们可以利用这样的事实:使用基向量我们可以找到平面的法向量:

n = cross( (corr_b - corr_a), (corr_c - corr_b) );

现在缺少的是到飞机d的距离,可以找到原始点矢量均值的范数:

d = norm( mean( [ corr_a ; corr_b ; corr_c ] ), 2 );

从Hesse表单中,这给了我们nd,所有缺失的是r,这是平面上格子中的点,所以我们{{1 }}值是位于平面上的r列。

现在我们可以在MATLAB中以矢量化形式进行以下计算,通过使用A作为行向量来获得格子中每个点与平面的距离(列向量的转置)并利用矩阵乘法

n

由于我们使用矩阵乘法,L = ( ( (n.') * A ) - d ); 变为L数组,其中每个条目都是1 x (m • n • p)的点积和n的列。 A处或附近的任何值 - 取决于您要使用的阈值 - 是平面中晶格中的点。

您可以使用0方法从A获取l的索引,并生成逻辑findNOT)以转换所有零到~1的所有非零值,其中0返回给定矩阵或向量的所有非零值的所有索引:

find

还有很多其他方法可以做到这一点,但我认为这种方法利用了代数和内置的MATLAB函数。如果您小心,您可以实际获取所有以前的命令,并在一行MATLAB代码中完成所有操作。阅读起来很可怕,所以最好将它们全部留作单独的行。

此外,这可以很容易地设置为一个函数,以便您输入3个点值和给定的晶格或晶格定义矩阵,然后您可以返回平面上的所有晶格点或返回表单中的距离向量i = find( ~L ); ,以便您可以准确地选择"关闭"根据您手头的问题,L可以接受实际平面上。

最后,为了明确,如果你想创建一个平面上所有点的单通道图像,你可以从以下位置获得点数组:

0

执行此操作后,您可以使用基本的ImPoints = A(:,i); 循环从M中提取每个点,并将for的值放在某个新的图像数组M中,即你会想要用零预构建。

请注意,I的列是ImPoints的行 - 列 - 通道索引,这意味着您需要执行以下操作:

M

您必须预先定义for j = [ 1 : 1 : NumPoints ] NewImIndex = SomeFunc( ImPoints, j ); I( NewImIndex ) = M( ImPoints(:,j) ); end; ,并提出首选方法,ISomeFunc的像素/数据放入新图片M。< / p>

答案 1 :(得分:1)

我适合飞机,然后找到最近的点。

%This is the inputs you provided
M = floor(256*rand(256, 256, 124));

a = [100, 100, 124];
b = [256, 156, 0];
c = [156, 256, 0];

% change from a set of triplets to x, y and z vectors
points = [a', b', c'];
x = points(1,:)';
y = points(2,:)';
z = points(3,:)';

%Use Matlab's plane fit function
[ft, ~] = fit( [x, y], z, 'poly11' );

%Get the size of the input matrix
[XExt, YExt, ZExt] = size(M);

%These will be the inputs in the plane
X = 0:XExt-1;
Y = 0:YExt-1;
[X, Y] = meshgrid(X, Y);

%Find the points closest to the plane
Z = round(ft(X, Y));

%Get the x, y, z points of the points on the plane which are also in the extent of M
x = X((Z > 0) & (Z < ZExt)) + 1;
y = Y((Z > 0) & (Z < ZExt)) + 1;
z = Z((Z > 0) & (Z < ZExt));

%Preallocate for the points on the plane
MPrime = zeros(size(z));

%Get the points, need the loop because otherwise Matlab throws an error
for i = 1:length(z)
    MPrime(i) = M(x(i), y(i), z(i));
end

%Final output is a N x 3 vector with the row, column, value
NewImage = [x, y, MPrime];

我希望这会有所帮助。