Shifting a multidimensional matrix

조회 수: 12 (최근 30일)
Alex Feinman
Alex Feinman 2012년 10월 12일
댓글: Pascal Loohuis 2019년 9월 17일
I'm trying to offset a matrix by a certain distance, like dragging an image partially out of frame.
The 'new' area gets filled with zeroes or NaNs, and the 'extra' area gets clipped, so you end up with a new matrix the same size as the original.
In one dimension this is easy--just add 0s to the size of the offset:
offset = 3;
dest = [zeros(1, offset), original(1:end-offset)];
But I'm having trouble generalizing this to n dimensions. Is there an algorithmic way to handle this, or a built-in I've missed?
EDIT: To clarify, in the N dimensional case, offset is a vector of N elements, some of which can be negative.
For example:
A = ones([3 3]);
offset = [1 1];
_function_(A, offset) =
0 0 0
0 1 1
0 1 1
offset = [1 -1];
_function_(A, offset) =
0 0 0
1 1 0
1 1 0

채택된 답변

Matt J
Matt J 2012년 10월 12일
편집: Matt J 2012년 10월 12일
I think this might be the generalization you're looking for of Azzi's approach,
function B=noncircshift(A,offsets)
%Like circshift, but shifts are not circulant. Missing data are filled with
%zeros.
%
% B=noncircshift(A,offsets)
siz=size(A);
N=length(siz);
if length(offsets)<N
offsets(N)=0;
end
B=zeros(siz);
indices=cell(3,N);
for ii=1:N
for ss=[1,3]
idx=(1:siz(ii))+(ss-2)*offsets(ii);
idx(idx<1)=[];
idx(idx>siz(ii))=[];
indices{ss,ii}=idx;
end
end
src_indices=indices(1,:);
dest_indices=indices(3,:);
B(dest_indices{:})=A(src_indices{:});
  댓글 수: 2
Matt Fig
Matt Fig 2012년 10월 12일
Nice!
Pascal Loohuis
Pascal Loohuis 2019년 9월 17일
What if the shifts are different for each layer?

댓글을 달려면 로그인하십시오.

추가 답변 (3개)

Azzi Abdelmalek
Azzi Abdelmalek 2012년 10월 12일
편집: Azzi Abdelmalek 2012년 10월 12일
offset=3
A=rand(10,12);
[n,m]=size(A)
out=zeros(n,m)
out(:,offset+1:m)=A(:,1:m-offset)
If your matrix is nxmxp
offset=3
A=rand(10,12,3);
[n,m,p]=size(A)
out=zeros(n,m,p)
out(:,offset+1:m,:)=A(:,1:m-offset,:)
  댓글 수: 4
Alex Feinman
Alex Feinman 2012년 10월 12일
편집: Alex Feinman 2012년 10월 12일
This only appears to shift things along the first dimension of offset? (I apologize for being so unclear.)
Azzi Abdelmalek
Azzi Abdelmalek 2012년 10월 12일
Ok, I did'nt read your full comment. I have a second answer

댓글을 달려면 로그인하십시오.


Matt J
Matt J 2012년 10월 12일
First, recognize that in 1D, this can be done by a sparse matrix multiplication
offset=3;
N=10;
x=(1:N).'
S=speye(N); %N is length of vector
S=circshift(S,[offset,0]);
S(1:offset,:)=0;
dest= S*x,
To generalize to 2D, multiply all the columns and rows by S
x=rand(N,N);
dest=S*x*S.';
Or, if you have different offsets in different dimensions, you'll need separate matrices Sx and Sy.
To generalize to 3D and higher, I recommend using my KronProd package
x=rand(N,N,N);
dest=KronProd({S},[1,1,1])*x;
where KronProd is available here
  댓글 수: 2
Alex Feinman
Alex Feinman 2012년 10월 12일
What if offset contains negative numbers in some dimensions? I'm having trouble figuring that one out.
Matt J
Matt J 2012년 10월 12일
편집: Matt J 2012년 10월 12일
Only change
S(end+1-(1:-offset),:)=0;
However, Azzi's method can be similarly generalized and is probably better, now that I think about it. That's assuming you're restricting yourself to integer shifts. If you need to do sub-pixel shifts, where you need to interpolate, then my approach is more easily generalized, I think.

댓글을 달려면 로그인하십시오.


Azzi Abdelmalek
Azzi Abdelmalek 2012년 10월 12일
A=randi(10,4,8,2,4,4,3);
offset=[2 2 1 2 1 2];
siz=size(A);
n=numel(siz);
out=zeros(siz);
idx1=sprintf('%d:%d,',[offset+1; siz]);
idx1(end)=[];
idx2=sprintf('%d:%d,',[ones(1,n); siz-offset]);
idx2(end)=[];
eval(['out(' idx1 ')=A(' idx2 ')'])
  댓글 수: 3
Alex Feinman
Alex Feinman 2012년 10월 15일
It's possible that you could squeeze a lot of time out of your code but as they stand his is about 20% faster in my testing; just on that basis I'm going to accept his...but this is nice and compact!
Matt J
Matt J 2012년 10월 15일
I think part of the compactness is due to the fact that this solution doesn't support negative offsets. It's interesting that you favor EVAL. Most TMW employees seem to discourage it

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Resizing and Reshaping Matrices에 대해 자세히 알아보기

제품

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by