3

I have below a contiguous patch of cells plotted in Matlab. enter image description here

The outer cells of the red patch have to be determined and then a polygon joining the centers of these cells will give me a polygon. How do i compute the outer cells of the contiguous patch?

I have an array of integers whose elements denote the cell in the red patch, for example,

a=[1;64;23;456;345];

Each element , say 64 corresponds to a cell in the image, and it is the cell belonging to the red patch.

The motivation to solve the problem is to deal with a polygon with minimal number of edges rather than so many cells. it slows down computation. Convex hull is not good enough. I don't want the resulting polygon to overlap with the brown area at all.

What i am suggesting is the case on the left in image below but it seems ugly. So a better way would be as in right to just skip the cells only sharing a single point with the outer brown area. I would like my outer cells to then be only those that share more than just a single point with the outer brown area.

But we want to avoid large number of edges in the resultant polygon!

enter image description here

user_1_1_1
  • 903
  • 1
  • 12
  • 27
  • 1
    similar to this [Outline circumference polygon extraction from geometry constructed from equal squares](http://stackoverflow.com/a/33473452/2521214) and [Determine Minimum Number of Line Segments to Solve a Maze](http://stackoverflow.com/a/30908390/2521214) – Spektre Feb 02 '17 at 11:17
  • thanks, very helpful! – user_1_1_1 Feb 02 '17 at 18:24

3 Answers3

2

I first processed the sample image from your question to create a logical mask (you already have an example of how to do that here).

Once you have this mask, there is a really easy way to generate the polygon you want using the bwtraceboundary function from the Image Processing Toolbox. This will give you a set of pixel indices in order around the perimeter of your masked region:

[r, c] = find(mask, 1);
coords = bwtraceboundary(mask, [r c], 'N');

And we can visualize it like so:

imagesc(mask);
colormap([0.9 0.9 0.9; 0.6 0.6 0.6]);
axis equal
set(gca, 'XLim', [0.5 0.5+size(mask, 2)], 'YLim', [0.5 0.5+size(mask, 1)]);
hold on;
plot(coords(:, 2), coords(:, 1), 'r', 'LineWidth', 2);
plot(coords(1, 2), coords(1, 1), 'go', 'LineWidth', 2);

enter image description here

The coordinates for the red line are ordered starting from the green circle and moving clockwise around the perimeter pixels of the masked region.

If you would prefer to generate a boundary outline that follows along the perimeter pixel edges of the region instead of the perimeter pixel centers, you can use the solution from my answer to a related question. This will yield the following:

enter image description here

gnovice
  • 125,304
  • 15
  • 256
  • 359
1

Using Image Processing toolbox You can apply dilation on the image and than apply and operator between result of dilation and the original image.

enter image description hereenter image description here

A = imread('bnhfm.png');
B = A & imdilate(~A, true(3));
imshow(B);
imwrite(B, 'result.png');
rahnema1
  • 15,264
  • 3
  • 15
  • 27
  • Very cool trick! How did you convert the red-brown image to black and white? Can it be done thru matlab programatically? – user_1_1_1 Jun 05 '17 at 21:43
  • @user_1_1_1 I used an image editing software to do it, However I believe it can be done thru matlab with some effort . It my be subject to a new question. – rahnema1 Jun 06 '17 at 01:05
1

Although the answer by @rahnema1 is really cool, I think the OP is asking more how to extract the set of edges according to the described rules.

Here is my approach identifying all the 10 patterns of 2x2 pixels that contain edges. Assuming the matrix A has the image with 1s and 0s (A = zeros(ny, nx); A(a) = 1):

% we identify patterns with edges over 2x2 patches, describing with
% the first 4 binary values what pixels are set, and with the next 2
% the edge with 2 indices over the 2x2 patch
patterns = [
 0,1,0,1,  3,4 % vertical edge at rhe right 
 1,0,1,0,  1,2 % vertical edge at the left
 0,0,1,1,  2,4 % horizontal edge at the bottom
 1,1,0,0,  1,3 % horizontal edge at the top
 1,0,0,1,  1,4 % diagonal edge
 0,1,1,0,  2,3 % diagonal edge
 1,0,1,1,  1,4 % diagonal edge, extra pixel set
 1,1,0,1,  1,4 % diagonal edge, extra pixel set
 1,1,1,0,  2,3 % diagonal edge, extra pixel set
 0,1,1,1,  2,3 % diagonal edge, extra pixel set
];

% 2x2 patches (matrix form)
P00 = A(1:end-1,1:end-1);
P10 = A(2:end,1:end-1);
P01 = A(1:end-1,2:end);
P11 = A(2:end,2:end);

% edge unique identifier using powers of 2
id = @(p00,p01,p10,p11) 1*p00 + 2*p10 + 4*p01 + 8*p11;
P = id(P00,P01,P10,P11); % vectorized pattern identification

% edges
e0 = []; % from (i,j)
e1 = []; % to (i,j)
for i = 1:size(patterns, 1) % small loop over the 10 patterns
  p = patterns(i, :);
  E = (P == id(p(1),p(2),p(3),p(4))); % pattern search, vectorized
  [c,r] = ind2sub(size(E), find(E));
  [c0,r0] = ind2sub([2,2], p(5));
  [c1,r1] = ind2sub([2,2], p(6));
  e0 = [e0; c+c0, r+r0];
  e1 = [e1; c+c1, r+r1];
end

And here the result applying it to your image (I used GIMP for capture, resize and filter, so maybe the image is not exactly the same):

X = [e0(:,2) e1(:,2)];
Y = size(A,1) - [e0(:,1) e1(:,1)];
plot(X', Y', '.-')

Resulting set of edges

I am assuming that obtaining an ordered sequence of edges describing the polygon (or polygons) is not the main problem here once you have the aforementioned set.

Iban Cereijo
  • 1,675
  • 1
  • 15
  • 28
  • This is the solution i was looking for. But i was wondering how to obtain a nx2 matrix storing the vertices of the polygon in clockwise or counterclockwise manner starting from any vertex? – user_1_1_1 Jun 05 '17 at 22:27
  • I tired:- `X=X'; Y=Y'; new_poly=[X(1,:)',Y(1,:)'];line(new_poly(:,1), new_poly(:,2));` This did not work. – user_1_1_1 Jun 05 '17 at 22:30
  • What is the name of this method you used involving 2x2 patches and powers of 2? Could you point me to some source to understand this in more detail? – user_1_1_1 Oct 25 '17 at 22:50
  • I guess this is an example of a "marching squares" algorithm. – Iban Cereijo Oct 26 '17 at 20:49