Reputation: 437
i need to find all the black neighbors of a pixel; for that i tried the following ;but the output is not correct.Cropped input image is labeled image(i put color to this label) i want to add the black region of the input image (region around ellipse like structure) and change the white region around ellipse in the labeled image as blue(need to change the label of surrounding white region as 1)
clc
clear all;close all
img=[0 255 0 0 0;
0 1 1 255 0;
255 0 0 255 0;];
[m n]=size(img)
img= padarray(img, [2 2], 0)
fi_neighbors=zeros(1,8);
for i=1:m
for j=1:n
for r=3:m
for c=3:n
neighbors(1) = img(r-1,c-1); % Upper left.
neighbors(2) = img(r-1,c); % Upper middle.
neighbors(3) = img(r-1,c+1); % Upper right.
neighbors(4) = img(r,c-1); % left.
neighbors(5) = img(r,c+1); % right.
neighbors(6) = img(r+1,c+1); % Lowerleft.
neighbors(7) = img(r+1,c); % lower middle.
neighbors(8) = img(r+1,c-1); % Lower left.
end
end
fi_neighbors=[neighbors;fi_neighbors]
end
end
Upvotes: 0
Views: 619
Reputation: 16791
There are several errors in your code, so I'll try to take them one by one. Here is your original code, reformatted a bit:
img = [0 0 0 0 0;
0 1 1 0 0;
0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [2 2], 0)
fi_neighbors = zeros(1,8);
for i = 1:m
for j = 1:n
for r = 3:m
for c = 3:n
neighbors(1) = img(r-1,c-1); % Upper left.
neighbors(2) = img(r-1,c); % Upper middle.
neighbors(3) = img(r-1,c+1); % Upper right.
neighbors(4) = img(r,c-1); % left.
neighbors(5) = img(r,c+1); % right.
neighbors(6) = img(r+1,c+1); % Lower right. <-- corrected
neighbors(7) = img(r+1,c); % lower middle.
neighbors(8) = img(r+1,c-1); % Lower left.
end
end
fi_neighbors = [neighbors;fi_neighbors]
end
end
The first error is that the loop variables i
and j
are never used. Therefore they are useless (except for making us perform the same calculations m x n
times). Let's take those out.
img = [0 0 0 0 0;
0 1 1 0 0;
0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [2 2], 0)
fi_neighbors = zeros(1,8);
for r = 3:m
for c = 3:n
neighbors(1) = img(r-1,c-1); % Upper left.
neighbors(2) = img(r-1,c); % Upper middle.
neighbors(3) = img(r-1,c+1); % Upper right.
neighbors(4) = img(r,c-1); % left.
neighbors(5) = img(r,c+1); % right.
neighbors(6) = img(r+1,c+1); % Lower right.
neighbors(7) = img(r+1,c); % lower middle.
neighbors(8) = img(r+1,c-1); % Lower left.
end
end
fi_neighbors = [neighbors;fi_neighbors]
With those loops out of the way, we can see that you're only updating the fi_neighbors
array once after you've done all of the calculations. That's why you got the same result m x n
times before. We need to move that inside the loop where the result is updated after each set of calculations (I've left out the setup this time and only listed the loops):
for r = 3:m
for c = 3:n
neighbors(1) = img(r-1,c-1); % Upper left.
neighbors(2) = img(r-1,c); % Upper middle.
neighbors(3) = img(r-1,c+1); % Upper right.
neighbors(4) = img(r,c-1); % left.
neighbors(5) = img(r,c+1); % right.
neighbors(6) = img(r+1,c+1); % Lower right.
neighbors(7) = img(r+1,c); % lower middle.
neighbors(8) = img(r+1,c-1); % Lower left.
fi_neighbors = [neighbors;fi_neighbors] %// moved inside loops
end
end
Next up are the ranges for our loops. You padded the array with 2 zeros on each side, so you start with row/column 3
. That's good, but you still end the loops at m
and n
. That means you process (m-2) x (n-2)
pixels. You need to extend the range. But actually, you've padded more than you need. A padding of one pixel on each side would be sufficient, so let's do both at once, change the padding and correct the ranges:
img = [0 0 0 0 0;
0 1 1 0 0;
0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [1 1], 0)
fi_neighbors = zeros(1,8);
for r = 2:m+1
for c = 2:n+1
neighbors(1) = img(r-1,c-1); % Upper left.
neighbors(2) = img(r-1,c); % Upper middle.
neighbors(3) = img(r-1,c+1); % Upper right.
neighbors(4) = img(r,c-1); % left.
neighbors(5) = img(r,c+1); % right.
neighbors(6) = img(r+1,c+1); % Lower right.
neighbors(7) = img(r+1,c); % lower middle.
neighbors(8) = img(r+1,c-1); % Lower left.
fi_neighbors = [neighbors;fi_neighbors]
end
end
Now you should have a working program that gives you the correct output:
fi_neighbors =
0 0 0 0 0 0 0 0 <-- img(m,n) neighbors
1 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0
0 1 1 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 1 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 1
0 0 0 0 0 0 1 1
0 0 0 0 0 1 1 0
0 0 0 0 0 1 0 0 <-- img(1,1) neighbors
0 0 0 0 0 0 0 0
This works, but have a look at the notes that I added to the output. The first row of the result contains the neighbors for the pixel img(m,n)
: the last pixel in the image. The next-to-last row contains the neighbors for img(1,1)
, and the last row is just hanging there as a result of your initialization to zeros(1,8)
. All of that seems unnatural to me, so I'm going to flip the result array so that img(1,1)
is the first row. Also, growing an array over each loop iteration is slow. We want to preallocate the array and then put the data in the proper place.
Since we're referencing pixels in the original image, but calculating on a padded image, it's much easier to add a counter variable than to do all of the row/column index calculations, so I've added pix
as a counter:
img = [0 0 0 0 0;
0 1 1 0 0;
0 0 0 0 0;];
[m n] = size(img);
img = padarray(img, [1 1], 0)
fi_neighbors = zeros(m*n,8); % preallocate result array
pix = 0; % pixel counter
for r = 2:m+1
for c = 2:n+1
pix = pix + 1; % find neighbors for next pixel
neighbors(1) = img(r-1,c-1); % Upper left.
neighbors(2) = img(r-1,c); % Upper middle.
neighbors(3) = img(r-1,c+1); % Upper right.
neighbors(4) = img(r,c-1); % left.
neighbors(5) = img(r,c+1); % right.
neighbors(6) = img(r+1,c+1); % Lower right.
neighbors(7) = img(r+1,c); % lower middle.
neighbors(8) = img(r+1,c-1); % Lower left.
fi_neighbors(pix,:) = neighbors; % update the correct row
end
end
Result:
fi_neighbors =
0 0 0 0 0 1 0 0
0 0 0 0 0 1 1 0
0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 1 1 0 0 0 0 0
1 1 0 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Now, the neighbors of img(1,1)
are in row 1 and the neighbors of img(m,n)
are in row m*n.
Finally, there are a couple of quick optimizations you can make. Both of them require changes in the ordering of the result. If you're willing to have the pixels and neighbors presented in a different order, which I'll try to show clearly, then we can first change the ordering of the loops to take advantage of MATLAB's column-major ordering.
Instead of:
for r = 2:m+1
for c = 2:n+1
...
end
end
we'll use:
for c = 2:n+1 % be sure to swap m and n as well!
for r = 2:m+1
...
end
end
For large matrices, this should help with keeping the current columns we're working with in the cache. This will change the ordering of the pixels so that instead of the second pixel being img(1,2)
, it will now be img(2,1)
, then img(3,1)
, down to img(m,1)
, then img(1,2)
.
The second change condenses all of your neighbor calculations into 2 lines (maybe 3), but it changes the ordering as I'll show below:
pix = 0; % pixel counter
for c = 2:n+1
for r = 2:m+1
pix = pix + 1; % find neighbors for next pixel
neighbors = img(r-1:r+1,c-1:c+1);
neighbors = neighbors(:).';
fi_neighbors(pix,:) = neighbors; % update the correct row
end
end
This takes the submatrix of img
around the current pixel, then uses colon notation to turn it into a column vector and finally transposes it into a row vector. Here are the resulting neighbor locations within neighbors
:
neighbors(1) % Upper left.
neighbors(2) % left.
neighbors(3) % Lower left.
neighbors(4) % Upper middle.
neighbors(5) % *** current pixel ***
neighbors(6) % Lower middle.
neighbors(7) % Upper right.
neighbors(8) % right.
neighbors(9) % Lower right.
But now we have 9 elements in neighbors
including the current pixel! If you really don't want the current pixel listed, we can fix that, but either way we need to change the size of fi_neighbors
to (m*n,9)
. We can then remove column 5 from the result at the end, if desired.
Here's the final code:
img = [0 0 0 0 0;
0 1 1 0 0;
0 0 0 0 0;];
[m n] = size(img);
img = padarray(img, [1 1], 0);
fi_neighbors = zeros(m*n,9); % preallocate result array
pix = 0; % pixel counter
for c = 2:n+1
for r = 2:m+1
pix = pix + 1; % find neighbors for next pixel
neighbors = img(r-1:r+1,c-1:c+1);
neighbors = neighbors(:).';
fi_neighbors(pix,:) = neighbors; % update the correct row
end
end
fi_neighbors(:,5) = []; % OPTIONAL - remove current pixel from each row
Obviously, there's more you could do, but this should be a very good start.
Upvotes: 2