How can i replace some elements of a matrix by other numbers in MATLAB? - matlab

I have a matrix consists of 1000 binary elements like below in Matlab:
M =
11001100101100001011010001001100101000101110010110001‌​10000101010110010111‌​0111001...
How i can split every 3 elements and replace them By another elements. for example 000 By 000000, 110 By 000001, 001 By 00001, 100 By 0001, 101 By 001, 010 By 01, 011 By 1.
I used this method but it doesn't work. What is wrong with it?
Lookup_In = [ 000 110 001 100 101 010 011 ] ;
Lookup_Out = {'000000','000001','00001','0001','101','01','1' } ;
StrOut = repmat({'Unknown'},size(M)) ;
[tf, idx] =ismember(M, Lookup_In) ;
StrOut(tf) = Lookup_Out(idx(tf))

M here is randomly generated with 1000 binary elements:
rng(1);
M = randi([0 1], 1,1000);
fprintf('%d\n',M)
First, I zeropadded M to reach a length multiple of 3. Second, I reshaped the array in a matrix with 3 elements of each row and applied Lookup_Out.
c = mod(numel(M),3);
M = [M,zeros(1,3-c)]; %zeropadding to multiple of 3
M = reshape(M,[3,numel(M)/3])';
Lookup_In = [ 000 110 001 100 101 010 011 ] ;
Lookup_Out = {'000000','000001','00001','0001','101','01','1' } ;
StrOut = repmat({''},[1,size(M,1)]);
for r=1:size(M,1)
StrOut{r} = Lookup_Out{str2double(sprintf('%d',M(r,:))) == Lookup_In};
end

Related

Get points which are within a given distance in two different matrices

I have two matrices A and B, in which the number of rows can vary. A and B do not necessarily have the same number of rows.
For example:
A = [ 110 90
130 140
230 50
370 210 ];
B = [ 321 95
102 35
303 200 ];
Now matrix A and B have 'corresponding points'. Corresponding points are rows where the values in the 2nd column of both matrices are within +/-20.
For example:
A(1,2) = 90 and B(1,2) = 95, the difference is within +/-20 so A(1,:) and B(1,:) are corresponding points.
A(2,2) = 140 and B(2,2) = 35, the difference is not within +/-20 so A(2,:) and B(2,:) are not corresponding points.
A(3,2) = 50 and B(2,2) = 35, the difference is within +/-20 so A(3,:) and B(2,:) are corresponding points.
Using this I want to store the corresponding points of A and B in C and D respectively. For the above example, the final matrices should look like this:
C = [ 110 90
230 50
370 210 ]
D = [ 321 95
102 35
303 200 ]
You can get all of the distances using pdist2
dists = pdist2( A(:,2), B(:,2) )
>> dists = [ 5 55 110
45 105 60
45 15 150
115 175 10 ]
Then get the indices of all 'corresponding points', as defined by a threshold of 20.
% Get combinations within tolerance
idx = dists < 20;
% Get indices
[iA, iB] = find(idx);
Then you can create the final matrices
C = A(iA, :);
D = B(iB, :);
Edit: One way to ensure each pairing is unique (i.e. A(1,:) cannot be paired with multiple rows from B) would be to get the minimum dists for each row/column. Note: this would still give you duplicate matches if the distances are exactly the same, you haven't defined how this should be handled.
dists = pdist2( A(:,2), B(:,2) );
% Set values which are greater than the row/column minima to be infinity.
% This means they will never be within the tolerance of 20 (or whatever else)
dists ( bsxfun(#gt, dists, min(dists,[],1)) | bsxfun(#gt, dists, min(dists,[],2)) ) = Inf;
% In MATLAB versions > 2016b, you can use implicit expansion to replace bsxfun
% That would be: dists( dists > min(dists,[],1) | dists > min(dists,[],2) )
% Now continue as before
[iA, iB] = find( dists < 20 );
C = A(iA, :);
D = B(iB, :);

How i can encode some elements in MATLAB?

I made two random numbers from 0 to 3.
a=0;
b=3;
A=round(a+(b-a)*rand(1,1000));
B=round(a+(b-a)*rand(1,1000));
then i add every two bits of them. then i convert it to binary.
SUM = A + B;
binarySum = dec2bin(SUM);
because i wanted to count transitions, i write this code:
s = 1;
for i = 1:1000
for j = 1:3
M(1,s) = binarySum(i,j);
s = s+1;
end
end
Tr = sum(diff(M)~=0);
now i want to split every 3 elements of M and encode them By another elements. for example 000 By 000000, 110 By 000001, 001 By 00001, 100 By 0001, 101 By 001, 010 By 01, 011 By 1.
I used this method but it doesn't work. What is wrong with it?
Lookup_In = [ 000 110 001 100 101 010 011 ] ;
Lookup_Out = {'000000','000001','00001','0001','101','01','1' } ;
StrOut = repmat({'Unknown'},size(M)) ;
[tf, idx] =ismember(M, Lookup_In) ;
StrOut(tf) = Lookup_Out(idx(tf))
M is an string that can be mapped using Lookup_Out in this way:
M2 = reshape(M, [3,1000] )';
Lookup_In = [ 000 110 001 100 101 010 011 ] ;
Lookup_Out = {'000000','000001','00001','0001','101','01','1' } ;
StrOut = repmat({''},[1,size(M,1)]);
for r=1:size(M2,1)
StrOut{r} = Lookup_Out{str2double(M2(r,:)) == Lookup_In};
end

Checking the repeated values and then finding mean

I m working on my project, where i have 2 images as Img1 and Img2.
As Img1 is the binary image so i have calculated all decimal values.
For Img2 i have taken the pixel values.
For convenience i have taken 10X10 matrix values from the entire image for the below operation.
[row,col] = size(Img1);
m = zeros(row,col);
w = [1 2 4 8; 16 32 64 128; 256 512 1024 2048; 4096 8192 16384 32768];
for i=2:10
for j=2:10
O = double(Img1(i-1:i+2,j-1:j+2));
m(i,j) = sum(sum(O.* w));
end;
end;
[row,col] = size(Img2);
count = row*col;
outMat = zeros(4,4,count);
l=0;
%m = zeros(row,col);delete
O = zeros(1,256);
for i=2:10
for j=2:10
l=l+1;
outMat(:,:,l) = Img2(i-1:i+2,j-1:j+2);
vec = outMat(3,3,:);
vec = vec(:);
end;
end;
Now, for Img2 , i have collected all pixel values, and need to store 2 col.as below.
Col1 col2 from Img2
from Img1
44128 162
54960 150
58320 119
31200 120
48240 180
54960 160
44128 163
51109 90
44128 56
Here, 44128 is repeated 3 times,now adding all correspong mapping values from col2 i.e.
162,163,56 add them all divide by 3(becos occurance of 44128 is 3 times) and same procedure
to be followed for all values.
44128 (162+163+56)/3
54960 (150+160)/2
58320 (119/1)
31200 (120/1)
48240 (180/1)
51109 (90/1)
Here, I want to create an array N of 1D 1X(size of col) which acts as a counter of Img1 decimal
values,repeated values and store the counter values inside N, and then finding mean by dividing corresponding counter values of N to the Img2 pixel values as above.
Please help:-( , how can i write the code further.
Here's a way doing it using sparse.
Accumulate sums and counts:
S = sparse(Img1, ones(size(Img1)), Img2);
N = sparse(Img1, ones(size(Img1)), ones(size(Img2)));
Determine which values actually occur:
ind = find(N)
Extract sums and counts for those values:
S = full(S(ind))
N = full(N(ind))
Compute corresponding means
M = S ./ N
For your example numbers, this gives
ind =
31200
44128
48240
51109
54960
58320
S =
120
381
180
90
310
119
N =
1
3
1
1
2
1
M =
120
127
180
90
155
119
Try this:
totals = sparse(1, Img1, Img2 );
denominators = sparse( 1, Img1, 1);
img1vals = find(totals);
averages = nonzeros(totals) ./ nonzeros(denominators);
[img1vals(:) averages(:)]

matlab how to delete rows using logical index

I have a matrix:
A = [ 4567 345; 45 6787; 3345 NaN; 87 6787]
and a vector
B = [ 4567; 45; 8976 ]
I want to compare A and B and delete in A all the rows that do not have at least one number which is included in matrix B.
The resulting matrix would be:
[ 4567 345;
45 6787 ]
Here is the code:
idx=ismember(A(:,1:2),B); %%create a logical index in order to see if A includes elements of B
n = length(A)
for i=1:n
if (idx(i,1)==0)& (idx(i,2)==0)
A(i,:)=[];
end
end
However I got this error:
Index of element to remove exceeds matrix dimensions.
I tried with another solution but I get the same error.
n = length(A)
for i=1:n
if (find(idx(i,1)==0))& (find(idx(i,2)==0))
A(i,:)=[];
end
end
You do not need a loop in this logical indexing task:
ismember(A,B)
ans =
1 0
1 0
0 0
0 0
All you need is to keep those rows with at least one match with any(...,2):
idx = any(ismember(A,B),2)
idx =
1
1
0
0
The result:
A(idx,:)
ans =
4567 345
45 6787
The error is caused by the fact that your loop runs from 1:n but you are removing rows from the matrix making it effectively shorter than n.
A = [ 4567 345; 45 6787; 3345 NaN; 87 6787]
B = [ 8976; 45; 4567 ]
z = sum(ismember(A,B)');
NewMatrix=[];
for i = 1:length(z)
if z(i)>= 1
newMatrix = A(i,:);
NewMatrix=[NewMatrix;newMatrix];
end
end
NewMatrix

MatLab to convert a matrix with respect to 1st col

This question is an outgrowth of MatLab (or any other language) to convert a matrix or a csv to put 2nd column values to the same row if 1st column value is the same? and Group values in different rows by their first-column index
If
A = [2 3 234 ; 2 44 99999; 2 99999 99999; 3 123 99; 3 1232 45; 5 99999 57]
1st column | 2nd column | 3rd column
--------------------------------------
2 3 234
2 44 99999
2 99999 99999
3 123 99
3 1232 45
5 99999 57
I want to make
1st col | 2nd col | 3rd col | 4th col | 5th col | 6th col| 7th col
--------------------------------------------------------------------
2 3 234 44
3 123 99 1232 45
5 57
That is, for each numbers in the 1st col of A, I want to put numbers EXCEPT "99999"
If we disregard the "except 99999" part, we can code as Group values in different rows by their first-column index
[U, ix, iu] = unique(A(:,1));
vals = reshape(A(:, 2:end).', [], 1); %'// Columnize values
subs = reshape(iu(:, ones(size(A, 2) - 1, 1)).', [], 1); %'// Replicate indices
r = accumarray(subs, vals, [], #(x){x'});
But obviously this code won't ignore 99999.
I guess there are two ways
1. first make r, and then remove 99999
2. remove 99999 first, and then make r
Whichever, I just want faster one.
Thank you in advance!
I think options 1 is better, i.e. first make r, and then remove 99999. Having r, u can remove 99999 as follows:
r2 = {}; % new cell array without 99999
for i = 1:numel(r)
rCell = r{i};
whereIs9999 = rCell == 99999;
rCell(whereIs9999) = []; % remove 99999
r2{i} = rCell;
end
Or more fancy way:
r2= cellfun(#(c) {c(c~=99999)}, r);