MATLAB Answers

if statement/numel (A)

9 views (last 30 days)
Sara Ismail-Sutton
Sara Ismail-Sutton on 24 Nov 2020
Edited: Jan on 7 Dec 2020
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

  2 Comments

Stephen Cobeldick
Stephen Cobeldick on 24 Nov 2020
"Since 1:numel(A) is positive integers, starting at 1, I don't understand where this is coming from"
The error message shows you exactly which line it is coming from. When i is one, what is i-1 ? Is that value a valid index?:
A(i-a)
Sara Ismail-Sutton
Sara Ismail-Sutton on 24 Nov 2020
obviously not, I meant why the if statement was not filtering out the trash, obviously , as pointed out by the guy below who explained it well...thanks...

Sign in to comment.

Answers (1)

Jan
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.

  14 Comments

Jan
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.
Sara Ismail-Sutton
Sara Ismail-Sutton on 5 Dec 2020
okay , many thanks for your response, okay thanks that helps re. C1,
no I do not want it to keep its previous value, so Ihave added else statements, but this
doesn't help, and I am still stuck. thanks
function[output]=blur(A,w)
[row,col]=size(A);
%function: img is a 2-d matrix values between 0 and 255
%average every pixel with vlaues 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
for i=1:numel(A)
%consider some element in a 'middle' row/column, start within this column
for a=0:w
if(1 <= (i - a) && (i - a) <= numel(A))&& (1 <= (i + a) && (i + a) <= numel(A))
C1=sum(A(i+a)+A(i-a));
else C1=0;
end
%go to columns to the right
t=i+a*col;
if(1 <= (t - a) && (t - a) <= numel(A))&& (1 <= (t + a) && (t + a) <= numel(A))&&(1<=(t)&&(t)<=numel(A))
C2(t)=sum(A(t+a)+A(t-a));
else C2=0;
end
%and columns to the left
s=i-a*col;
if((1 <= (s - a) && (s - a) <= numel(A))&& (1 <= (s + a) && (s + a) <= numel(A))&&(1<=(s)&&(s)<=numel(A)))
C3(s)=sum(A(s+a)+A(s-a));
else C3=0;
end
%in column j + a (incldue and focused on the same eleemnt, the same)
C(i)= ((C1(i)+C2(t)+C3(s))\(2*w+1)^2);
end
end
A(i)=C(i);
output=A(i)
end
Jan
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?

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!