Calculating a partial cumulative sum for a square matrix - matlab

Let's say I have a square matrix M:
M = [0 0 0 0 0 1 9; 0 0 0 0 0 4 4; 0 0 1 1 6 1 1; 0 1 2 9 2 1 0; 2 1 8 3 2 0 0; 0 8 1 1 0 0 0; 14 2 0 1 0 0 0]
0 0 0 0 0 1 9
0 0 0 0 0 4 4
0 0 1 1 6 1 1
M = 0 1 2 9 2 1 0
2 1 8 3 2 0 0
0 8 1 1 0 0 0
14 2 0 1 0 0 0
Now I'd like to calculate two different cumulative sums: One that goes from the top of each column to the element of the column, that is a diagonal element of the matrix, and one that goes from the bottom of the column to the same diagonal element.
The resulting matrix M'should therefore be the following:
0 0 0 0 0 1 9
0 0 0 0 0 4 5
0 0 1 1 6 2 1
M' = 0 1 3 9 4 1 0
2 2 8 5 2 0 0
2 8 1 2 0 0 0
14 2 0 1 0 0 0
I hope the explanation of what I'm trying to achieve is comprehensible enough. Since my matrices are much larger than the one in this example, the calculation should be efficient as well...but so far I couldn't even figure out how to calculate it "inefficiently".

In one line using some flipping and the upper triangular function triu:
Mp = fliplr(triu(fliplr(cumsum(M)),1)) ...
+flipud(triu(cumsum(flipud(M)),1)) ...
+flipud(diag(diag(flipud(M))));

The following will do the job:
Mnew = fliplr(triu(cumsum(triu(fliplr(M)),1))) + flipud(triu(cumsum(triu(flipud(M)),1)));
Mnew = Mnew - fliplr(diag(diag(fliplr(Mnew)))) + fliplr(diag(diag(fliplr(M))));
But is it the fastest method?
I think logical indexing might get you there faster

Related

Linear span of a vector in MATLAB

I'm looking for a way to generate the spans of a given vector in MATLAB.
For example:
if a = [ 0 1 0 1] I need all vectors of the form [0 x 0 y], 1 <= x <= max1, 1 <= y <= max2,.
or if
a = [ 0 1 0 1 1 0] I need all vectors of the form [0 x 0 y z 0], 1 <= x <= max1, 1 <= y <= max2, 1<= z <= max3.
Note that the vector can have a variable number of 1's.
My first impression is that I would need a variable number of for loops, though I don't know if that is doable in MATLAB. Also any other ideas are welcome!
You don't need multiple for loops for this. The code below generates all required vectors as rows of a tall matrix. It actually creates the columns of the matrix one at a time. Each column will have numbers 1:m(i) arranged in the pattern where
each term repeats the number of times equal to the product of all m-numbers after m(i)
the whole pattern repeats the number of times equal to the product of all m-numbers before m(i)
This is what repmat(kron(1:m(i),ones(1,after)),1,before)' does. (Starting with R2015a you can use repelem to simplify this by replacing the kron command, but I don't have that release yet.)
a = [0 1 0 1 1 0];
m = [2 4 3]; // the numbers max1, max2, max3
A = zeros(prod(m), length(a));
i = 1; // runs through elements of m
for j=1:length(a) // runs through elements of a
if (a(j)>0)
before = prod(m(1:i-1));
after = prod(m(i+1:end));
A(:,j) = repmat(kron(1:m(i),ones(1,after)),1,before)';
i = i+1;
end
end
Output:
0 1 0 1 1 0
0 1 0 1 2 0
0 1 0 1 3 0
0 1 0 2 1 0
0 1 0 2 2 0
0 1 0 2 3 0
0 1 0 3 1 0
0 1 0 3 2 0
0 1 0 3 3 0
0 1 0 4 1 0
0 1 0 4 2 0
0 1 0 4 3 0
0 2 0 1 1 0
0 2 0 1 2 0
0 2 0 1 3 0
0 2 0 2 1 0
0 2 0 2 2 0
0 2 0 2 3 0
0 2 0 3 1 0
0 2 0 3 2 0
0 2 0 3 3 0
0 2 0 4 1 0
0 2 0 4 2 0
0 2 0 4 3 0

Concatenating binary bits into a number

I want to concatenate last four bits of binary into a number i have tried the following code
x8=magic(4)
x8_n=dec2bin(x8)
m=x8_n-'0'
which gives me the following output
m =
1 0 0 0 0
0 0 1 0 1
0 1 0 0 1
0 0 1 0 0
0 0 0 1 0
0 1 0 1 1
0 0 1 1 1
0 1 1 1 0
0 0 0 1 1
0 1 0 1 0
0 0 1 1 0
0 1 1 1 1
0 1 1 0 1
0 1 0 0 0
0 1 1 0 0
0 0 0 0 1
now i want to take every last 4 bits it each row and convert it into an integer
n = 4; %// number of bits you want
result = m(:,end-n+1:end) * pow2(n-1:-1:0).'; %'// matrix multiplication
Anyway, it would be easier to use mod on x8 directly, without the intermediate step of m:
result = mod(x8(:), 2^n);
In your example:
result =
0
5
9
4
2
11
7
14
3
10
6
15
13
8
12
1
This could be another approach -
n = 4; %%// number of bits you want
out = bin2dec(num2str(m(:,end-n+1:end)))
Output -
out =
0
5
9
4
2
11
7
14
3
10
6
15
13
8
12
1

Copying part of a matrix to another empty matrix with the same indices

I'm trying to copy part of a matrix (matrix 1) in matlab to another empty matrix of zeros (matrix 2) so that the section I copy from matrix 1 has the same indices in matrix 2, e.g.
Matrix 1 (mat1):
0 3 0 0 2 4 1 2 6
1 3 4 2 0 0 0 2 0
0 2 6 1 3 6 6 1 1
0 0 0 2 1 3 3 1 0
1 4 5 2 3 3 0 0 1
Matrix 2 (mat2) desired output:
0 0 0 0 0 0 0 0 0
0 0 4 2 0 0 0 0 0
0 0 6 1 3 6 6 0 0
0 0 0 2 1 3 3 0 0
0 0 0 0 0 0 0 0 0
I've tried something like
mat2([2:4],[3:7]) = mat1([2:4],[3:7])
but of course it doesn't work... any ideas of an efficient way to do this? I couldn't find another thread to help with this problem.
Thanks!
It does work. You just need to create mat2 first:
mat2 = zeros(size(mat1));
mat2(2:4, 3:7) = mat1(2:4, 3:7);
Note that you don't need the square brackets on those ranges.
Do this:
mat2 = zeros(size(mat1));
Before copying over.

profile of circular image - more efficient way to do it?

I need to get a 1-D profile of a circular image, for example 256x256 sin(R) image
I've written a matlab function for the task but it turns out to be very un-efficient.
the function averages over radius intervals of the original images.
matlab profiler reveals that the first line in the for-loop [indxs=find(...)]
takes ~86% of the running time.
i need to run the function on a some thousands of simulated images (some larger then 256x256) and it takes very long time to complete.
does anyone knows how can i make this code run faster?
maybe someone has another, more efficient way to do the task??
i also tried to convert to function into C++ & mex file using matlab coder
but it took longer (x3) to perform the task, might be because the sub-function- "findC"
uses some 2D-ffts to find the center of the image.
Thanks you All,
Dudas
My Matlab function:
function [sig R_axis Center]= Im2Polar (imR,ch,Center_Nblock)
% Converts Circular image to 1-D sig
% based on true image values w/o interpolation
% Input -
% imR - circular sinuns image
% ch - number of data-points in output signal (sig)
% Center_Nblock - a varible related to the image center finding method
% Output -
% sig - 1D vector of the circular image profile
% R_axis - axis data-points for sig
% Center - image center in pixels
[Mr Nr] = size(imR); % size of rectangular image
[Center]=findC(imR,Center_Nblock);
Xc=Center(1);
Yc=Center(2);
rMax=sqrt((Mr/2)^2 + (Nr/2)^2);
x=[0:1:Mr-1]-Xc+1;
y=[0:1:Nr-1]-Yc+1;
[X,Y]=meshgrid(x,y);
[TH,R] = cart2pol(X,Y);
% Assembling 1-D signal
sig=single([]);
ii=1;
dr=floor(rMax)/ch;
V=dr:dr:floor(rMax);
for v=V
indxs=find((v-dr)<=R & R<v);**
sig(ii)=mean(imR(indxs));
Nvals(ii)=length(indxs);
ii=ii+1;
end %for v
R_axis=V-dr/2;
end % of function
Following from the comments here's an example of something I might try. Let's work with a 9x9 example. Suppose you have the following annulus.
A =
0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 0 0
0 1 1 1 0 1 1 1 0
0 1 1 0 0 0 1 1 0
0 1 0 0 0 0 0 1 0
0 1 1 0 0 0 1 1 0
0 1 1 1 0 1 1 1 0
0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0
Then the indices of your sort of mask are, lets say [k n]
>> [k n]
ans =
3 2
4 2
5 2
6 2
7 2
2 3
3 3
4 3
6 3
7 3
8 3
2 4
3 4
7 4
8 4
2 5
8 5
2 6
3 6
7 6
8 6
2 7
3 7
4 7
6 7
7 7
8 7
3 8
4 8
5 8
6 8
7 8
Now have a 9x9 matrix of zeroes on hand called B, we can shift the whole thing over to the left by one pixel as follows using the formula (i+9*(j-1)) to convert double index to a single index.
>> B=zeros(9,9);
>> B((k)+9*(n-2))=1
B =
0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 0 0 0
1 1 1 0 1 1 1 0 0
1 1 0 0 0 1 1 0 0
1 0 0 0 0 0 1 0 0
1 1 0 0 0 1 1 0 0
1 1 1 0 1 1 1 0 0
0 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0
Or move down and to the right as follows
>> B=zeros(9,9);
>> B((k+1)+9*(n-0))=1
B =
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 0
0 0 1 1 1 0 1 1 1
0 0 1 1 0 0 0 1 1
0 0 1 0 0 0 0 0 1
0 0 1 1 0 0 0 1 1
0 0 1 1 1 0 1 1 1
0 0 0 1 1 1 1 1 0
As long as it doesn't go out of bounds you should be able to shift a single annular mask around with a simple addition to put the center at the image center.

finding local maxima in 3D images

I want to use a 3D blob detector which is a filtration algorithm, used for detection of spherical object in images. In this filter voxels with value greater than all pixels in their 26-neighborhood are set to 1
(s(x,y,z)=max(n26(x,y,z)))
and every other pixel is set to 0. Is there any function in matlab to do this work?
M(x,y,z)={ 1 if s(x,y,z)=max(n26(x,y,z))
0 otherwise
The easiest way to find local maxima is to use imdilate:
%# s = 3D array
msk = true(3,3,3);
msk(2,2,2) = false;
%# assign, to every voxel, the maximum of its neighbors
s_dil = imdilate(s,msk);
M = s > s_dil; %# M is 1 wherever a voxel's value is greater than its neighbors
matlabs own imregionalmax supports 26n from the get go, output is a logical.
2D example with 8n:
A =
1 1 1 1 1 1 1 1
1 3 3 3 1 1 4 1
1 3 5 3 1 4 4 4
1 3 3 3 1 4 4 4
1 1 1 1 1 4 6 4
1 1 1 1 1 4 4 4
>> B = imregionalmax(A);
>> B
B =
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0