Borrar filtros
Borrar filtros

Split Volume Along 2D Surface

2 visualizaciones (últimos 30 días)
Johannes Rebling
Johannes Rebling el 18 de Abr. de 2020
Comentada: darova el 19 de Abr. de 2020
Hi everyone,
I have what I feel is a simple problem but I just can't find a fast, vectorized way to split a 3d volume along the z indicies defined in a matrix, as described below.
I have a volume [X Y Z] in which in find an arbitrary surface. This surface has the dimension [X Y] and the value at each positon in said surface tells me where to split my volume along z. Here is the naive for-loop approach, but it's sloooow (I have many volumes and they are much larger than in this example).
volume = rand(500,600,300);
surface = round(rand(500,600).*150+1);
tic;
[topVol,botVol] = split_volume(volume,splitDepth);
done(toc);
function [topVol,botVol] = split_volume(volData,Z)
[nX,nY,~] = size(volData);
topVol = volData;
botVol = volData;
for iX = 1:nX
for iY = 1:nY
zIdx = Z(iX,iY);
topVol(iX,iY,zIdx:end) = 0;
botVol(iX,iY,1:zIdx) = 0;
end
end
end
  2 comentarios
darova
darova el 18 de Abr. de 2020
Can you show the volume and surface?
Johannes Rebling
Johannes Rebling el 19 de Abr. de 2020
Editada: Johannes Rebling el 19 de Abr. de 2020
I am not sure what you mean. The volume can be any size, like in my working example aboe:
volume = rand(500,600,300);
Same for the "surface", it will always be the same size in x-y as the volume and can have any values between 1 and the number of elements in z in the volume (i.e. 1 to 300 in my example).
surface = round(rand(500,600).*150+1);

Iniciar sesión para comentar.

Respuesta aceptada

Johannes Rebling
Johannes Rebling el 18 de Abr. de 2020
I have found a somewhat vectorized solution that is 15 times faster than the native for loops and still 5 times faster than the optimized for loops.
If anyone has an even faster way, let me know!
My code as it might be usefull to someone doing the same:
tempVol = rand(500,500,800);
[nX,nY,nZ] = size(tempVol);
splitPlane = uint16(randi([round(nZ/2)-10 round(nZ/2)+10],[nX, nY])); % line to split along...
tic;
botVolKeep1 = split_volume_naive(nX,nY,nZ,splitPlane);
toc;
tic;
botVolKeep2 = split_volume_for(nX,nY,nZ,splitPlane);
toc;
tic;
botVolKeep3 = split_volume_fast(nX,nY,nZ,splitPlane);
toc;
isequal(botVolKeep1,botVolKeep2)
isequal(botVolKeep1,botVolKeep3)
function [botVolKeep] = split_volume_naive(nX,nY,nZ,splitPlane)
botVolKeep = ones(nX,nY,nZ);
for iX = 1:nX
for iY = 1:nY
zIdx = splitPlane(iX,iY);
botVolKeep(iX,iY,1:zIdx) = 0;
end
end
end
function [botVolKeep] = split_volume_for(nX,nY,nZ,splitPlane)
botVolKeep = true(nX,nY,nZ);
for iY = 1:nY
for iX = 1:nX
zIdx = splitPlane(iX,iY);
botVolKeep(iX,iY,1:zIdx) = false;
end
end
end
function [botVolKeep] = split_volume_fast(nX,nY,nZ,splitPlane)
linZIdx = uint16(repmat(1:nZ,[nY,1])); % array from 1:nZ with nY rows
botVolKeep = false([nY,nZ,nX]);
for iX = 1:nX
splitLine = splitPlane(iX,:)';
% t = linZIdx > splitLine;
botVolKeep(:,:,iX) = linZIdx > splitLine;
end
botVolKeep = permute(botVolKeep,[3 1 2]);
end

Más respuestas (1)

darova
darova el 19 de Abr. de 2020
See this madness
clc,clear
[x1,y1,z1] = meshgrid(1:10); % volume boundaries
[x2,y2] = meshgrid(1:0.5:10); % surface boundaries
[T,R] = cart2pol(x2,y2);
z2 = 10*sin(R)./R+5; % create surface
z11 = interp2(x2,y2,z2,x1,y1); % find 'Z' value for each volume point
ix = z1 > z11; % half of a volume
surf(x2,y2,z2)
hold on
plot3(x1(ix),y1(ix),z1(ix),'.r')
plot3(x1(~ix),y1(~ix),z1(~ix),'.g')
hold off
axis vis3d
  2 comentarios
Johannes Rebling
Johannes Rebling el 19 de Abr. de 2020
Thanks a lot for taking the time and providing a fully vectorized solution. It does indeed work and produces the same results as the naive double for-loop, but is only marginally faster and actually much slower than my other approaches.
For a800 x 800 x 400 volume (actually still smaller than the volumes I am processing), here is what I get on my fairly decent PC.
Naive for-loop implementation took 3.230 s.
Optimized for-loop implementation took 0.822 s (3.9 x faster).
Partially vectorized implementation took 0.292 s (11.1 x faster).
Fully vectorized implementation took 2.335 s (1.4 x faster).
Unfortunately, the meshgrid in 3d becomes quite slow and the fully vectorized approach also uses a lot more memory.
darova
darova el 19 de Abr. de 2020
Im out of ideas. It was my best

Iniciar sesión para comentar.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by