if statement/numel (A)

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

"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)
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

Sara Ismail-Sutton
Sara Ismail-Sutton on 24 Nov 2020
Edited: Jan on 24 Nov 2020
apologies I am still stuck, your solution has worked on the problem stated on the original post, but now I want to consider elements in a differnet column of the matrix, and I've done this via, 't' in the code bwelow, and then I wanted a similar if statement, so also added the same condition for 't' alone, but it is producing the error message again:
"Array indices must be positive integers or logical values"
Many thanks in advance !
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))
end
Jan
Jan on 24 Nov 2020
Use the debugger and find out, which index is concerned.
right okay thanks, it has returned
i =0.4167 , but I have no idea where it is geting this from since I thought 1:numel(A) is just positive integers- this is why I said this in my op so someone could correct me if I was wrong on this ...?
Jan
Jan on 24 Nov 2020
We need to see the complete code. If i is set to0.41 this happend in a line, which has not been posted here.
it should just be the op combined with the t variable code stuff as in the first comment here, but here it is...
function[output]=blur(A,w)
[row,col]=size(A)
for i=1:numel(A)
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))
end
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))
end
C(i)= ((C1(i)+C2(t))\(2*w+1)^2)
i=C(i)
end
end
end
says error occuring in line 27... Error in blurri (line 27)
C2(t)=sum(A(t+a)+A(t-a))
Please format your code to make it readable. Do you see the numerous empty lines and the strange indentation? Delete the blank lines, select the text by ctrl-a and press ctrl-i for an auto-indentation.
Please post the complete error message.
The problem is caused be the line:
i=C(i)
This replaces the integer value of i.
okay many thanks, yes that was a silly error I should have spotted, it was meant to be A(i)=C(i)
Still getting an error message, see screenshot attached- can see that s=-4 in the prior iteration, don't understand how the if statement still has not got rid of allowing this to happen. Many thanks
this is my code now, A(i)=C(i) is assigned outside the for loop as want to keep the original values in the loop.
function[output]=blur(A,w)
[row,col]=size(A);
for i=1:numel(A)
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))
end
%in another column
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))
end
%in another column j
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))
end
C(i)= ((C1(i)+C2(t)+C3(s))\(2*w+1)^2)
end
end
A(i)=C(i)
end
Jan
Jan on 26 Nov 2020
The code looks really confusing and a clean and clear description of the purpose is missing.
Note that if a condition for the indices is not matching, the C1, C2, C3 values of the previous iteration are used. Is this really what you want to do?
The name "blur" sounds like a filter operation. Then Matlab has powerful commands to achieve this.
i wouldnt worry too much about what the code is doing, or powerful commands, that's not gonna help me learn. it's helpful if i break it down into the mini chunks that i am stuck on though.
"Note that if a condition for the indices is not matching".. what do you mean by this?
Jan
Jan on 27 Nov 2020
Edited: 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.
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
Edited: Jan on 7 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.

Products

Release

R2020b

Asked:

on 24 Nov 2020

Edited:

Jan
on 7 Dec 2020

Community Treasure Hunt

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

Start Hunting!