Find sorrunding elements and element from an array

I have an array
y = [
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0]
where Index 7,41,75 are the locations where 1 is found .
My requirement is
  • create a block around true(1) with a size of 5
  • get the indices like 5,6,7,8,9 and data 0 0 1 0 0

25 Comments

What shoud the output be if you have nearby pixels? For example
y = [
0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0]
  • include the nearby pixel as well in the block of 5 elements
  • if first pixel 1 then include next 4 elements
  • if end pixel 1 then include previous 4 elements
So to confirm, you would want [0 0 1 0 1] indices [5 6 7 8 9] and [1 0 1 0 0] indices [7 8 9 10 11] ?
Anyhow, what is your question?
So to confirm, you would want [0 0 1 0 1] indices [5 6 7 8 9] and [1 0 1 0 0] indices [7 8 9 10 11] ?
[0 0 1 0 1]
5 6 7 8 9 ==> Block 1
[1 0 1 0 0]
[7 8 9 10 11] ==> Block 2
we don't need block2 if the indices is in Block 1 . Index repeatation will consume memory and processing time increases.
And more so first indices and last indices should be 1st Indcie + 4(next ) & Last indice - 4 (previous)
we don't need block2 if the indices is in Block 1
So you want a single combined output that is longer, block1 = [0 0 1 0 1 0 0] indices [5 6 7 8 9 10 11] ?
You appear to be doing a homework assignment. When I read the homework assignment, I am left certain that you are intended to always produce blocks of 5. Index duplication and memory consumption is not a primary concern: the block of 5 is imposed by the question.
As such, there is a much easier solution to finding the indices. Hint: find() and min() and max() . You can calculate the starting and ending indices in vectorized form.
Once you have vectors of the starting and ending indices, you can loop or arrayfun to extract the contents.
You have a mis understing ! The requirement is
  • Block is needed as an input to process the polynomial vector.
  • movmax makes the poly bit as 1 .. This is incorrect since it over write poly error information
  • A block can start from 1 bit as 1 and trail bit either 0/1 .
  • In case of variable block/s, you know the CRC points in a data set then why re-run same data. This is using more memory (buffer) and processs time. I don't understand why this should not be concern
It will be a help to have a very simple code/algorithm if you can share just to have as a starting point,
I shared a sample code below, can you please add more robust logic to get desired results.
Thank you!
start = max(1, position-2);
stop = start + 4;
Now do the fix-up for end of buffer.
For end bit , I think padding is needed
For example
y1 = [1 0 0 0 0 ]
y2 = [0 1 0 0 0 ]
y3 = [0 0 1 0 0 ] & so on
to accomadate the block size fit the fixed polynomial size
No, padding is not needed, as long as the length of the input vector y is not less than the blocksize (5)
OK, we can do the reverse count from end and put the previous bit in to the array
y = [ 0 0 0 0 0 0 0 0 1 0]
position is 9 then ?
I expect the result should be
blockBits(:,:,1) = [1,0,0,0,0]
blockindcs(:,:,1) = [9, 10, 8,7,6]
No need to do reverse indices.
Think about the code I posted:
start = max(1, position-2);
stop = start + 4;
We started at some unknown position. We go blocksize/2 towards an edge that is of interest to us, which would normally get us the location of the edge. But we check whether taking that step would have positioned that tentative edge beyond the actual edge, and if it did then we substitute the coordinate of the actual edge instead. Then we take that (possibly substituted) coordinate and say that the other end of the block is the blocksize towards the other edge.
It is trivial to extend this to do the same logic against the other edge, detecting if we have passed the actual edge and if so moving the boundary to the actual edge and saying that the other end of the block is blocksize towards the front.
No no.. this is wrong explanation for edge detection
As per your logic ,
start = max(1, position-2);
stop = start + 4;
we don't know what is the error value at start but position define error.If you train
a edge detection polynomial with leading edge with non error bit. Then the logic won't make
sense
Below is an example
Leading bit can be 0.
a = [ 1 0 0 0 1 ]; sys = idpoly(a)
sys =
Discrete-time AR model: A(z)y(t) = e(t)
A(z) = 1 + z^-4
Sample time: unspecified
Parameterization:
Polynomial orders: na=4
Number of free coefficients: 4
Use "polydata", "getpvec", "getcov" for parameters and their uncertainties.
Status:
Created by direct construction or transformation. Not estimated.
K>> a = [ 0 0 0 0 1 ]; sys = idpoly(a)
Error using idpoly (line 384)
The leading coefficient of the "A" polynomial must be 1.
But for a polynomial leading position must 1 and tail bits can be 0/1. What if block started with 0. So edge detection will not proceed at the initial state.
For the end block , it is Ok to process 1-4 to additional bits to go pass the edge unless we have a conving logic
as I proposed
  • bit reverse
  • padd to sufice the block which is a polynomial
  • short polynomial
for a block to process for edge detection. The problem with Short polynomial size than a block size then we have size error...
Please have re look into below code and suggest solution for ( I prefer to have offset elements to have 0 filled , then we don't alter edge detection error bit and it will be safe)
if bit_position>= (siz_y-blksize)
blockBits(:,:,i) = y(bit_position:1:siz_y);
blockindcs(:,:,i) = (bit_position:1:siz_y);
end
Current implementation with a bad size for end block
y = [
0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0, ...
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0, ...
0 0 0 0 0 0 0 1 0]
siz_y = size(y,2);
[Val,idx] = find(y>0);
blksize = 5;
blockBits = zeros(1,blksize,size(idx,2));
blockindcs = zeros(1,blksize,size(idx,2));
statelock = 0;
yMax = movmax(y, blksize);
props = regionprops(yMax > 0, 'PixelIdxList'); % Requires the Image Processing Toolbox.
for i = 1:size(idx,2)
bit_position = idx(i);
% blockBits(:,:,i) = y(props(i).PixelIdxList);
% blockindcs(:,:,i) = props(i).PixelIdxList;
% start = max(1, bit_position-2)
% stop = start + 4
% blockBits(:,:,i) = y(start:1:stop)
% blockindcs(:,:,i) = (start:1:stop)
if (bit_position>blksize) && bit_position< (siz_y-blksize)
blockBits(:,:,i) = y(bit_position:1:bit_position+4);
blockindcs(:,:,i) = bit_position:1:bit_position+4;
end
if bit_position<=blksize
blockBits(:,:,i) = y(bit_position:1:bit_position+4);
blockindcs(:,:,i) = bit_position:1:bit_position+4;
end
if bit_position>= (siz_y-blksize)
% bit_position = 100,
% siz_y = 101
% offset = 3
% Fill blockindcs offset & substitute with 0's
% 97 98 99 100 101
% blockindcs = 100 101 99 98 97
% blockBits = 1 0 0 0 0
blockBits(:,:,i) = y(bit_position:1:siz_y); % fill offset with 0's
blockindcs(:,:,i) = (bit_position:1:siz_y);
end
end
All that stuff is irrelevant. You gave the definition at https://www.mathworks.com/matlabcentral/answers/626663-find-sorrunding-elements-and-element-from-a-array#comment_1087903
Though you did omit the definition for the case [0 1 x x x]
My apologies,
so what is the proposal for [0 1 x x x] & it's permutation ?
Trying to catch up, here.
What doesn't work from this approach?
% Create example input with true at 7,9,41,75
y = false(1,101);
y([7,9,41,75]) = true
y = 1x101 logical array
0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
% Pad 2 false values to the beginning and end
ypad = [false(1,2), y, false(1,2)];
% Find locations of True
I = find(ypad(:)')
I = 1×4
9 11 43 77
% Remove any values of I closer than 2-units
I([false,diff(I)<=2]) = []
I = 1×3
9 43 77
% Isolate each true-value +/-2 to the right/left
% and remove the effect of padding
A = find(ypad(:)) + (-4:0)
A = 4×5
5 6 7 8 9 7 8 9 10 11 39 40 41 42 43 73 74 75 76 77
B = ypad(A+2)
B = 4x5 logical array
0 0 1 0 1 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0
Thanks a lot Adam! Let me check the proposal and verify it.
Hi Adam,
If we see the B out put we have 4 rows and 5 column.
Each row is a polynomial with a size of 5 ( column). I consider it as block size ( so 4 blocks with polynomial size of 5)
What is not OK in the output B is , starting element is NOT 1 and this will lead to coefficient of the polynomial must be 1 error )
Note: Important point is , we have to keep the polynomial size same (so that I don't have to change the degree of polynomial ) and run the polynomial data having error bits.
So we have to re work the logic !
Thank you
Could you show what the two outputs should be for the input in my comment?
Please see the figure,
C - represent , no data & it has a dimension of 3x5 . We dont have to run a error polynomial coeff , so removing.I am looking this solution.
For indices location
A to A' is improvement
A to C' is final expectation
For logical values
B to B' is improvement
B to C' is final expectation
I'm still having trouble extracting the set of rules to follow to get the expected matrix. Maybe those rules are scattered about in this thread and I haven't seen them. For example, why would the first row of A' be [7 8 9 6 5]?
You have A_idx = [5 6 7 8 9] but expectation is A'_idx = [7 8 9 6 5]
You have A_idx = [0 0 1 0 1] but expectation is A'_bits = [1 0 1 0 0]
Rules:
  • The first / every row must start with error bit location followed by rest of bit. i.e. leading coefficeint of a the polynomial must be 1
  • Tail bits of a polynomial can be any 0/1 in a block size( we get in the array). Bitreversal is done for 5,6 to 6,5
  • Once a error bit is processed in a block , we don't need to processs the bit again. Block window should slide further in search of next index / error bit to make a polynomial of fixed size
  • Minimum polynomial size i.e. block of 5 is reasonable .
  • polynomial size should not change during the execution.
Thank you!
Thanks a lot adam for your efforts and help !

Sign in to comment.

 Accepted Answer

Try this:
fprintf('Beginning to run %s.m ...\n', mfilename);
y = [
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0, ...
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0, ...
0 0 0 0 0 0 0 0 0]
yMax = movmax(y, 5)
props = regionprops(yMax > 0, 'PixelIdxList') % Requires the Image Processing Toolbox.
for k = 1 : length(props)
fprintf('\nFor block #%d, indexes = ', k);
indexes{k} = props(k).PixelIdxList;
fprintf('%d ', indexes{k});
end
fprintf('\nDone running %s.m ...\n', mfilename);
You'll see:
For block #1, indexes = 5 6 7 8 9
For block #2, indexes = 39 40 41 42 43
For block #3, indexes = 73 74 75 76 77

11 Comments

==================================================================
Updated comment [Image Analyst]
Your code will NOT work in case first elemet is set to 1. The block size will be reduced to 3 instead of 5 and this does not fit anymore to a predefined block size ( as you took 5 in movmax fcn)
For block #1, indexes = 1 2 3 ==> Bug "doesn't fit in a block"
For block #2, indexes = 5 6 7 8 9
For block #3, indexes = 39 40 41 42 43
For block #4, indexes = 73 74 75 76 77
Done running .m ...
Probably You have to change properties of movmax fcn
==================================================================
Looks good! Since I don't have a image processing toolbox to work on. Could you please help in imroving the below code?
siz_y = size(y,2);
[Val,idx] = find(y>0);
blockBits = zeros(1,5,size(idx,2));
blockindcs = zeros(1,5,size(idx,2));
for i = 1:size(idx,2)
a = idx(i);
if a>1 && a< siz_y
blockBits(:,:,i) = y(a-2:1:a+2);
blockindcs(:,:,i) = a-2:1:a+2;
elseif a==1
blockBits(:,:,i) = y(a:1:a+4);
blockindcs(:,:,i) = (a:1:a+4);
elseif a== siz_y
blockBits(:,:,i) = y(a-4:1:a);
blockindcs(:,:,i) = (a-4:1:a);
end
end
Are you sure? It's got to be the most common toolbox out there. I know it is here in Answers. Type ver on the command line to check.
If not, use find() to get the indexes of the 1's, and then use findgroups() to identify the separate blocks of them.
Thanks- can you please correct the error as I shared below
The code will NOT work in case first elemet is set to 1.
The block size will be reduced to 3 instead of 5 and this does not fit anymore to a predefined block size ( as you took 5 in movmax fcn)
For block #1, indexes = 1 2 3 ==> Bug "doesn't fit in a block"
For block #2, indexes = 5 6 7 8 9
For block #3, indexes = 39 40 41 42 43
For block #4, indexes = 73 74 75 76 77
So did you end up using my code? Or did you change it to use findgroups()? If so, attach that code.
If you're able to use the Image Processing Toolbox, you can use bwareaopen() to get rid of regions less than 5 in length:
fprintf('Beginning to run %s.m ...\n', mfilename);
y = [
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0, ...
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0, ...
0 0 0 0 0 0 0 0 0]
yMax = movmax(y, 5) > 0; % A logical vector.
yMax = bwareaopen(yMax, 5); % Keep runs of 5 or longer ONLY.
props = regionprops(yMax, 'PixelIdxList') % Requires the Image Processing Toolbox.
for k = 1 : length(props)
fprintf('\nFor block #%d, indexes = ', k);
blockIndexes{k} = props(k).PixelIdxList;
fprintf('%d ', blockIndexes{k});
end
fprintf('\nDone running %s.m ...\n', mfilename);
You'll see
For block #1, indexes = 5 6 7 8 9
For block #2, indexes = 39 40 41 42 43
For block #3, indexes = 73 74 75 76 77
Looks pretty good, But still improvement is required. Following Issues are observed & listed below
For block #1, indexes = 5 6 7 8 9
For block #2, indexes = 39 40 41 42 43
For block #3, indexes = 73 74 75 76 77
Issue -1:
Starting index is expected to be error bit i.e.I am expecting like below
For block #1, indexes = 7 8 9 6 5
For block #2, indexes = 41 42 43 40 39
For block #3, indexes = 75 76 77 74 73
Issue -2:
There is also a case where we have higher than block size is achieved. This mean higher polynomial order. This will NOT fit into pre-allocated buffer
[For block #1, indexes = 1 2 3 4 5 6 7 8 9 ]
Issue -3:
In case , if I modify y = errors positions(set to 1), I don't get the required output, For example, You can give a try by setting 1 and 101 locations ,
For block #1, indexes = 5 6 7 8 9
For block #2, indexes = 39 40 41 42 43
For block #3, indexes = 73 74 75 76 77
Done running .m ...
>> find(y>0)
ans =
1 7 41 75 101
Also please keep "bwareaopen" function c code translation, coder support is needed for c/c++ code generation, otherwise it is pretty difficult to implement on a 32 bit processor.
Thank you!
What is the case where you had indexes 1-9? What do you expect to happen if you have 1's that are closer than 5 elements? Is the solution to just add 2 to all the indexes? Area you saying that bwareaopen() is a function that is explicitly not included in the MATLAB Coder Toolbox?
  • What is the case where you had indexes 1-9?
In case - data altered for testing & verification
y = [
0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0, ...
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0, ...
0 0 0 0 0 0 0 0 1]
props =
3×1 struct array with fields:
PixelIdxList
For block #1, indexes = 1 2 3 4 5 6 7 8 9
  • What do you expect to happen if you have 1's that are closer than 5 elements?
It's OK and they may be , after all 1 are the error bits. The expectation is , we should have constant block size and we don't need to process the already processed error bit in a block . Block must start with a error bit ( leading coefficient of a the polynomial must be 1). And block size should not change. In case block does
not accomadete all error bit, then process the error bit in next block . We should not repeat the already processed error bit.
  • Is the solution to just add 2 to all the indexes?
No. If I understood your question correctly , you say adding/pad 2 additional bits. then my answer is you can do but finally we are not altering the output
  • Area you saying that bwareaopen() is a function that is explicitly not included in the MATLAB Coder Toolbox?
No. I am saying bwareaopen(), I have to write the c code that might be difficult for me if i don't understand the details of bwareaopen()
You said "Also please keep "bwareaopen" function c code translation, coder support is needed for c/c++ code generation, otherwise it is pretty difficult to implement on a 32 bit processor." so I was assuming that you needed the whole program to be converted to C code with the Coder Toolbox because you were going to embed this algorithm in a custom chip on some device. If you don't need Coder support and are not going to generate C code, then I don't know why you said that. Please elaboarate. Also, I don't know that Coder can generate code for 32 bit processors. I know MATLAB stopped supporting 32 bit processors with version 2016b.
If you want
For block #1, indexes = 7 8 9 6 5
For block #2, indexes = 41 42 43 40 39
For block #3, indexes = 75 76 77 74 73
then you can just tack on the first two indexes to the end, like this:
fprintf('Beginning to run %s.m ...\n', mfilename);
y = [
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0, ...
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0, ...
0 0 0 0 0 0 0 0 0]
windowWidth = 5;
halfWindowWidth = floor(windowWidth/2);
yMax = movmax(y, windowWidth) > 0; % A logical vector.
yMax = bwareaopen(yMax, windowWidth); % Keep runs of 5 or longer ONLY.
props = regionprops(yMax, 'PixelIdxList') % Requires the Image Processing Toolbox.
for k = 1 : length(props)
fprintf('\nFor block #%d, indexes = ', k);
theseIndexes = props(k).PixelIdxList';
blockIndexes{k} = [theseIndexes(end-halfWindowWidth : end), fliplr(theseIndexes(1:halfWindowWidth))];
fprintf('%d ', blockIndexes{k});
end
fprintf('\nDone running %s.m ...\n', mfilename);
It prints out:
For block #1, indexes = 7 8 9 6 5
For block #2, indexes = 41 42 43 40 39
For block #3, indexes = 75 76 77 74 73
Thank you! I'II update further with my comments on your queries with additional information. For the time being this is sufficient

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!