Make index of elements based on random values in another matrix
1 view (last 30 days)
Show older comments
I have the following two matrices, one of random numbers, and the other of a random integer 1-8:
X = rand(10,10);
r = round(0.5+rand(size(X))*8);
I want the numbers in matrix r to refer to adjacent elements in the matrix X as:
1 2 3
4 X(i,j) 5
6 7 8
and return the indices of those elements. I will avoid repeating elements by only working on every 3rd row and column (1:3:end,1:3:end). I want to use periodic boundary conditions.
So, how can I return the indices of the randomly selected neighbor of each element X(1:3:end,1:3:end)? It should return in a matrix of size(X(1:3:end,1:3:end))
The reason I want to do this is because I want to flip the elements in X between X(i,j) and a neighboring X with a row/column offset determined by the value in matrix r. So if r(i,j)=7, then I can use the index to make a new matrix X_new where X_new(i,j)=X(i+1,j). This needs to be fast, so I am trying to vectorize.
Thank you!!!
0 Comments
Accepted Answer
Guillaume
on 5 Oct 2014
Edited: Guillaume
on 6 Oct 2014
What you want to do is transform your r values into linear offsets into X. These linear offsets would be
-size(X, 1)-1 -1 size(X,1)-1
-size(X, 1) N/A size(X,1)
-size(X, 1)+1 1 size(X,1)+1
So:
offsets = [-size(X,1)-1 -1 size(X,1)-1 -size(X,1) size(X,1) -size(X,1)+1 1 size(X,1)+1];
roffsets = offsets(r);
You then just have to add these offsets to the linear indices of X:
xindices = reshape(1:numel(X), size(X));
swapindices = xindices + roffsets;
swapindices defines the index of each element to replace the original x element, for the whole matrice. You could just do:
newX = X(swapindices);
to get the new matrice. There will be problems at the edges of the matrix since there's no restriction to swap with columns (rows) 0 and numcol (numrow) + 1. You haven't specified what you want to do at the edges.
Note: you can generate r simply with:
r = randi(8, size(X));
2 Comments
Guillaume
on 6 Oct 2014
There are probably many ways to deal with the boundary. You could indeed pad the matrix. Another way would be to deal with in the creation of the linear indices. For the left and right edge, it's easy it's just a modulo operation. For the top and bottom edge, I would extend the indices of r so [9 10 11] means swap with bottom edge and [12 13 14] swap with top edge:
r = randi(8, size(X));
rt = r(1, :); rt(rt <= 3) = rt(rt <= 3) + 8; r(1, :) = rt;
rb = r(size(r, 1), :); rb(rb >= 6) = rb(rb >= 6) + 6; r(size(r, 1), :) = rb;
You then extend the offsets matrix to:
offsets = [-size(X,1)-1 -1 size(X,1)-1 -size(X,1) size(X,1) -size(X,1)+1 1 size(X,1)+1 -1 size(X,1)-1 2*size(X,1)-1 -2*size(X,1)+1 -size(X,1)+1 1];
The roffsets and swapindices calculation is the same:
roffsets = offsets(r);
xindices = reshape(1:numel(X), size(X));
swapindices = xindices + roffsets;
But before you use the indices you pass them through modulo:
swapindices = mod(swapindices-1, numel(X)) + 1;
newX = X(swapindices);
More Answers (1)
Image Analyst
on 5 Oct 2014
Not sure where the 7 comes into play in your last paragraph. And what are you doing? I didn't understand your algorithm. What do you do with the 3x3, or 7x7, window once you've extracted it? What I'm wondering is if you can use conv2(), imfilter(), or blockproc() to do what you want to do instead of manually scanning the array with the window yourself.
2 Comments
Image Analyst
on 6 Oct 2014
OK that's fine. Glad he got it all working for you and you accepted his answer. I just didn't see why, when you said " So if r(i,j)=7, then I can use the index to make a new matrix X_new where X_new(i,j)=X(i+1,j)" that 7 did not show up in the indexes for X_new or X, and how they would change if the r value was 13 or 42 or 123 or whatever, since i and j didn't have anything at all to do with 7.
I still don't see that you've said what you're going to do with X_new. And since you will have a different X_new at every location, I don't see why you'd need to call conv2() 8 times. For example if you were just going to sum the values in X_new, you could simply do
out = conv2(in, ones(3), 'same');
and do that just one time to process all possible X_news in the entire image.
See Also
Categories
Find more on Logical in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!