How to classify a matrix within a Matlab parfor loop? - matlab

I am looking to classify the values of a matrix. The following example works outside of a parfor loop, however it does not work when used within a parfor loop. What are my options to classify matrices, following the provided example, within a parfor loop?
% Sample data
Imag1 = [ 62 41 169 118 210;
133 158 96 149 110;
211 200 84 194 29;
209 16 15 146 28;
95 144 13 249 170];
% Perform the classification
Imag1(find(Imag1 <= 130)) = 4;
Imag1(find(Imag1 >= 150)) = 1;
Imag1(find(Imag1 > 140)) = 2;
Imag1(find(Imag1 > 130)) = 3;
Results in the following (outside parfor loop):
Imag1 =
62 41 169 118 210
133 158 96 149 110
211 200 84 194 29
209 16 15 146 28
95 144 13 249 170
Imag1 =
4 4 1 4 1
3 1 4 2 4
1 1 4 1 4
1 4 4 2 4
4 2 4 1 1

You can use another matrix to store the result.
Imag2 = zeros(size(Imag1));
% Perform the classification
Imag2(find(Imag1 <= 130)) = 4;
Imag2(find(Imag1 >= 150)) = 1;
Imag2(find(Imag1 > 140)) = 2;
Imag2(find(Imag1 > 130)) = 3;
so you can use a parfor loop somehow. Since parfor doesn't care about order of execution. Your code doesn't work in a parfor loop because right now you are modifying the values of Imag1, then comparing those values again, aka any loop iteration would be be dependent on the prior loop iterations

Here's another approach:
parfor c = 1:size(Imag1,2)
Imag2(:,c) = 4-min(ceil(max((Imag1(:,c) - 130),0)/10),3);
end
Now you can split it up however you like; by rows, by columns, by blocks, by alternate columns...
Edit:
Unfortunately this classifies a value of 150 as 2. So you probably shouldn't use this one.
Take 3
class = [150 141 131 0]; %// minimum values for class 1, 2, 3, 4
[m, n] = size(Imag1);
parfor c=1:n
for r=1:m
Imag3(r,c) = find(Imag1(r,c) >= class, 1);
end
end

Related

Dividing a matrix into two parts

I am trying to classify my dataset. To do this, I will use the 4th column of my dataset. If the 4th column of the dataset is equal to 1, that row will added in new matrix called Q1. If the 4th column of the dataset is equal to 2, that row will be added to matrix Q2.
My code:
i = input('Enter a start row: ');
j = input('Enter a end row: ');
search = importfiledataset('search-queries-features.csv',i,j);
[n, p] = size(search);
if j>n
disp('Please enter a smaller number!');
end
for s = i:j
class_id = search(s,4);
if class_id == 1
Q1 = search(s,1:4)
elseif class_id ==2
Q2 = search(s,1:4)
end
end
This calculates the Q1 and Q2 matrices, but they all are 1x4 and when it gives new Q1 the old one is deleted. I need to add new row and make it 2x4 if conditions are true. I need to expand my Q1 matrix.
Briefly I am trying to divide my dataset into two parts using for loops and if statements.
Dataset:
I need outcome like:
Q1 = [30 64 1 1
30 62 3 1
30 65 0 1
31 59 2 1
31 65 4 1
33 58 10 1
33 60 0 1
34 58 30 1
34 60 1 1
34 61 10 1]
Q2 = [34 59 0 2
34 66 9 2]
How can I prevent my code from deleting previous rows of Q1 and Q2 and obtain the entire matrices?
The main problem in your calculation is that you overwrite Q1 and Q2 each loop iteration. Best solution: get rid of the loops and use logical indexing.
You can use logical indexing to quickly determine where a column is equal to 1 or 2:
search = [
30 64 1 1
30 62 3 1
30 65 0 1
31 59 2 1
31 65 4 1
33 58 10 1
33 60 0 1
34 59 0 2
34 66 9 2
34 58 30 1
34 60 1 1
34 61 10 1
];
Q1 = search(search(:,4)==1,:) % == compares each entry in the fourth column to 1
Q2 = search(search(:,4)==2,:)
Q1 =
30 64 1 1
30 62 3 1
30 65 0 1
31 59 2 1
31 65 4 1
33 58 10 1
33 60 0 1
34 58 30 1
34 60 1 1
34 61 10 1
Q2 =
34 59 0 2
34 66 9 2
Warning: Slow solution!
If you are hell bent on using loops, make sure to not overwrite your variables. Either extend them each iteration (which is very, very slow):
Q1=[];
Q2=[];
for ii = 1:size(search,1) % loop over all rows
if search(ii,4)==1
Q1 = [Q1;search(ii,:)];
end
if search(ii,4)==2
Q2 = [Q2;search(ii,:)];
end
end
MATLAB will put orange wiggles beneath Q1 and Q2, because it's a bad idea to grow arrays in-place. Alternatively, you can preallocate them as large as search and strip off the excess:
Q1 = zeros(size(search)); % Initialise to be as large as search
Q2 = zeros(size(search));
Q1kk = 1; % Intialiase counters
Q2kk = 1;
for ii = 1:size(search,1) % loop over all rows
if search(ii,4)==1
Q1(Q1kk,:) = search(ii,:); % store
Q1kk = Q1kk + 1; % Increase row counter
end
if search(ii,4)==2
Q2(Q2kk,:) = search(ii,:);
Q2kk = Q2kk + 1;
end
end
Q1 = Q1(1:Q1kk-1,:); % strip off excess rows
Q2 = Q2(1:Q2kk-1,:);
Another option using accumarray, if Q is your original matrix:
Q = accumarray(Q(:,4),1:size(Q,1),[],#(x){Q(x,:)});
You can access the result with Q{1} (for class_id = 1), Q{2} (for class_id = 2) and so on...

Find the difference between positive and negative peaks MATLAB

I need to find the difference between positive and negative peaks where the difference is greater than +-3.
I am using findpeaks function in MATLAB to find the positive and negative peaks of the data.
In an example of my code:
[Ypos, Yposloc] = findpeaks(YT0);
[Yneg, Ynegloc] = findpeaks(YT0*-1);
Yneg = Yneg*-1;
Yposloc and Ynegloc return the locations of the positive and negative peaks in the data.
I want to concatenate Ypos and Yneg based on the order of the peaks.
For example, my peaks are
Ypos = [11 6 -10 -10 6 6 6 6 6 -5]
Yneg = [-12 -14 -11 -11 -11 5 5 5 -6]
Locations in YT0
Yposloc = [24 63 79 84 93 95 97 100 156]
Ynegloc = [11 51 78 81 85 94 96 99 154]
In this case, where both Yposloc and Ynegloc are 9x1, I can do the following;
nColumns = size(Yposs,2);
YTT0 = [Yneg, Ypos]';
YTT0 = reshape(YTT0(:),nColumns,[])';
YTT0 = diff(YTT0)
YT0Change = numel(YTT0(YTT0(:)>=3 | YTT0(:)<=-3));
Total changes that I am interested is 6
However, I need to concatenate Yneg and Ypos automatically, based on their locations. So I think I need to to do an if statement to figure out if my positive or negative peaks come first? Then, I am not sure how to tackle the problem of when Ypos and Yneg are different sizes.
I am running this script multiple times where data changes and the negative/positive peak order are constantly changing. Is there a simple way I can compare the peak locations or am I on the right track here?
I would check each minimum with both the previous and the next maxima. In order to do that you can first combine positive and negative peaks according to their order:
Y = zeros(1, max([Yposloc, Ynegloc]));
Yloc = zeros(size(Y));
Yloc(Yposloc) = Yposloc;
Yloc(Ynegloc) = Ynegloc;
Y(Yposloc) = Ypos; % I think you inserted one extra '6' in your code!
Y(Ynegloc) = Yneg;
Y = Y(Yloc ~= 0) % this is the combined signal
Yloc = Yloc(Yloc ~= 0) % this is the combined locations
% Y =
%
% -12 11 -14 6 -11 -10 -11 -10 -11 6 5 6 5 6 5 6 -6 -5
%
% Yloc =
%
% 11 24 51 63 78 79 81 84 85 93 94 95 96 97 99 100 154 156
And then calculate the differences:
diff(Y)
% ans =
%
% 23 -25 20 -17 1 -1 1 -1 17 -1 1 -1 1 -1 1 -12 1
If you want changes of at least 6 units:
num = sum(abs(diff(Y)) > 6)
% num =
%
% 6
Ypos = [11 6 -10 -10 6 6 6 6 -5];
Yneg = [-12 -14 -11 -11 -11 5 5 5 -6];
Yposloc = [24 63 79 84 93 95 97 100 156];
Ynegloc = [11 51 78 81 85 94 96 99 154];
TOTAL=[Yposloc Ynegloc;Ypos Yneg];
%creatin a vector with positions in row 1 and values in row 2
[~,position]=sort(TOTAL(1,:));
%resort this matrix so the values are in the orginial order
TOTAL_sorted=TOTAL(:,position);
%look at the changes of the values
changes=diff(TOTAL_sorted(2,:));
if changes(1)>0
disp('First value was a Minimum')
else
disp('First value was a MAximum')
end
%same structure at the TOTAL matrix
%abs(changes)>3 produces a logical vector that shows where the absolute values was bigger
%than 3, in my opinon its rather intresting where the end is then were the start is
% thats why i add +1
Important_changes=TOTAL_sorted(:,find(abs(changes)>3)+1);
plot(TOTAL_sorted(1,:),TOTAL_sorted(2,:))
hold on
plot(Important_changes(1,:),Important_changes(2,:),...
'Marker','o','MarkerSize',10, 'LineStyle','none');
hold off

Fast way to find the neighboor of pixel

I am programming for task that finds the neighbor of a given pixel x in image Dthat can formula as:
The formula shown pixels y which satisfy the distance to pixel x is 1, then they are neighbor of pixel x. This is my matlab code. However, it still takes long time to find. Could you suggest a faster way to do it. Thank you so much
%-- Find the neighborhood of one pixel
% x is pixel coordinate
% nrow, ncol is size of image
function N = find_neighbor(x,nrow,ncol)
i = x(1);
j = x(2);
I1 = i+1;
if (I1 > nrow)
I1 = nrow;
end
I2 = i-1;
if (I2 < 1)
I2 = 1;
end
J1 = j+1;
if (J1 > ncol)
J1 = ncol;
end
J2 = j-1;
if (J2 < 1)
J2 = 1;
end
N = [I1, I2, i, i; j, j, J1, J2];
For example: ncol=128; nrow=128; x =[30;110] then output
N =31 29 30 30; 110 110 111 109]
For calling the function in loop
x=[30 31 32 33; 110 123 122 124]
for i=1:length(x)
N = find_neighbor(x(:,i),nrow,ncol);
end
Here's a vectorized approach using bsxfun:
% define four neighbors as coordinate differences
d = [-1 0 ; 1 0 ; 0 -1 ; 0 1]';
% add to pixel coordinates
N = bsxfun(#plus, x, permute(d, [1 3 2]));
% make one long list for the neighbors of all pixels together
N = reshape(N, 2, []);
% identify out-of-bounds coordinates
ind = (N(1, :) < 1) | (N(1, :) > nrow) | (N(2, :) < 1) | (N(2, :) > ncol);
% and remove those "neighbors"
N(:, ind) = [];
The permute is there to move the "dimension" of four different neighbors into the 3rd array index. This way, using bsxfun, we get the combination of every pair of original pixel coordinates with every pair of relative neighbor coordinates. The out-of-bounds check assumes that nrow belongs to the first coordinate and ncol to the second coordinate.
With
ncol=128;
nrow=128;
x = [30 31 32 33; 110 123 122 124];
the result is
N =
29 30 31 32 31 32 33 34 30 31 32 33 30 31 32 33
110 123 122 124 110 123 122 124 109 122 121 123 111 124 123 125
Different neighbors of different pixels can end up to be the same pixel, so there can be duplicates in the list. If you only want each resulting pixel once, use
% remove duplicates?
N = unique(N', 'rows')';
to get
N =
29 30 30 30 31 31 31 32 32 32 33 33 33 34
110 109 111 123 110 122 124 121 123 124 122 123 125 124
Matlab's performance is horrible when calling small functions many time. The Matlab approach is to do vectorize as much as possible. A vectorized version of your code:
function N = find_neighbor(x,nrow,ncol)
N = [min(x(1,:)+1,nrow), max(x(1,:)-1,1), x(1,:), x(1,:); x(2,:), x(2,:),min(x(2,:)+1,ncol), max(x(2,:)-1,1)];
end
and usage
x=[30 31 32 33; 110 123 122 124]
N = find_neighbor(x,nrow,ncol);
BTW, for pixels on the border , your solution always gives 4 neighbors. This is wrong. the neighbors of (1,1) for examples should be only (2,1) and (1,2), while you add two extra (1,1).
The solution to this is quite simple - delete all neighbors that are outside the image
function N = find_neighbor(x,nrow,ncol)
N = [x(1,:)+1, x(1,:)-1, x(1,:), x(1,:); x(2,:), x(2,:),x(2,:)+1, x(2,:)-1];
N(:,N(1,:)<1 | N(1,:)> nrow | N(2,:)<1 | N(2,:)>ncol)=[];
end

Find closest matching distances for a set of points in a distance matrix in Matlab

I have a matrix of measured angles between M planes
0 52 77 79
52 0 10 14
77 10 0 3
79 14 3 0
I have a list of known angles between planes, which is an N-by-N matrix which I name rho. Here's is a subset of it (it's too large to display):
0 51 68 75 78 81 82
51 0 17 24 28 30 32
68 17 0 7 11 13 15
75 24 7 0 4 6 8
78 28 11 4 0 2 4
81 30 13 6 2 0 2
82 32 15 8 4 2 0
My mission is to find the set of M planes whose angles in rho are nearest to the measured angles.
For example, the measured angles for the planes shown above are relatively close to the known angles between planes 1, 2, 4 and 6.
Put differently, I need to find a set of points in a distance matrix (which uses cosine-related distances) which matches a set of distances I measured. This can also be thought of as matching a pattern to a mold.
In my problem, I have M=5 and N=415.
I really tried to get my head around it but have run out of time. So currently I'm using the simplest method: iterating over every possible combination of 3 planes but this is slow and currently written only for M=3. I then return a list of matching planes sorted by a matching score:
function [scores] = which_zones(rho, angles)
N = size(rho,1);
scores = zeros(N^3, 4);
index = 1;
for i=1:N-2
for j=(i+1):N-1
for k=(j+1):N
found_angles = [rho(i,j) rho(i,k) rho(j,k)];
score = sqrt(sum((found_angles-angles).^2));
scores(index,:)=[score i j k];
index = index + 1;
end
end;
end
scores=scores(1:(index-1),:); % was too lazy to pre-calculate #
scores=sortrows(scores, 1);
end
I have a feeling pdist2 might help but not sure how. I would appreciate any help in figuring this out.
There is http://www.mathworks.nl/help/matlab/ref/dsearchn.html for closest point search, but that requires same dimensionality. I think you have to bruteforce find it anyway because it's just a special problem.
Here's a way to bruteforce iterate over all unique combinations of the second matrix and calculate the score, after that you can find the one with the minimum score.
A=[ 0 52 77 79;
52 0 10 14;
77 10 0 3;
79 14 3 0];
B=[ 0 51 68 75 78 81 82;
51 0 17 24 28 30 32;
68 17 0 7 11 13 15;
75 24 7 0 4 6 8;
78 28 11 4 0 2 4;
81 30 13 6 2 0 2;
82 32 15 8 4 2 0];
M = size(A,1);
N = size(B,1);
% find all unique permutations of `1:M`
idx = nchoosek(1:N,M);
K = size(idx,1); % number of combinations = valid candidates for matching A
score = NaN(K,1);
idx_triu = triu(true(M,M),1);
Atriu = A(idx_triu);
for ii=1:K
partB = B(idx(ii,:),idx(ii,:));
partB_triu = partB(idx_triu);
score = norm(Atriu-partB_triu,2);
end
[~, best_match_idx] = min(score);
best_match = idx(best_match_idx,:);
The solution of your example actually is [1 2 3 4], so the upperleft part of B and not [1 2 4 6].
This would theoretically solve your problem, and I don't know how to make this algorithm any faster. But it will still be slow for large numbers. For example for your case of M=5 and N=415, there are 100 128 170 583 combinations of B which are a possible solution; just generating the selector indices is impossible in 32-bit because you can't address them all.
I think the real optimization here lies in cutting away some of the planes in the NxN matrix in a preceding filtering part.

Matlab : How I can creat a polynomial generator Reed Solomon for QR Code

I have to make a matlab program, which should create a QR Code.
My problem is the Reed Solomon error correction
The user enters the word he wants. [...] I got a string of numbers I should be gone in a polynomial generator (Reed Solomon) (I found some sites that do this very well: http://www.pclviewer.com/rs2/calculator.html)
I would like it to happen: for example I input: 32 91 11 120 209 114 220 77 67 64 236 17 236
[Reed Solomon generator polynomial]
and I want to find out: 168 72 22 82 217 54 156 0 46 15 180 122 16
I found the functions rsenc comm.rsencoder gf ... But it is impossible to understand the operation of these functions. Functions are detailed: http://www.mathworks.fr/fr/help/comm...n.html#fp12225
I tried a code of this type :
n = 255; k = 13; % Codeword length and message length
m = 8; % Number of bits in each symbol
msg = [32 91 11 120 209 114 220 77 67 64 236 17 236]; % Message is a Galois array.
obj = comm.RSEncoder(n, k);
c1 = step(obj, msg(1,:)');
c = [c1].';
He produced a string of 255 while I want 13 output.
Thank you for your help.
I think that you are committing a mistake.
'n' is the length of final message with parity code.
'k' is the lenght of message (number of symbols)
I guess that this will help you:
clc, clear all;
M = 16; % Modulation Order || same that Max value, at your case: 256! 2^m
hEnc = comm.RSEncoder;
hEnc.CodewordLength = M - 1; % Max = M-1, Min = 4, Must be greater than MessageLenght
hEnc.MessageLength = 13; % Experiment change up and down value (using odd number)
hEnc.BitInput = false;
hEnc
t = hEnc.CodewordLength - hEnc.MessageLength;
frame = 2*hEnc.MessageLength; % multiple of MensagemLength
fprintf('\tError Detection (in Symbols): %d\n',t);
fprintf('\tError Correction: %.2f\n',t/2);
data = randi([0 M-1], frame, 1); % Create a frame with symbols range (0 to M-1)
encodedData = step(hEnc, data); % encod the frame