How can I perform this non circular shift in Matlab? [closed] - matlab

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am trying to perform a non circular shift in MATLAB. I have
A = [1 2 3 4 5; 0 0 13 14 15; 21 22 23 24 25; 0 0 33 34 35 ; 41 42 43 44 45]
and
B = [1 2 3 4 5; 11 12 13 14 15; 21 22 23 24 25; 31 32 33 34 35 ; 41 42 43 44 45]
How can I shift the indexes of the even rows and is it possible to fill in the empty indexes with an integer of choice?
Desired outputs:
A =
1 2 3 4 5
13 14 15
21 22 23 24 25
33 34 35
41 42 43 44 45
B =
1 2 3 4 5
11 12 13 14 15
21 22 23 24 25
31 32 33 34 35
41 42 43 44 45
Edit: Realized I messed up the desired output of matrix B. I had accidentally omitted some of the elements. Trying to shift the variables over to the right non circularly

Using Indexing and Concatenation
Input Arrays:
A = [1 2 3 4 5;
0 0 13 14 15;
21 22 23 24 25;
0 0 33 34 35 ;
41 42 43 44 45];
B = [1 2 3 4 5;
11 12 13 14 15;
21 22 23 24 25;
31 32 33 34 35;
41 42 43 44 45];
Shifting Even Rows Left:
To shift the arrays you can index the arrays relative to the Shift_Factor in this case 2. You can alternatively use circshift() and overwrite the portions of the array with zeroes/the desired Fill_Value. Here a for loop with an increment value of 2 is used to iterate over all the even rows. Upon each iteration, a partition of the array A(Row,Shift_Factor+1:end) is concatenated to an arbitrary fill array Fill_Value*ones(1,Shift_Factor).
Shift_Factor = 2;
Fill_Value = 0;
[Number_Of_Rows,Number_Of_Columns] = size(A);
for Row = 2: +2: Number_Of_Rows
A(Row,:) = [A(Row,Shift_Factor+1:end) Fill_Value*ones(1,Shift_Factor)];
end
A
Shifting Even Rows Right
Shift_Factor = 2;
Fill_Value = 0;
[Number_Of_Rows,Number_Of_Columns] = size(B);
B = [B zeros(Number_Of_Rows,Shift_Factor)];
for Row = 2: +2: Number_Of_Rows
B(Row,:) = [Fill_Value*ones(1,Shift_Factor) B(Row,1:end-Shift_Factor)];
end
B
Ran using MATLAB R2019b

Related

Change values in matrix if it matches a table

Hello I'm trying to do the following:
This is my table :
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
and I have a matrix [25,1].
I want to do the following: if the values in first and last columns match the numbers in the matrix, change the value to "99".
So the output should be this:
99
2
3
4
99
99
7
8
9
99
99
12
13
14
99
99
17
18
19
99
99
22
23
24
99
This is my attempt:
NT = zeros (x*y:1);
NT(:,1) = 1:x*y;
for i = 1:x*y
for j = 1
if NT(i,j) == x1(i,j)
NT(i,j) = 99;
end
end
end
This can be done very easily with ismember. Let
A = [1 2 3 4 5; 6 7 8 9 10; 11 12 13 14 15; 16 17 18 19 20; 21 22 23 24 25];
B = (1:25).';
new_value = 99;
Then
B(ismember(B, A(:, [1 end]))) = new_value;
gives
B =
99
2
3
4
99
99
7
8
9
99
99
12
13
14
99
99
17
18
19
99
99
22
23
24
99

Implementing matching pursuit algorithm

I have implemented matching pursuit algorithm but i m unable to get the required result.
Here is my code:
D=[1 6 11 16 21 26 31 36 41 46
2 7 12 17 22 27 32 37 42 47
3 8 13 18 23 28 33 38 43 48
4 9 14 19 24 29 34 39 44 49
5 10 15 20 25 30 35 40 45 50];
b=[6;7;8;9;10];
n=size(D);
A1=zeros(n);
R=b;
H=10;
if(H <= 0)
error('The number of iterations needs to be greater then 0')
end;
for k=1:1:H
[c,d] = max(abs(D'*R)); %//'
A1(:,d)=D(:,d);
D(:,d)=0;
y = A1\b;
R = b-A1*y;
end
Output
y=
0.8889
0
0
0
0
0
0
0
0
0.1111
I should get only non-zero value at (2,1) and other values should be zero but I'm getting 2 non-zero value. Can you please help me find out where the error is?
Thanks.
I checked with:
http://www.scholarpedia.org/article/Matching_pursuit
Your functions need to be normalized!
D = D./repmat(sum(D,1),5,1);
I get the following algorithm:
D=[1 6 11 16 21 26 31 36 41 46
2 7 12 17 22 27 32 37 42 47
3 8 13 18 23 28 33 38 43 48
4 9 14 19 24 29 34 39 44 49
5 10 15 20 25 30 35 40 45 50];
D = D./repmat(sum(D,1),5,1);
b=[6;7;8;9;10];
n=size(D);
A1=zeros(n);
R=b;
H=100;
if(H <= 0)
error('The number of iterations needs to be greater then 0')
end;
a = zeros(1,H);
G = zeros(size(D,1),H);
for k=1:1:H
ip = D'*R;
[~,d] = max(abs(ip)); %//'
G(:,k) = D(:,d);
a(k) = ip(d);
R = R-a(k)*G(:,k);
end
% recover signal:
Rrec = zeros(size(R));
for i=1:H
Rrec = Rrec + a(i)*G(:,i);
end
figure();
plot(b);
hold on;
plot(Rrec)
It approximates the signal quite well. But not with D(:,2) at first as expected. Maybe it is a starting point...
Here is the updated code. This is based on the algorithm provided at https://en.wikipedia.org/wiki/Matching_pursuit
clc;
clear all;
D=[1 6 11 16 21 26 31 36 41 46
2 7 12 17 22 27 32 37 42 47
3 8 13 18 23 28 33 38 43 48
4 9 14 19 24 29 34 39 44 49
5 10 15 20 25 30 35 40 45 50];
b=[6;7;8;9;10];
H=10;
for index=1:10
G(:,index)=D(:,index)./norm(D(:,index));
end
G1=G;
n=size(G);
R=b;
if(H <= 0)
error('The number of iterations needs to be greater then 0')
end;
if(H >size(D,2))
error('The number of iterations needs to be less than dictionary size')
end;
bIndex=1:size(G,2);
for k=H:-1:1
innerProduct=[];
for index=1:size(G,2)
innerProduct(index)=dot(R,G(:,index));
end
[c,d] = max(abs(innerProduct));
An(H-k+1)=innerProduct(d);
R = R-(An(H-k+1)*G(:,d));
G(:,d)=[];
strong(H-k+1)=bIndex(d);
bIndex(d)=[];
end
G_new=G1(:,strong);
%% reconstruction
bReconstructed=zeros(size(G_new,1),1);
for index=1:size(G_new,2)
bReconstructed(:,index) = (An(index)*G_new(:,index));
end
b_new=sum(bReconstructed,2)
Yes the atoms in the dictionary must be normalized so that the inner products of the current residual with different atoms can be compared fairly.
You may want to check my OMP implementation which also includes incremental Cholesky updates for the least square step in OMP at https://github.com/indigits/sparse-plex/blob/master/library/%2Bspx/%2Bpursuit/%2Bsingle/omp_chol.m
I have written detailed tutorial notes on OMP in my library documentation at https://sparse-plex.readthedocs.io/en/latest/book/pursuit/omp/index.html
My library sparse-plex contains a C implementation of OMP which is close to 4 times faster than fastest MATLAB implementations. See the discussion here https://sparse-plex.readthedocs.io/en/latest/book/pursuit/omp/fast_omp.html

How to rearrange each image patch into number of column vector [duplicate]

This question already has answers here:
Efficient Implementation of `im2col` and `col2im`
(2 answers)
Closed 7 years ago.
I am working on a project where i have used a image whose size is (512x512)then i have divided the whole image by 8 so that there will be 64x64 block then i have to rearrange each 8x8 image patch into a single column so that new size would be
64x4069. unable to understand how to do it.please help.
Here is my code
enter code here
a=imread('lena.png');
b=double(a);
[r,c]=size(b);
bl=8;
br=r/bl;
bc=r/bl;
It will arrange in such a order that first column would be image patch of (1:8,1:8)next column would be(9:16,9:16)likewise.
If reshape is allowed, permute is definitely allowed.
Assuming both the original and block sub-matrix are square matrices
Here is one approach
out = permute(reshape(A,blSz,size(A,1)/blSz,blSz,[]),[1 3 2 4]);
out = reshape(out,size(out,1)*size(out,1),[]);
Sample inputs:
A = randi(50,8); %// Change it with your original `512x512` matrix
blSz = 2; %// Change it to 8 for your problem
Results:
>> A
A =
31 17 18 10 33 31 43 16
20 40 31 15 34 23 42 6
46 24 10 5 32 23 13 47
1 2 37 29 48 34 31 33
24 9 13 35 11 39 30 24
22 37 46 28 36 18 28 32
24 24 14 22 12 34 44 28
39 8 39 33 6 21 14 33
>> out
out =
31 46 24 24 18 10 13 14 33 32 11 12 43 13 30 44
20 1 22 39 31 37 46 39 34 48 36 6 42 31 28 14
17 24 9 24 10 5 35 22 31 23 39 34 16 47 24 28
40 2 37 8 15 29 28 33 23 34 18 21 6 33 32 33
Using loops as OP requested
A = randi(50,8);
blSz = 2;
nBl = size(A,1)/2;
out = zeros(size(reshape(A,blSz*blSz,[])));
count = 1;
for ii = 1:nBl
for jj= 1:nBl
block = A((jj-1)*blSz + 1:(jj-1)*blSz + blSz, (ii-1)*blSz + 1:(ii-1)*blSz + blSz);
out(:,count) = block(:);
count = count + 1;
end
end
Gives the same result as above!
Alternative for im2col using vectorized approach
newOut = mat2cell(reshape(out,blSz,[]),blSz,repmat(blSz,size(out,2),1));
newOut = cell2mat(reshape(newOut,nBl,[]));

Matlab: add vector to matrix

I have a 3XN matrix representing a list of 3D coordinates,something like
33 33 33 33 34 34 34 34 34 35 35
17 18 19 20 16 17 18 19 20 16 17
10 10 10 10 10 10 10 10 10 10 10
I want to shift all coordinates by some vector v=[1 2 3], that is add the 3D vector to each column of the matrix.
I know how to do that with a for loop, but how can I do it without a loop? Surely there's a way...
you mean like this?
D=[33 33 33 33 34 34 34 34 34 35 35;
17 18 19 20 16 17 18 19 20 16 17;
10 10 10 10 10 10 10 10 10 10 10 ];
A=[1 2 3]';
C= bsxfun(#plus, D, A)
C =
34 34 34 34 35 35 35 35 35 36 36
19 20 21 22 18 19 20 21 22 18 19
13 13 13 13 13 13 13 13 13 13 13
Use repmat:
M = randn(3, N); % your 3 x N matrix
v = randn(3, 1); % your vector
r = M + repmat(v, [1 N]); % add v to every column of M

sum over a matrix with condition in matlab

assume I have a 10x10 matrix M
M=[64 36 50 87 22 45 37 23 68 88;
33 23 87 49 54 25 35 98 78 52;
12 54 76 43 24 87 54 98 45 34;
77 87 23 45 34 65 23 76 12 76;
12 34 55 44 76 98 93 23 54 67;
22 55 78 90 88 56 34 23 12 76;
99 23 67 89 34 23 12 87 45 23;
22 54 76 89 65 23 45 12 93 12;
44 56 23 88 67 14 15 67 34 12;
11 44 77 99 34 23 78 34 12 79];
I want to first find out the local maximum in the matrix
and then according to the maximum position do a sum over a 3x3 region over M
For the first step, the code I used is local_max=imregionalmax(M). to find out the local maximum position, but how can I go further to use this coordination to sum over a 3x3 matrix over M?
Thanks for the help.
You can calculate the sum for the whole matrix and then only keep the values that you're interested in. This should work:
local_max=imregionalmax(M)
sums = imfilter(M, ones(3));
local_max_sums = sums(local_max);
And if what you want is a matrix with non-zero entries where the local maxima are located:
local_max_sums = sums .* local_max;
You seem to be looking for the matrix subset functionality of Matlab.
Basically, for
M = [ 1 2 3 4 5 6;
4 5 6 7 8 9;
7 8 9 0 1 2;
0 1 2 3 4 5;
3 4 5 6 7 8;
6 7 8 9 0 1];
If you have a max at (3,3), you can use M(2:4, 2:4) to get
N = [ 5 6 7;
8 9 0;
1 2 3];
Summing that matrix is all that remains - as simple as
total = sum(N(:));
This is kind of brute force for Matlab, but I think it works.
bw = imregionalmax(M);
[x,y] = find(bw);
s = [];
for i = 1:length(x)
startX = x(i)-2;
if(startX < 1)
startX = 1;
end
endX = x(i)+2;
if endX > 10
endX = 10;
end
startY = y(i)-2;
if startY < 1
startY = 1;
end
endY = y(i)+2;
if endY > 10
endY = 10;
end
s(i) = sum2(M(startX:endX, startY:endY));
end