bsxfun vs repmat 使用不同大小的矩阵输入来匹配索引
bsxfun vs repmat using different sized matrix inputs to match indices
我知道已经有很多关于 bsxfun
应该比 repmat
更快的问题,所以我希望这个问题不会太多余。
我正在使用带有 repmat 的短代码。此代码的目的是识别 A
和 B
之间的索引,其中行向量相同,因此我可以稍后删除它们,但是使用 repmat
使用 Matlab R2016a 花费的时间太长。
[~,i] = min(abs(dot(A',repmat(B,length(A),1)')./sqrt(sum(A'.^2))./norm(B)-1));
这里的A
和B
不一定是一样大的,所以用repmat
好像总的来说还是不行。目前 A
和 B
的大小分别为 8020x3 和 21615x3。我发现这种使 A
和 B
大小相同的方法有效,但我也对其他方法持开放态度。
if isequal(size(A),size(B))==1
else
a = size(A,1);
b = size(B,1);
if a<b
A = [A;nan(abs(B-A),3)];
else
B = [B;nan(abs(B-A),3)];
end
end
我正在查看 bsxfun
文档和这个 Mathworks 网站 https://www.mathworks.com/matlabcentral/answers/297088-speed-up-indexing-repmat-operation,看来我应该可以用 bsxfun(@times, B, length(A))
替换 repmat(B,length(A),1)'
,但他们确实这样做了没有输出相同的最终数组,所以我一定是做错了什么。
如果可能的话,我想修改上面的代码,以便计算时间更少,并且如果可能的话,A
和 B
的大小也不同,如上面给出的那样。如有必要,我仍然可以使用相同大小的 A
和 B
,但它们都会更大,在本例中为 571000x3,因此计算也将因此花费更长的时间。
加法:
评论里讨论了 intersect
行不行。从理论上讲,它应该因为 A
(黑色)和 B
使用函数 inpolyhedron
https://www.mathworks.com/matlabcentral/fileexchange/37856-inpolyhedron-are-points-inside-a-triangulated-volume-#comments. For some reason, the output of inpolyhedron
is a set of the points within the isosurface with some scattered points outside as well. When using inpolyhedron
to find the values outside the isosurface, these "extra" scattered points are not included in the set B
, so intersect
finds an empty set when inputting A
and B
.
原来 inpolyhedron
的创建者有一个 "patch" 主要纠正了这个问题。
本质上你需要将点移动一点点。
假设我所有的点都在一个名为 TestPoints
的数组中。
TestPoints = combvec(x',y',z')'; % x, y, and z are column vectors
NudgedPoints = TestPoints + repmat([1e-10 1e-10 0],length(TestPoints),1);
根据数据创建一个包含面和顶点的曲面
[F,V] = isosurface(X,Y,Z,A,-3); % you can use any value, and X, Y, and Z are positions from a meshgrid
in = inpolyhedron(F,V,NudgedPoints,'FlipNormals',false);
TestPoints_in = TestPoints(in,:);
此解决方案的所有功劳都归功于 inpolyhedron
的创建者 Sven。你可以联系他here.
我知道已经有很多关于 bsxfun
应该比 repmat
更快的问题,所以我希望这个问题不会太多余。
我正在使用带有 repmat 的短代码。此代码的目的是识别 A
和 B
之间的索引,其中行向量相同,因此我可以稍后删除它们,但是使用 repmat
使用 Matlab R2016a 花费的时间太长。
[~,i] = min(abs(dot(A',repmat(B,length(A),1)')./sqrt(sum(A'.^2))./norm(B)-1));
这里的A
和B
不一定是一样大的,所以用repmat
好像总的来说还是不行。目前 A
和 B
的大小分别为 8020x3 和 21615x3。我发现这种使 A
和 B
大小相同的方法有效,但我也对其他方法持开放态度。
if isequal(size(A),size(B))==1
else
a = size(A,1);
b = size(B,1);
if a<b
A = [A;nan(abs(B-A),3)];
else
B = [B;nan(abs(B-A),3)];
end
end
我正在查看 bsxfun
文档和这个 Mathworks 网站 https://www.mathworks.com/matlabcentral/answers/297088-speed-up-indexing-repmat-operation,看来我应该可以用 bsxfun(@times, B, length(A))
替换 repmat(B,length(A),1)'
,但他们确实这样做了没有输出相同的最终数组,所以我一定是做错了什么。
如果可能的话,我想修改上面的代码,以便计算时间更少,并且如果可能的话,A
和 B
的大小也不同,如上面给出的那样。如有必要,我仍然可以使用相同大小的 A
和 B
,但它们都会更大,在本例中为 571000x3,因此计算也将因此花费更长的时间。
加法:
评论里讨论了 intersect
行不行。从理论上讲,它应该因为 A
(黑色)和 B
使用函数 inpolyhedron
https://www.mathworks.com/matlabcentral/fileexchange/37856-inpolyhedron-are-points-inside-a-triangulated-volume-#comments. For some reason, the output of inpolyhedron
is a set of the points within the isosurface with some scattered points outside as well. When using inpolyhedron
to find the values outside the isosurface, these "extra" scattered points are not included in the set B
, so intersect
finds an empty set when inputting A
and B
.
原来 inpolyhedron
的创建者有一个 "patch" 主要纠正了这个问题。
本质上你需要将点移动一点点。
假设我所有的点都在一个名为 TestPoints
的数组中。
TestPoints = combvec(x',y',z')'; % x, y, and z are column vectors
NudgedPoints = TestPoints + repmat([1e-10 1e-10 0],length(TestPoints),1);
根据数据创建一个包含面和顶点的曲面
[F,V] = isosurface(X,Y,Z,A,-3); % you can use any value, and X, Y, and Z are positions from a meshgrid
in = inpolyhedron(F,V,NudgedPoints,'FlipNormals',false);
TestPoints_in = TestPoints(in,:);
此解决方案的所有功劳都归功于 inpolyhedron
的创建者 Sven。你可以联系他here.