How do I fix my array indices? Error says must be positive or logical values.

Error:
Array indices must be positive integers or logical values.
Error in lefthalfdonutcode (line 155)
profileSums(thisDistance) = profileSums(thisDistance) + double(grayImage(row, column));
I am very beginner to matlab and I am trying to get my attached script to work.
My code is attempting to count the number of dots (using a left half donut shaped mask) over 12 (or 9 the number is arbitrary) consecutive locations evenly distributed across the image and plot the count of the content as a function of the location.
My issues are the integer values are either not logical, or not positive and my code doesn't like that. Everytime I think I fix it, some other related error pops up. I thought the issue was the mask, then the maxDistance but now i am unsure. What would you suggest to get it working? Thank you.
I'm not an artist but i have attached a drawing of what I am trying to accomplish..
I want to make 12 equal bins that segment across the image in a radial mask shape to count the (in this image) purple dots then plot them as a function of their bin locations in a graph. The count would be normalized to the bin area so that the counts in the different bins can be comparable. once I get the code working to do that i think I can finish it up but i have been stuck for weeks on this part and would appreciate help because to me it is not trivial!! Thanks. -N.

 Akzeptierte Antwort

Weitere Antworten (3)

Image Analyst
Image Analyst am 28 Feb. 2023
I gave you a program for when the zones were 12 vertical rectangles in your other post. Why do you need annular zones now? I see nothing in the image you posted that would indicate annular zones were what you should use.
And, like I said before, when you post stuff like this you need to post the original image and not just the annotated/marked-up one.
If you do want annular zones, you'd need to specify the center of the circles so the zones can be properly computed.

7 Kommentare

Neo
Neo am 28 Feb. 2023
Verschoben: Voss am 28 Feb. 2023
@Image Analyst it is SO good to hear from you. As I have mentioned, I admire you a lot (I've learned so much from giants like you and Walter). So it is really nice to hear from you. I have attached my original image. and how I want to define the center of my circle. Please let me know if there is anything else that I can be more clear in. Using annular segments can be important for some of my images like the one I attached (exampleimagecorrect.zip) so I would like to know how to perform the exact segmentation as in your rectangular program but with annular segments like the other attached image (exampleimage.zip).
To specify the center of the circles I have tried a few diff approaches: One approach is to manually select the center point using a mouse or touchpad in the image viewer. Another approach is to use image processing algorithms to automatically detect the center point based on specific features of the image, such as intensity or color.
Here is an example code I made to create a circle centered at the point (2,3) with a radius of 5:
x = 2; % x-coordinate of the center
y = 3; % y-coordinate of the center
r = 5; % radius of the circle
theta = linspace(0, 2*pi, 100); % create an array of angles
xc = x + r*cos(theta); % x-coordinates of the circle points
yc = y + r*sin(theta); % y-coordinates of the circle points
plot(xc, yc, 'o'); % plot the circle
But when applied to my code for annular segmentation it doesn't work like the rectangular strips!! Ahhh! can you provide an example on how I can get this to work properly? Thanks!!
The example you gave had the center of the image off the right side of the image by quite a large distance.
You can use code like you have but you need to exclude points that are outside of the image, like
outsideImage = (xc < 1) | (xc > columns) | (yc < 1) | (yc > rows);
xc(outsideImage) = [];
yc(outsideImage) = [];
where rows and columns is the size of your image.
Neo
Neo am 28 Feb. 2023
Bearbeitet: Neo am 28 Feb. 2023
here is an updated version but it is still not working as intended. Can you make the changes to the script and reattach to ensure that i am understanding your example? @Image Analyst
The error:
Error using zeros
Size inputs must be integers.
Error in lefthalfdonutcode (line 154)
profileSums = zeros(1, maxDistance);
Here is a flow chart of what i am trying to make my code perform:
+-----------------+
| Original Image |
+--------+--------+
|
|
+--------v--------+
| Subtract |
| Background |
+--------+--------+
|
|
+--------v--------+
| Gaussian Filter |
+--------+--------+
|
|
+--------v--------+
| Threshold |
+--------+--------+
|
|
+--------v--------+
| Binarization |
+--------+--------+
|
|
+--------v--------+
| Masking |
+--------+--------+
|
|
+--------v--------+
| Count Spots |
| 12 Segments |
+--------+--------+
|
|
+--------v--------+
| Normalize to |
| Area of Bin |
+--------+--------+
|
|
+--------v--------+
| Plotting |
+--------+--------+
I attached a skeleton script (its not completly functional but hopefully it explains the path I am trying to follow clearly). The only thing besides it actually working is to input the user specified coordinates like in your radial profile program. Can you show me how you would get it functional? @Image Analyst
I made my code to produce angular masks but the masks is still not shaped like the way I want in the image I attached. Can you fix it to be shaped like a left half donut masks as I'm trying to do? Here is my updated code, I tried really hard and I just need a little push to get it across the finish line but I am almost there!

Melden Sie sich an, um zu kommentieren.

You need to submit more of your code before anybody can comment on what went wrong.
However a variable termed ThisDistance sounds to me as potentially non-integer. Using either floor, round or ceil could possibly be a solution. See help for floor, ceil and round to select the bes for your purpose

2 Kommentare

@Morten Sparre Andersen Sorry, what do you mean by more of my code? I only have the script I attached which is my full code. I also looked into the non-integer problem and came up with this:
% Scan the original image getting gray level, and scan edtImage getting distance.
% Then add those values to the profile.
for column = 1 : columns
for row = 1 : rows
thisDistance = round(sqrt((row-y)^2 + (column-x)^2));
if thisDistance <= 0 || thisDistance > maxDistance % Add a check to ensure that thisDistance is positive and within range
continue;
end
profileSums(thisDistance) = profileSums(thisDistance) + double(grayImage(row, column));
profileCounts(thisDistance) = profileCounts(thisDistance) + 1;
end
end
Even once i add it does not run all the way and the mask doesn't iterate through the image as I illustrated in the picutre. What do you suggest? Can you try to get it to wrok as intended and show me what you changed? Thanks.
Sorry! I didn't look for the code you included.
It is late in my part of the world. I may take a look on your code tomorrow.

Melden Sie sich an, um zu kommentieren.

thisDistance = round(sqrt((row-y)^2 + (column-x)^2));
Your x and y are 300 x 300 arrays, so (row-y) returns an array and then (row-y)^2 is matrix power -- (row-power) matrix multiplied by (row-power) . Which is permitted because it happens to be a square matrix, but probably you would want .^ instead.
The result in thisDistance would be an 2d array of distances
if thisDistance <= 0
continue;
end
so you are checking whether the 2D array of distances is <= 0 . If x and y contain only real values, then sqrt((row-y)^2 + (column-x)^2) would be non-negative -- possibly 0 but never negative -- so <= 0 would effectively be testing for == 0 (since < 0 cannot occur for reals in this situation.) Well, at least not once you repair the ^2 to be .^2 .
When you if a non-scalar, the test is considered true only if all of the values being tested are non-zero. So in order for the test to be considered true, all of the values in thisDistance would have to be non-positive, and if there is even a single positive distance then the test would be false and you would not continue
profileSums(thisDistance) = profileSums(thisDistance) + double(grayImage(row, column));
and there you are using the 2D array as indices -- but because of the mistake in the if test, you failed to reject the case where at least one value was 0 but not all of the values were 0. So you potentially have 0 as a subscript, which is not permitted.
Be further warned: the values in thisDistance will have numerous duplicates. So there will, for example, probably be about 12 places that are distance 2 away, so your code is like (for example) profileSums([3 2 2 2 3; 2 1 1 1 2]) = profileSums([3 2 2 2 3; 2 1 1 1 2]) + double(grayImage(row,column)) . This is at the very least going to cause you confusion. Should the value be added to index 2 once for each different place the distance was computed as 2? Or should the value be added to index 2 once on if at least one place computed the distance as 2? If the answer is "once for each time" then you are calculating that incorrectly. If you want "once only" then you should unique(thisDistance) to find the indices that should be incremented.

8 Kommentare

So what would be the correction? I tried what you suggested and the code is not working as I intended which is to "to count the number of dots (with a left half donut shaped mask) over 9 consecutive
% locations evenly distributed across the image and plot the count as a function of the location.'"
It helps if i can see how you get it to work and fix my mistake that way (beginner problems). I am a wet sponge. Thanks.
@Neo Your code is very confusing. You're trying to do it two different ways at the same time. I suggest you make a flow chart and pick one of the ways. You need to make up your defining radii
% Get the radial distance to the edges of each zone.
numZones = 12;
zoneRadii = linspace(0, maxDistance, numZones + 1)
and then decide if you want to make 12 annular zone masks and then process the whole zone at once, like
profile(zoneNumber) = nnz(maskImage(zoneMask));
Or if you want to scan the image pixel by pixel determining what zone that pixel belongs to and incrementing the count for that zone.
profile(zoneNumber) = profile(zoneNumber) + 1;
Counting the number of dots does not involve adding the content of the image
double(grayImage(row, column))
If you have an array of distances thisDistance and want to count each of the distances, then
counts_by_distance = accumarray(thisDistance(:)+1, 1);
When I put your line in the code it doesn't work it might work if you put it in then attach it so I can see it next to mine. I made the flow chart in my above comment but basically its like your radial profile program but with 12 equal bins and for multiple images at once. Oh and it would count the number of spots in the image not the average gray level.
When I put the referenced line of code to make it work it doesn't work as expected maybe you can include it in the script then reattach it so I can compare it?
Of course those lines alone won't work. You have to have a whole program. Those snippets are just the "meat" of the program. I gave you two options for program flows. One to create 12 masks, and one to scan pixel by pixel. Both methods will work. Which way do you want to do it?
Neo
Neo am 1 Mär. 2023
Bearbeitet: Neo am 1 Mär. 2023
The way where you create 12 angular masks.
Where in my code do I start to go two different ways? I’m going to have a good look tomorrow and see if I can fix it based on your feedback so far but if you can give me how you would fix it to check against afterwards would be awesome, thanks

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Display Image finden Sie in Hilfe-Center und File Exchange

Gefragt:

Neo
am 27 Feb. 2023

Beantwortet:

Neo
am 3 Mär. 2023

Community Treasure Hunt

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

Start Hunting!

Translated by