Assign value to matrix using vector value as an index

Asked by Alex Zibitsker

Alex Zibitsker (view profile)

on 15 Jun 2019
Latest activity Commented on by Alex Zibitsker

Alex Zibitsker (view profile)

on 19 Jun 2019
Accepted Answer by Guillaume

Guillaume (view profile)

Will appreciate your help in the following problem.
Let's say I have a 3D matrix (Image):
A=zeros(3,3,3)
and I have a column vector with NaNs and numbers:
a=[NaN; 2; 3]
I want to assign to matrix A value of
B=[255, 100, 50]
such that the values of vector "a" provide the column indices for matrix A, NaN values means nothing is asigned. The result would be:
A=[0 0 0; 0 255 0; 0 0 255] [0 0 0; 0 100 0; 0 0 100] [0 0 0; 0 50 0; 0 0 50];
I use the following code, but it runs very long if I process N images in the video..
Im=Some RGB Image; M=size(Im,1);
Vec_ind=Some column vector of size Mx1
B=[255, 100, 50];
for i=1:M
if ~isnan(Vec_ind(i,1))
j_im=Vec_ind(i,1);
Im(i,j_im,1)=B(1);
Im(i,j_im,2)=B(2);
Im(i,j_im,3)=B(3);
end

Guillaume (view profile)

on 15 Jun 2019

One solution:
[row, page] = ndgrid(1:numel(a), 1:numel(B)); %cartesian product of indices of a and B. Indicates which row and page the values go in
col = a(row); %matching destination column
assignee = B(page); %matching value to assign
tokeep = ~isnan(col);
A(sub2ind(size(A), row(tokeep), col(tokeep), page(tokeep))) = assignee(tokeep)

Alex Zibitsker

Alex Zibitsker (view profile)

on 15 Jun 2019
Works perfect. Thanks a lot!
Is it possbile with the same approach to assign the B values according to a range of columns, instead of a=[nan; 2; 3]; a_tag=[nan nan; 1, 2; 2, 3]?
Such that
A=[0 0 0; 255 255 0; 0 255 255] [0 0 0; 100 100 0; 0 100 100] [0 0 0; 50 50 0; 0 50 50];
With just replacing "a" as "a_tag" it doesn't work unfortunatelly
Guillaume

Guillaume (view profile)

on 16 Jun 2019
The idea is to build 3 arrays of destination row, column and page and replicate your B accordingly, then pass that to sub2ind. You can achieve that many ways.
row = repmat((1:size(a_tag, 1))', 1, size(a_tag, 2), numel(B))
col = repmat(a_tag, 1, 1, numel(B))
page = repmat(permute(1:numel(B), [1 3 2]), size(a_tag, 1), size(a_tag, 2))
assignee = B(page); %matching value to assign
tokeep = ~isnan(col);
A(sub2ind(size(A), row(tokeep), col(tokeep), page(tokeep))) = assignee(tokeep)
Alex Zibitsker

on 19 Jun 2019
Thanks!