필터 지우기
필터 지우기

How can I split a matrix into N different parts?

조회 수: 33 (최근 30일)
matlabkid602
matlabkid602 2017년 7월 20일
댓글: Jan 2018년 1월 17일
I have a 120x30 matrix of data points, how can I split the matrix into nine equal parts of 400 data chunks and store them as separate matrices?
  댓글 수: 2
Stephen23
Stephen23 2017년 7월 20일
편집: Stephen23 2017년 7월 20일
"how can I split the matrix into nine equal parts of 400 data chunks and store them as separate matrices?"
While this is possible it would make your code slow, buggy, inefficient, hard to read, hard to debug, etc, etc. Here is what the MATLAB documentation says about magically creating variable names like that: "A frequent use of the eval function is to create sets of variables such as A1, A2, ..., An, but this approach does not use the array processing power of MATLAB and is not recommended. The preferred method is to store related data in a single array."
As you can read, the much better alternative is use one array and indexing. Indexing is simple, very efficient, neat, easy to read, easy to debug, etc, etc.
You can read more explanations and discussions here:
Just use indexing: simple, efficient, neat, easy to debug, easy to understand,... Or you could split the array into a cell array of numeric arrays: see mat2cell and num2cell.
Stephen23
Stephen23 2017년 7월 24일
편집: Stephen23 2017년 7월 24일
Note to browsers of this thread: If you want to write fast, neat, efficient, and robust code then scroll down to Jan Simon's answer. It is not required to use slow and buggy code to solve this task.

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

채택된 답변

John BG
John BG 2017년 7월 20일
편집: John BG 2017년 7월 20일
Hi matlabkid602
to split 120x30 matrix into chunks of 400 pixels, there are many different ways, like for instance selecting 400 random points and removing the just selected points from the matrix iterating until no points left, or using masks or patterns for similar elimination.
One can also sequentially pull strings of 400 pixels at a time, like Jan has concisely shown above, with a resulting cell.
For rectangular matrices, it is reasonable to aim at splitting the matrix into smaller rectangle chunks.
The following splits your 3600 points matrix into sub-rectangles of 400 points each
1.
loading example matrix
clear all;clc;close all
A=imread('001.jpg');
imshow(A)
2.
Scaling down to 120x30 pixels
the rulers are in pixels
.
.
3.
Simplifying to single RGB layer, made available in attached image 003.jpg
A=imread('003.jpg')
A=A(:,:,1);
fh=figure(1);imshow(A);ax=gca
fh.MenuBar='none'
fh.ToolBar='none'
fh.Position=[500 500 1440 360]
ax.OuterPosition=[0 0 1 1]
.
3.
Finding out how many rectangle chunks have 400 pixels area
L1=120 % x, horizontal
L2=30 % y, vertical
A0=400 % target area
K=L1*L2/A0 % how many equal area chunks, K is your N
x=[1:10]
y=[1:10]
[X,Y]=meshgrid(x,y)
L=(L1./X).*(L2./Y);
figure(4);S=surf(L)
.
N1=find(S.ZData==A0)'
% N1 =
% 9 23 81
It turns out vertical and horizontal slicing may also be possible
L(N1)
% =
% 400 400 400
% the slicing
a=X(N1)
% =
% 1 3 9
b=Y(N1)
% =
% 9 3 1
But since it's reasonable to assume that data points cannot be split, for the case pixels, the horizontal and vertical slicing cases a=1 b=9, a=9 a=1 have to be excluded.
Choosing the elements that are neither 1 or K
a=3;b=3
4.
Generating variable containing the rectangles
La=[1:L1/a:L1];
Lb=[L2:L2/b:L2];
D=zeros(L2/b,L1/a,K);
s=1
for j=1:1:b
for i=1:1:a
n2=[(j-1)*L2/b+[1:1:L2/b]]
n1=[(i-1)*L1/a+[1:1:L1/a]]
D(:,:,b*(j-1)+i)=A(n2,n1);
end
end
D=uint8(D) % for imshow to work correctly
close all;
for s=1:1:K
figure(s);imshow(D(:,:,s));
fh=figure(s);imshow(D(:,:,s));ax=gca
fh.MenuBar='none'
fh.ToolBar='none'
fh.Position=[500 500 480 120]
ax.OuterPosition=[0 0 1 1]
end
fh=figure(10)
for s=1:1:K
subplot(b,a,s);imshow(D(:,:,s))
end
.
5.
Dynamic generation of variables
Some people like the dynamic generation of variables with for instance command e evalin, some other people don't like such approach.
evalin is a very powerful command and I am using it here to generate the separate matrices you have asked for
.
str1=repmat('Chunk_',K,1) % building strings for evalin
N0=num2str(100+[1:1:K]');N0(:,1)=[]
N1=repmat('=D(:,:,',K,1)
N2=repmat(')',K,1)
str2=[str1 N0 N1 num2str([1:1:K]') N2]
for s=1:1:K % running evalin
L2=str2(s,:);
evalin('base',L2);
end
.
Now you have a list of smaller matrices containing the rectangular chunks
Chunk_01
Chunk_02
Chunk_03
Chunk_04
Chunk_05
Chunk_06
Chunk_07
Chunk_08
Chunk_09
if you find this answer useful would you please be so kind to consider marking my answer as Accepted Answer?
To any other reader, if you find this answer useful please consider clicking on the thumbs-up vote link
thanks in advance
John BG
  댓글 수: 1
Jan
Jan 2017년 7월 22일
편집: Jan 2017년 7월 22일
The shown code works in the command window only, because evalin('base') creates the variables in the Base-WorkSpace. Hundreds of threads in this forum explain the drawbacks of the dynamic creation of variables exhaustively. See Stephen's comment above.

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

추가 답변 (2개)

Jan
Jan 2017년 7월 20일
편집: Jan 2017년 7월 22일
Storing in separate matrices might be a bad idea. Why not using the matrix itself?
data = rand(120, 30);
data9 = reshape(data, [], 9);
dataC = cell(1, 9);
for iC = 1:9
dataC{iC} = data9(:, iC);
end
Here you get the different vectors as a cell array. But I'd prefer to work with data9: The i.th block is data9(:, i).
[EDITED] You can split the matrix to a 3x3 set uf submatrices efficiently without nested loops by:
sM = size(M);
c = reshape(M, sM(1) / 3, 3, sM(2) / 3, 3);
M33 = permute(reshape(c, 4, 3, 3, 3), [1, 3, 2, 4]);
M9 = reshape(M33, [4, 3, 9]);
Now the matrix is divived in 3 x 3 submatrices of the same size, which can be addressed by M9(:, :, i) with the index 1 to 9 or by using M33(:, :, x, y) with x and y going from 1 to 3.
This is much faster then nested loops.
  댓글 수: 2
Kodavati Mahendra
Kodavati Mahendra 2018년 1월 17일
편집: Kodavati Mahendra 2018년 1월 17일
regarding the edit you made, c has more than 4*3*3*3 elements.
sM = size(M);
M33 = permute(reshape(M,sM(1)/3,3,sM(2)/3,3),[1,3,2,4]);
M9 = reshape(M33, [sM(1)/3,sM(2)/3,9]);
Is this the correct code or did I misunderstand it?
Jan
Jan 2018년 1월 17일
@Kodavati Mahendra: This looks fine.

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


Image Analyst
Image Analyst 2017년 7월 22일
You didn't specify how you wanted the matrix split up, since neither 120 nor 30 is a multiple of 9. So I just made 9 vectors taking the data column by column from upper left to lower right. Try this:
data = rand(120,30); % Sample data
% Now split up into 9 row vectors.
m1 = data(1:1*400);
m2 = data(1*400+1 : 2*400);
m3 = data(2*400+1 : 3*400);
m4 = data(3*400+1 : 4*400);
m5 = data(4*400+1 : 5*400);
m6 = data(5*400+1 : 6*400);
m7 = data(6*400+1 : 7*400);
m8 = data(7*400+1 : 8*400);
m9 = data(8*400+1 : 9*400);
If those aren't the 9 arrays you were thinking of them clarify the location of where the elements for each matrix are supposed to come from.

카테고리

Help CenterFile Exchange에서 Variables에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by