Distributing a function over a single array size in MATLAB?

I often find that I want to collapse an n-dimensional matrix in one dimension using a user-defined function and cannot figure out if there is a compressed spell I can use to do this.

For example, when analyzing an image, I often want to do something like this. (Note: for illustrative purposes only. I know about rgb2gray for this particular case.)

 img = imread('whatever.jpg'); s = size(img); for i=1:s(1) for j=1:s(2) bw_img(i,j) = mean(img(i,j,:)); end end 

I would like to express it somehow like:

 bw = on(color, 3, @mean); 

or

 bw(:,:,1) = mean(color); 

Is there a short way to do this?


EDIT: Apparently mean already doing this; I want to be able to do this for any function that I wrote. For example.
 ... filtered_img(i,j) = reddish_tint(img(i,j,:)); ... 

Where

 function out = reddish_tint(in) out = in(1) * 0.5 + in(2) * 0.25 + in(3) * 0.25; end 
+6
function arrays matrix multidimensional-array matlab
source share
5 answers

Many basic MATLAB functions, such as MEAN , MAX , MIN , SUM , etc., are designed to work on a specific size:

 bw = mean(img,3); %# Mean across dimension 3 

You can also take advantage of the fact that MATLAB arithmetic operators are designed for elementary modulation on matrices. For example, the operation in your reddish_tint function can be applied to all the pixels in your image with this separate line:

 filtered_img = 0.5.*img(:,:,1)+0.25.*img(:,:,2)+0.25.*img(:,:,3); 

To handle the more general case when you want to apply a function to an arbitrary size of an N-dimensional matrix, you probably want to write your function in such a way that it takes an additional input argument for which the measurement should be performed (like the aforementioned MATLAB functions), and then uses some simple logic (i.e., if-else statements) and elementary matrix operations to apply its calculations to the matrix’s own dimension.

Although I would not suggest using it, there is a quick and dirty solution, but it is quite ugly and computationally more expensive. You can use the NUM2CELL function to collect the values ​​of the size of your array into the cells of the cell array, and then apply your function to each cell using the CELLFUN function:

 cellArray = num2cell(img,3); %# Collect values in dimension 3 into cells filtered_img = cellfun(@reddish_tint,cellArray); %# Apply function to each cell 
+6
source share

I wrote a helper function called "vecfun" that can be useful for this if this is what you are trying to achieve?

link

+5
source share

You can use BSXFUN for at least some of your tasks. It performs an elementary operation between two arrays, expanding the size 1 - sizes to fit the size in another array. The reddish function will become

 reddish_image = bsxfun(@times,img,cat(3,0.5,0.25,0.25)); filtered_img = sum(reddish_image,3); 

All of the above statement requires that the work is that the third size img has a size of 1 or 3. The number and size of other dimensions can be freely selected.

+3
source share

If you are successively trying to apply a function to a vector contained in 3 dimensions in an image block, I recommend using a couple of transformations, for example:

 Img = rand(480,640,3); sz = size(Img); output = reshape(myFavoriteFunction(reshape(Img,[prod(sz(1:2)),sz(3)])'),sz); 

Thus, you can change any function that works with matrices along their first dimension.

to change. The above code will fail if you enter an image that has only one layer: the function below can fix it.

 function o = nLayerImage2MatrixOfPixels(i) %function o = nLayerImage2MatrixOfPixels(i) s = size(i); if(length(s) == 2) s3 = 1; else s3 = s(3); end o = reshape(i,[s(1)*s(2),s(3)])'; 
+2
source share

Well, if you are only concerned about multiplying vectors together, you can just use a dot product, for example:

 bw(:,:,1)*[0.3;0.2;0.5] 

taking care of the conformity of the shapes of your vectors.

+1
source share

All Articles