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

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

Related

How to classify a matrix within a Matlab parfor loop?

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

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

Matlab - Create a vector using another vector as the limits

Say I have the following columns vector Z
1 53 55 57 60 64 68 70 71 72 74 76 77 78 79 80 255
I want to use it to create a matrix such that each row would contain all the number between (and including) 2 adjacent elements in Z
So the output matrix should be something like this:
1 2 3 .... 53
53 54 55
55 56 57
57 58 60
....
80 81 ... 255
I've been searching for something similar but couldn't find it.
Thanks
See if this works for you -
lens = diff(Z)+1;
mask1 = bsxfun(#le,[1:max(lens)]',lens); %//'
array1 = zeros(size(mask1));
array1(mask1) = sort([1:255 Z(2:end-1)]);
out = array1.'; %//'# out is the desired output
Try this to break the monotony of bsxfun :) :
d = diff(Z);
N = max(d)+1;
R = zeros(length(Z)-1,N);
for i = 1:length(Z)-1
R(i,1:1+d(i)) = Z(i):Z(i+1);
end
EDIT:
I know that the general consensus is that one always should try to avoid loops in Matlab, but is this valid for this example? I know that this is a broad question, so lets focus on this particular problem and compare bsxfun to JIT loop. Comparing the two proposed solutions:
the code used for testing:
Z = [1 53 55 57 60 64 68 70 71 72 74 76 77 78 79 80 255];
%[1 3 4, 6];
nn = round(logspace(1,4,10));
tm1_nn = zeros(length(nn),1);
tm2_nn = zeros(length(nn),1);
for o = 1:length(nn)
tm1 = zeros(nn(o),1);
tm2 = zeros(nn(o),1);
% approach1
for k = 1:nn(o)+1
tic
d = diff(Z);
N = max(d)+1;
R = zeros(length(Z)-1,N);
for i = 1:length(Z)-1
R(i,1:1+d(i)) = Z(i):Z(i+1);
end
tm1(k) = toc;
end
%approach 2
for k = 1:nn(o)+1
tic
lens = diff(Z)+1;
mask1 = bsxfun(#le,[1:max(lens)]',lens); %//'
array1 = zeros(size(mask1));
array1(mask1) = sort([1:255 Z(2:end-1)]);
out = array1.';
tm2(k) = toc;
end
tm1_nn(o) = mean(tm1);%sum(tm1);%mean(tm1);%
tm2_nn(o) = mean(tm2);%sum(tm2);%mean(tm2);%
end
semilogx(nn,tm1_nn, '-ro', nn,tm2_nn, '-bo')
legend('JIT loop', 'bsxfun')
xlabel('log_1_0(Number of runs)')
%ylabel('Sum execution time')
ylabel('Mean execution time')
grid on
I encountered other tasks previously where the loop was faster. (or I mess up the comparison?)

Most repeated values

I know how to check an 8-neighbourhood in matlab (i.e; nlfilter). But, I want to assign the value which is more repeated to the center value. So, say for instance that I have the following values in the 8-neighbourhood:
2-values = 56
3-values = 64
1-value = 70
1-value = 87
1-value = 65
In this case we would assign 64 to the center pixel.
How can we do that?
Thanks.
I think you want either the mode or the histc function.
M=mode(X) for vector X computes M as the sample mode, or most
frequently
occurring value in X.
Example with your data:
x = [56 56 64 64 64 70 87 65];
mode(x)
ans =
64
But this will only get you the most frequently occurring value.
If you want the count of each unique item in the array, you could do,
unqx = unique(x);
unqx =
56 64 65 70 87
valueCount = histc(x, unqx)
ans =
2 3 1 1 1
You could then sort this and take the first N values
valueCount = sort(valueCount, 'descend');
% Use unqx(valueCount(1:N))

Matlab: find mode in range

I have a matrix like:
A=
10 31 32 22
32 35 52 77
68 42 84 32
I need a function like mode but with range, for example mymode(A,10) that return 30, find most frequent number in range 0-10, 10-20, 20-30, .... and return most number in range.
You can use histc to bin your data into the ranges of your desire and then find the bin with the most members using max on the output of histc
ranges = 0:10:50; % your desired ranges
[n, bins] = histc(A(:), ranges); % bin the data
[v,i] = max(n); % find the bin with most occurrences
[ranges(i) ranges(i+1)] % edges of the most frequent bin
For your specific example this returns
ans =
30 40
which matches with your required output, as the most values in A lay between 30 and 40.
[M,F] = mode( A((A>=2) & (A<=5)) ) %//only interested in range 2 to 5
...where M will give you the mode and F will give you frequency of occurence
> A = [10 31 32 22; 32 35 52 77; 68 42 84 32]
A =
10 31 32 22
32 35 52 77
68 42 84 32
> min = 10
min = 10
> max = 40
max = 40
> mode(A(A >= min & A <= max))
ans = 32
>
I guess by the number of different answers that we may be missing your goal. Here is my interpretation.
If you want to have many ranges and you want to output most frequent number for every range, create a cell containing all desired ranges (they could overlap) and use cellfun to run mode() for every range. You can also create a cell with desired ranges using arrayfun in a similar manner:
A = [10 31 32 22; 32 35 52 77; 68 42 84 32];
% create ranges
range_step = 10;
range_start=[0:range_step:40];
range=arrayfun(#(r)([r r+range_step]), range_start, 'UniformOutput', false)
% analyze ranges
o = cellfun(#(r)(mode(A(A>=r(1) & A<=r(2)))), range, 'UniformOutput', false)
o =
[10] [10] [22] [32] [42]