A general way to create helper arrays around a specific element

What is a quick, elegant way to use MatLab to form a subarray around a specific element? An element is randomly selected from the data, so you cannot take submassion in the usual way (it must be generalized for the selected elements). I mean: forming an array, like 5x5 or 7x7, or something else where the middle element is the one you want.


Thanks, but I mean a more general approach. Sorry for not understanding. I mean something like, say

a = magic(10) b = find(a<8) %giving linear indices m = size(a) [r,c] = ind2sub(m,b) %giving rows and columns of the elements that you later want to select 

and then I thought about how to use the rest for loops, but I'm not sure how to generalize it, and wondered, as I said, if there is an easier way to do this with MatLab.

The reason for this general approach is that I want to analyze any array for elements with certain properties, and then be able to form a subarray around each element in order to basically increase it for further data analysis, if that makes sense.

+2
source share
2 answers

Here are some examples of how you can address this issue:

 mat = rand(10); %# A 10-by-10 array of random elements vec = -3:3; %# To make a 7-by-7 subarray subArray = mat(5+vec,4+vec); %# Get subarray centered on element (5,4) vec = -2:2; %# To make a 5-by-5 subarray subArray = mat(3+vec,3+vec); %# Get subarray centered on element (3,3) 

Of course, you will need to be wary of conditions where your indexes go beyond the matrix that you are indexing, and then decide how you want to deal with this situation (i.e. return only the part of the subarray that is inside the larger matrix, or overlays larger matrix using PADARRAY to avoid this situation, etc.).

EDIT:

To summarize the above for the point sets that you want to receive as arrays, the solutions given by Jonas should work well. The only drawback is that you will need to access the Image Processing Toolbox . Here's a solution that will work without additional toolbars using a , r and c , as you defined them in the question:

 blockSize = 3; %# Block size around each point padSize = floor(blockSize/2); %# Padding size for the matrix aPad = padarray(a,[padSize padSize],NaN); %# Pad the matrix with NaNs rPad = r+padSize; %# Shift the row indices cPad = c+padSize; %# Shift the column indices blockIndices = (1:blockSize)-ceil(blockSize/2); %# Create indices for a block getBlockFcn = @(r,c) aPad(r+blockIndices,c+blockIndices); %# Function to get %# a block subArrays = arrayfun(getBlockFcn,rPad,cPad,... %# Create a cell array with 'UniformOutput',false); %# one block per cell 

This will give you an array of N-on-1 subArrays , where N is the number of points you have. If, for example, you want to get the maximum subarray value for point 3, you can do the following:

 maxValue = max(subArrays{3}(:)); %# MAX will ignore NaN values 

To take the average value of the entire subarray, you either first need to remove NaN (using the ISNAN function) or use the NANMEAN function from the Statistics Toolbox :

 mat = subArray{3}(:); %# Values from subarray meanValue = mean(mat(~isnan(mat))); %# Mean of non-NaN values %# Or... meanValue = nanmean(subArrays{3}(:)); %# Mean of non-NaN values 
+1
source

If you want to collect separate (possibly overlapping) neighborhoods into an array so that you can process each area separately, you can use IM2COL . If you want to create a β€œhalo” around each element to easily capture all areas of the candidates so that matches are not counted twice, you can use IMDILATE .

Example for im2col

 %# create array and get linear index of interesting elements a = magic(10); b = find(a<8); %# define region size subSz = 3; %# for 3x3 array halfSz = floor(subSz/2); %# for a 3x3 array, there window extends 1 pix to each side %# pad a with NaNs so that sub-window never goes outside the image ap = padarray(a,[halfSz halfSz],NaN); %# convert ap to columns - there are 9 rows (for 3x3 window) and as many columns as there %# are elements in a (100 in this example) apCol = im2col(ap,[subSz,subSz]); %# select columns of interest %# the first column contains the first neighborhood of interest, the second column %# the second neighborhood etc. interestingColumns = apCol(:,b); %# take eg the average of each neighborhood avg = nanmean(interestingColumns,1); 

Example for imdilate

 %# create array and get logical mask where 1 indicates an interesting element a = magic(10); bw = (a<8); %# define region size subSz = 3; %# for 3x3 array %# grow each element, so that a single 'good' pixel is in the center of a 3x3 mask bwDil = imdilate(bw,strel('square',subSz)); %# show the centers in white, 'halo' in grey %# note the overlaps figure,imshow(bw+bwDil,[]) %# take the average of all 'labeled' pixels avg = mean(a(bwDil)); 
+1
source

Source: https://habr.com/ru/post/1308069/


All Articles