Sliding window algorithm for activity recognition - matlab

I want to write a sliding window algorithm for use in activity recognition.
The training data is <1xN> so I'm thinking I just need to take (say window_size=3) the window_size of data and train that. I also later want to use this algorithm on a matrix
.
I'm new to matlab so i need any advice/directions on how to implement this correctly.

The short answer:
%# nx = length(x)
%# nwind = window_size
idx = bsxfun(#plus, (1:nwind)', 1+(0:(fix(nx/nwind)-1))*nwind)-1;
idx will be a matrix of size nwind-by-K where K is the number of sliding windows (ie each column contains the indices of one sliding window).
Note that in the code above, if the last window's length is less than the desired one, it is dropped. Also the sliding windows are non-overlapping.
An example to illustrate:
%# lets create a sin signal
t = linspace(0,1,200);
x = sin(2*pi*5*t);
%# compute indices
nx = length(x);
nwind = 8;
idx = bsxfun(#plus, (1:nwind)', 1+(0:(fix(nx/nwind)-1))*nwind)-1;
%'# loop over sliding windows
for k=1:size(idx,2)
slidingWindow = x( idx(:,k) );
%# do something with it ..
end
%# or more concisely as
slidingWindows = x(idx);
EDIT:
For overlapping windows, let:
noverlap = number of overlapping elements
then the above is simply changed to:
idx = bsxfun(#plus, (1:nwind)', 1+(0:(fix((nx-noverlap)/(nwind-noverlap))-1))*(nwind-noverlap))-1;
An example to show the result:
>> nx = 100; nwind = 10; noverlap = 2;
>> idx = bsxfun(#plus, (1:nwind)', 1+(0:(fix((nx-noverlap)/(nwind-noverlap))-1))*(nwind-noverlap))-1
idx =
1 9 17 25 33 41 49 57 65 73 81 89
2 10 18 26 34 42 50 58 66 74 82 90
3 11 19 27 35 43 51 59 67 75 83 91
4 12 20 28 36 44 52 60 68 76 84 92
5 13 21 29 37 45 53 61 69 77 85 93
6 14 22 30 38 46 54 62 70 78 86 94
7 15 23 31 39 47 55 63 71 79 87 95
8 16 24 32 40 48 56 64 72 80 88 96
9 17 25 33 41 49 57 65 73 81 89 97
10 18 26 34 42 50 58 66 74 82 90 98

Related

Matlab: select submatrix from matrix by certain criteria

I have a matrix A
A=[f magic(10)]
A=
931142103 92 99 1 8 15 67 74 51 58 40
931142103 98 80 7 14 16 73 55 57 64 41
931142103 4 81 88 20 22 54 56 63 70 47
459200101 85 87 19 21 3 60 62 69 71 28
459200101 86 93 25 2 9 61 68 75 52 34
459200101 17 24 76 83 90 42 49 26 33 65
459200101 23 5 82 89 91 48 30 32 39 66
37833100 79 6 13 95 97 29 31 38 45 72
37833100 10 12 94 96 78 35 37 44 46 53
37833100 11 18 100 77 84 36 43 50 27 59
The first column are firm codes. The rest columns are firms' data, with each row referring to the firm in Column 1 in a given year. Notice that years may not be balance for every firms.
I would like to subtract sub-matrices according to the first column. For instance, for A(1:3,2:11) for 931142103:
A(1:3,2:11)
ans =
92 99 1 8 15 67 74 51 58 40
98 80 7 14 16 73 55 57 64 41
4 81 88 20 22 54 56 63 70 47
Same as 459200101 (which would be A(4:7,2:11)) and A(8:10,2:11) for 37833100.
I get a sense that the code should like this:
indices=find(A(:,1));
obs=size(A(:,1));
for i=1:obs,
if i==indices(i ??)
A{i}=A(??,2:11);
end
end
I have difficulties in indexing these complicated codes: 459200101 and 37833100 in order to gather them together. And how can I write the rows of my submatrix A{i}?
Thanks so much!
One approach with arrayfun -
%// Get unique entries from first column of A and keep the order
%// with 'stable' option i.e. don't sort
unqA1 = unique(A(:,1),'stable')
%// Use arrayfun to select each such submatrix and store as a cell
%// in a cell array, which is the final output
outA = arrayfun(#(n) A(A(:,1)==unqA1(n),:),1:numel(unqA1),'Uni',0)
Or this -
[~,~,row_idx] = unique(A(:,1),'stable')
outA = arrayfun(#(n) A(row_idx==n,:),1:max(row_idx),'Uni',0)
Finally, you can verify results with a call to celldisp(outA)
If values in column 1 always appear grouped (as in your example), you can use mat2cell as follows:
result = mat2cell(A, diff([0; find(diff(A(:,1))); size(A,1)]));
If they don't, just sort the rows of A according to column 1 before applying the above:
A = sortrows(A,1);
result = mat2cell(A, diff([0; find(diff(A(:,1))); size(A,1)]));
If you don't mind the results internally not being ordered, you can use accumarray for this:
[~,~,I] = unique(A(:,1),'stable');
partitions = accumarray(I, 1:size(A,1), [], #(I){A(I,2:end)});

Matlab: 3D Surface Plot of values from own vectors

I have 3 vectors with values for coordinates (X,Y,Z) and I want to plot them as a surface. I have tried all sorts of solutions from here and other forums and cannot for the life of me get it to look like anything that makes sense. I have a picture that can describe the situation better but I can't post it as I don't have enough reputation. Please help. Thank you.
EDIT: This is the link to the picture :
In the picture, the origin of each vector arrow represents the point in a 3D coordinate, with the length of the vector arrow giving the magnitude of the required torque to move at that point in 3D space.
Right now, the data is separated in line vectors with each point's coordinate: so that's one vector for the X, one for Y. Z is one line inside a 3 line matrix as the whole matrix describes the required torque in a 3 coordinate axes.
I've tried using meshgridon the X and Y vectors and then attributed the Z value using griddataand then surfbut I'm not getting something that looks like the original:
The plot is linear but I'm pretty sure the data is not... at least not that linear.
It seems like you want want to plot the single points decribed by the vectors, here you have an old answer of mine (as a bonus you will have nice colorful plots 'cause that's what the original question asked):
Assuming Data=[Vec1,Vec2,Vec3,...] and VecN=[Xn,Yn,Zn]'
"
If you want to plot points, you can define an RGB color and plot single points with hold on like this:
hold on
for i=1:length(Data(:,1))
plot3(Data(i,1),Data(i,2),Data(i,3),'Color',[(i/100*255)/255 0/255 (255-(i/100*255))/255],'LineWidth',2)
end
shg
"
Managed to solve the problem. As mentioned, the data was not uniform and because of that, surfwas jumping from one end of the plot to the other, creating a total mess. Solved it by organising the values linearly using linspaceand then using those values to create the meshgrid and then assign the Z values using griddata with a cubic interpolation.. Managed to produce proper looking surface plots with the data on hand.
Plot each data point separately within a loop:
figure; hold on; grid on;
for i = 1:length(x)
stem3(x(i),y(i),z(i));
end
Don't forget to add hold on. Use "Rotate 3D" button from the toolbar in the figure window if the plot was shown in 2D at first.
You can use griddata parameter to natural, cubic or v4. This will do interpolation and make your graph with non-uniform data smooth
Below is a sample MATLAb code
x=[32 20 67 1 98 34 57 65 24 82 47 55 8 51 13 14 18 30 37 39 10 33 21 26 38 81 83 60 95 22 17 5 72 46 99 52 12 25 96 29 70 85 43 69 19 78 97 31 89 53 2 91 48 71 61 15 36 84 94 50 11 80 6 7 49 74 9 88 40 79 27 68 73 64 63 59 86 23 35 58 45 28 100 42 93 87 16 90 41 66 54 92 77 4 62 76 75 56 3 44];
y=[96 75 24 9 83 49 27 77 3 23 17 31 40 13 7 52 51 21 98 47 64 79 78 91 44 16 15 100 84 99 63 68 70 30 54 76 97 73 33 5 88 8 71 66 62 25 60 42 72 45 18 11 28 59 89 65 10 55 69 81 12 26 20 95 87 41 74 50 93 22 43 90 14 34 82 35 56 38 80 32 1 57 6 36 37 61 29 58 2 48 4 46 67 53 92 86 94 19 39 85];
z=[55 31 11 45 83 36 86 49 15 57 42 46 8 94 88 47 54 81 98 41 32 35 56 85 9 89 37 60 23 62 67 100 78 76 73 80 10 20 68 34 77 93 1 63 53 12 22 99 91 40 84 24 33 3 43 19 92 97 6 82 64 25 26 79 95 4 44 58 5 21 70 29 65 87 96 90 51 14 18 2 72 28 71 39 52 7 27 59 50 61 48 30 66 69 17 13 74 16 75 38];
xlin = linspace(min(x), max(x), 100);
ylin = linspace(min(y), max(y), 100);
[X,Y] = meshgrid(xlin, ylin);
% Z = griddata(x,y,z,X,Y,'natural');
% Z = griddata(x,y,z,X,Y,'cubic');
Z = griddata(x,y,z,X,Y,'v4');
mesh(X,Y,Z)
axis tight; hold on
plot3(x,y,z,'.','MarkerSize',15)

How to reshape a matrix horizontally using MATLAB

I have matrix A of the size(4,192). It consists of 12 matrices of the size(4,4) aligned horizontally. I want to get matrix B with the size(12,16). B must get as follows:
suppose
A=[y1,y2,y3,...,y12]
in which yn is a 4*4 matrix. Then,
B=[y1,y4,y7,y10;
y2,y5,y8,y11;
y3,y6,y9,y12]
Is there an efficient/quicker (using no loop) way to do this using MATLAB?
You can try the following code:
ys1 = 2; % size(1) from submatrix (for the following example, use ys1 = 4 for the actual problem)
ys2 = 2; % size(2) from submatrix (for the following example, use ys2 = 4 for the actual problem)
ns1 = 3; % size(1) of final matrix in terms of submatrix (3 rows)
ns2 = 4; % size(2) of final matrix in terms of submatrix (4 columns)
temp = reshape(A,ys1,ys2,ns1,ns2);
B = reshape(permute(temp,[1 3 2 4]),ys1*ns1,ys2*ns2);
Example:
A = [11 12 21 22 31 32 41 42 51 52 61 62 71 72 81 82 91 92 101 102 111 112 121 122;
13 14 23 24 33 34 43 44 53 54 63 64 73 74 83 84 93 94 103 104 113 114 123 124];
B =
11 12 41 42 71 72 101 102
13 14 43 44 73 74 103 104
21 22 51 52 81 82 111 112
23 24 53 54 83 84 113 114
31 32 61 62 91 92 121 122
33 34 63 64 93 94 123 124

Morphological dilation on Greyscale image using a neighborhood of size n x n in MATLAB

The Dilation process is performed by laying the structuring element B on the image A and sliding it across the image in a manner similar to convolution.
I understand the main concept behind the mathematical morphology dilation of the grayscale images, but i still have one question :
Can the values of the structure element be not chosen by the user ? In other words, can we perform a dilation process on the image by just choosing the size and shape of the structure element without specifying its elements?
For more precision, i will explain well my question by an example : Assume a greyscale image I of size 160 x 160 to be processed (dilated in this case) by a neighborhood of size 8 x 8. I didn't specify the elements of this neighborhood, so their elements are from the image itself. For example i wrote the matlab code below:
Max_image = max_filter(I, [0 0 7 7]);
Where the function max_filter is:
[n m] = size(I); % n=160 and m=160
B = I;
for i = 1:m-7,
B(:,i) = max(I(:,i:i+7),[],2);
end
for i=m-7+1:m
B(:,i) = max(I(:,i:min(end,i+7),[],2);
end
for i = 1:n-7,
I(i,:) = max(B(max(1,i):min(end,i+7),:),[],1);
end
for i = n-7+1:n,
I(i,:) = max(B(i:min(end,i+7),:),[],1);
end
Does that is still considered as a morphological dilation operation ? Recall that i used a structure element of size 8 x 8.
Your program is equivalent to a full image dilation with the structure element of ones(8) (btw, you didn't use the input argument [0 0 7 7], and you don't need that indeed):
I = [92 99 1 8 15 67 74 51 58 40
98 80 7 14 16 73 55 57 64 41
4 81 88 20 22 54 56 63 70 47
85 87 19 21 3 60 62 69 71 28
86 93 25 2 9 61 68 75 52 34
17 24 76 83 90 42 49 26 33 65
23 5 82 89 91 48 30 32 39 66
79 6 13 95 97 29 31 38 45 72
10 12 94 96 78 35 37 44 46 53
11 18 100 77 84 36 43 50 27 59];
Max_image = max_filter(I, [0 0 7 7]) will give you:
99 99 97 97 97 75 75 75 72 72
98 97 97 97 97 75 75 75 72 72
100 100 100 97 97 75 75 75 72 72
100 100 100 97 97 75 75 75 72 72
100 100 100 97 97 75 75 75 72 72
100 100 100 97 97 72 72 72 72 72
100 100 100 97 97 72 72 72 72 72
100 100 100 97 97 72 72 72 72 72
100 100 100 96 84 59 59 59 59 59
100 100 100 84 84 59 59 59 59 59
When you are using:
J1=imdilate(I,ones(8),'full');
J1(8:end,8:end)
It will give you exactly the same answer.
That's why I told you yesterday that it is often to use a binary image mask as the structure element. You don't need to choose the value inside the mask, but you need to choose the size (8*8) and shape. What is a shape? In a binary image, the elements that are filled with 1 determines the shape. Here in your code you selected the largest value within the 8*8 region, that is equivalent to the image dilation with a whole bright 8*8 square shaped mask.

MATLAB: extracting groups of columns into a submatrix?

I have a data-set, in which I want to extract columns 1-3, 7-9, 13-15, all the way to the end of the matrix
As an example, I've used the standard magic function to create a matrix
A=magic(10)
A =
92 99 1 8 15 67 74 51 58 40
98 80 7 14 16 73 55 57 64 41
4 81 88 20 22 54 56 63 70 47
85 87 19 21 3 60 62 69 71 28
86 93 25 2 9 61 68 75 52 34
17 24 76 83 90 42 49 26 33 65
23 5 82 89 91 48 30 32 39 66
79 6 13 95 97 29 31 38 45 72
10 12 94 96 78 35 37 44 46 53
11 18 100 77 84 36 43 50 27 59
I know that I can extract single columns starting at 1, in intervals of 3 with the command:
Aex=a(:,1 : 3 : end)
Aex =
92 8 74 40
98 14 55 41
4 20 56 47
85 21 62 28
86 2 68 34
17 83 49 65
23 89 30 66
79 95 31 72
10 96 37 53
11 77 43 59
Say I want to extract groups of columns instead (e.g. column 1-3, 7-9 etc.).
Is there a way to do this without having to manually point out all the column numbers?
Thanks for your help!
Rasmus
Is this what you are looking for:
Aex = A(:,[1:3 7:9])
?
I am assuming that you would like the result all concatenated into another large matrix?
If that is the case, try this one on for size:
result = A(diag(0:2)*ones(3,floor((size(A,2) - 3)/6) + 1) + ...
ones(3,floor((size(A,2) - 3)/6) + 1)*diag(1:6:(size(A,2)-3)))
That could probably be shortened with some matrix math rules. You could also parameterize the values so that it can be modified to do more than what this problem expects, (and also might make more sense),
a = 3;
b = 6;
result = A(diag(0:a-1)*ones(a,floor((size(A,2) - a)/b) + 1) + ...
ones(a,floor((size(A,2) - a)/b) + 1)*diag(1:b:(size(A,2)-a)))
where a is the size of "group" (length([1 2 3]) = length([7 8 9]) = ... = 3), etc. and b is the column spacing ([1...7...13...] in your example)
If you would like them separated, I put them in cells here, but they can go to wherever you need:
a = 3;
b = 6;
results = {};
for Cols = 1:b:(size(A,2)-a)
results{end+1} = A(:, Cols:(Cols+2));
end
I didn't check the speed of either of these, but I think the first one may be faster. You may want to split it up into terms so it's more readable, I just did it to fit on a single line (which isn't always the best way of writing code).
The simple way to do this:
M = magic(10);
n = size(M,2)
idx = sort([1:3:n 2:3:n 3:3:n])
M(:,idx)
If however, the pattern of removal is simpler than the pattern of colums that you want to keep you could use this instead:
A = magic(10);
B = A;
B(:,4:3:end)=[];
B(:,4:3:end)=[]; %Yes 3x the same line of code.
B(:,4:3:end)=[];