Hello. Suppose we have an 3D-array 4x4x4 with some values in it. The values are either 5 or 7.
A(:,:,1)=[5 5 7 7; 7 5 7 7; 5 5 5 5; 7 7 7 7];
A(:,:,2)=[5 5 7 7; 7 5 7 7; 5 5 5 5; 7 7 7 7];
A(:,:,3)=[5 5 7 7; 7 5 7 7; 5 5 5 5; 7 7 7 7];
A(:,:,4)=[5 5 7 7; 7 5 7 7; 5 5 5 5; 7 7 7 7];
How to refine this grid based on the majority rule? To make 2x2x2 grid, f.ex. Anew(1:1:1)= from 8 values of the blocks x1y1z1,x2y1z1,x1y2z1,x2y2z1,x1y1z2,x2y1z2,x1y2z2,x2y2z2 the values are 3 "5"s and 5 "7"th, so Anew(1:1:1)=7. If number of "5"s and "7"s is the same, choose "7".
The question is not easy, I think. Thank you!

 Akzeptierte Antwort

Massimo Zanetti
Massimo Zanetti am 8 Okt. 2016

4 Stimmen

You may want to histogram the 3D array by 3D histogram. There many functions in Matlab central, just search for "N dimensional histogram".

7 Kommentare

Vadim Tambovtsev
Vadim Tambovtsev am 8 Okt. 2016
I googled an ancient 2003 year thread for N dimensional histogram, but didn't manage to apply their scripts to my case. https://se.mathworks.com/matlabcentral/newsreader/view_thread/56544
For 1D array it is easy to make such averaging, but 3D-array is more complex.
Massimo Zanetti
Massimo Zanetti am 8 Okt. 2016
Bearbeitet: Massimo Zanetti am 8 Okt. 2016
Here I found a way to implement MAJORITY RULE in 3D array.
%array sizes
x=4; y=4; z=4;
%size of the block hxhxh
h=2;
%generate random 3d matrix of integers
A=randi(10,x,y,z)-1;
%initialize some useful indeces
ix=1:h:x; iy=1:h:y; iz=1:h:z;
[X,Y,Z]=meshgrid(ix,iy,iz);
D = reshape( 1:(x*y*z)/(h^3) , x/h , y/h , z/h );
H = 0:h-1;
%collect all the blocks in a cell
E = arrayfun( @(j) A(Y(j)+H,X(j)+H,Z(j)+H) , D , 'UniformOutput' , false );
%majority rule work as *mode* computed for each block
B = cell2mat( cellfun( @(block) mode(block(:)) , E , 'UniformOutput' , false ) )
To be more general, if you need blocks with size h1xh2xh3, this can be easily modified.
Vadim Tambovtsev
Vadim Tambovtsev am 8 Okt. 2016
Your script is correct, but a have a comment. From the values in the "volume", it celects the most frequent value. However, if there are several values with the same frequency - it chooses the smallest.
Could you propose the modification, so that the program will choose a) the biggest value if the max frequencies are equal b) random value of these two values with the max frequeicies
Massimo Zanetti
Massimo Zanetti am 8 Okt. 2016
Bearbeitet: Massimo Zanetti am 8 Okt. 2016
Ok, I found a trick by "overriding" the Matlab function mode, as in its call with only one output it only returns the smallest value. But other outputs have the information we want.
First, save in you current folder this function called myMode that overrides mode, and returns what we need (the biggest more frequent value):
function m=myMode(x)
[~,~,C]=mode(x);
%here you can play selecting what you want.
%to have biggest value (in this vector values are ordered ascending)
m=C{1}(end);
%to have some random value among the more frequent
%get a random element in C{1} (do it as an exercise)
end
Then in the other piece of code, just replace mode with myMode:
B = cell2mat( cellfun( @(block) myMode(block(:)) , E , 'UniformOutput' , false ) )
Vadim Tambovtsev
Vadim Tambovtsev am 8 Okt. 2016
Thank you.
Vadim Tambovtsev
Vadim Tambovtsev am 8 Okt. 2016
I haven't managed to get "random" values in myMode. Can you please tell me the answer?
m=C{1}( randi(numel(C{1})) );

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (2)

Jan
Jan am 8 Okt. 2016

0 Stimmen

If you realy have 2 values only, convert them to 0 and 1:
A(:,:,1)=[5 5 7 7; 7 5 7 7; 5 5 5 5; 7 7 7 7];
A(:,:,2)=[5 5 7 7; 7 5 7 7; 5 5 5 5; 7 7 7 7];
A(:,:,3)=[5 5 7 7; 7 5 7 7; 5 5 5 5; 7 7 7 7];
A(:,:,4)=[5 5 7 7; 7 5 7 7; 5 5 5 5; 7 7 7 7];
B = double(A == 7);
B = reshape(B, [2, 2, 2, 2, 2, 2]);
C = squeeze(sum(sum(sum(B, 1), 3), 5)) >= 4;
Result = 5 + C * 2;
% Or:
Result = repmat(5, [2,2,2]);
Result(C) = 7;
Andrei Bobrov
Andrei Bobrov am 8 Okt. 2016

0 Stimmen

B = mat2cell(A,[2,2],[2,2],[2,2]);
out = zeros(size(B));
for ii = 1:numel(out)
[a,~,c] = unique(B{ii}(:));
jj = accumarray(c,1);
k = sortrows([a,jj],[-2,-1]);
out(ii) = k(1);
end

Kategorien

Produkte

Community Treasure Hunt

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

Start Hunting!

Translated by