9 views (last 30 days)

I am confused why the if statement below is not working, I am getting the error message "Array indices must be positive integers or logical values.". Since 1:numel(A) is positive integers, starting at 1, I don't understand where this is coming from, I thought this if statement would filter out to ensure only valid matrix elements are included.

"Error in blur (line 12)

b(i)=A(i-a)"

(for context this is part of code I need for a bigger function I am writing)

E.g tested with A=[ 10 12 7 3 12; 3 10 6 2 8; 18 24 17 6 10; 15 21 10 8 12; 1 18 22 4 15] and w=2.

Many thanks for your help !

function[output]=blur(A,w)

%[row,col]=size(A)

%

for i=1:numel(A)

for a=0:w

if (1<=(i + a)<=numel(A))&&(1<=(i - a)<=numel(A))

c(i)= A(i+a)

b(i)=A(i-a)

end

end

end

Jan
on 24 Nov 2020

Edited: Jan
on 24 Nov 2020

These condition does not do, what you expect:

1<=(i + a)<=numel(A)

1<=(i - a)<=numel(A)

They are evaluated from left to right: 1<=(i + a) replies true or false. Then this result is compare with numel(A). For this comparison true is converted to 1 and false to 0.

You want:

1 <= (i + a) && (i + a) <= numel(A)

1 <= (i - a) && (i - a) <= numel(A)

By the way, The debugger is the perfect tool to examine such problems. Type in the command window:

dbstop if error

an run the code again. Matlab stops, when the problem occurs and you can check the values of the variables directly.

Jan
on 27 Nov 2020

If the condition:

if (1 <= (i - a) && (i - a) <= numel(A))&& (1 <= (i + a) && (i + a) <= numel(A))

is not true in the first iteratom, C1 is not defined. If the condition does not match later on, C1 keeps its value from the previous iteration. While the first causes an error, the second is most likely not, what you want to achieve.

Therefore the shown code ist not running. I cannot reliably determine the purpose of a code, which does not run. Thefore it is not possible to fix or simplify your code. As soon, as the code contains some comments which define its purpose exactly, it is much easier to fix it. Most of all I think, that such a clean descriptuion helps you also to keep the overview.

It looks strange, that C(i) is overwritten in each iteration.

Jan
on 6 Dec 2020

Some hinter to your code:

C2(t)=sum(A(t+a)+A(t-a));

This is a sum over a scalar only, so you can omit the sum command. For a=0 the result is 2*A(t). But why do you cound the central element twice? Actually you want to create a submatrix to build the average. I cannot see how you code does anything in this direction.

With your approach the pixels on the right side of the matrix are avreaged using the values of the left side in the next row. You start with getting row and col, but you do not use their important information anywhere.

The loop "for a=0:w" is a complicated idea. Obviously it is too confusing. Imagine how you would do this is the real world: You have a matrix with data printed on paper, and a stencil with the window width as side length. Then you move the stencil over the paper and calculate the meain over the numbers inside it.

Using an approach, which can be imagined as physical procedure makes it much easier to implement it.

function B = blur(A, w)

% B = blur(A, w)

% A is a 2-d matrix values between 0 and 255

% average every pixel with values in the vicinity of every pixel

% output pixel value is the mean of the pixels in a square

% submatrix of size 2w+1 where given pixel sits in the center

% only use valid pixels when portions of the blurring matrix fall

% outside the image

[row, col] = size(A);

B = zeros(row, col); % Pre-allocate the output

for iRow = 1:row % Loop over rows

iniRow = max(1, iRow - w); % Window indices from top to bottom

finRow = min(iRow + w, row);

for iCol = 1:col % Loop over columns

iniCol = max(1, iCol - w); % Window indices from left to right

finCol = min(iCol + w, col);

AA = A(iniRow:finRow, iniCol:finCol); % Submatrix

B(iRow, iCol) = mean(AA(:)); % Average over all elements of AA

% Shorter in modern Matlab versions:

% B(iRow, iCol) = mean(A(iniRow:finRow, iniCol:finCol), 'all');

end

end

end

To check the result:

A = rand(5, 8);

k = 2;

B = blur(A, k);

C = movmean(movmean(A, 2 * k + 1, 1), 2 * k + 1, 2);

B-C % Just some rounding errors

Do you see, how a simplified approach increases the clarity of the code?

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

Start Hunting!
## 2 Comments

## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/660228-if-statement-numel-a#comment_1157958

⋮## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/660228-if-statement-numel-a#comment_1157958

## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/660228-if-statement-numel-a#comment_1158033

⋮## Direct link to this comment

https://in.mathworks.com/matlabcentral/answers/660228-if-statement-numel-a#comment_1158033

Sign in to comment.