Switch to unified view

a b/combinedDeepLearningActiveContour/functions/mask2poly.m
1
function poly=mask2poly(mask,countourType,sortPointsMethod)
2
%% function poly=mask2poly(mask)
3
% Finds a polygon enclosing the user defind mask of logicals. Kind of a
4
%  reverse/complementary of Matlab poly2mask function.
5
%
6
%% Syntax
7
% poly=mask2poly(mask);
8
% poly=mask2poly(mask,countourType);
9
% poly=mask2poly(mask,countourType,sortPointsMethod);
10
%
11
%% Description
12
% This functions goal is to find a poligon which enclosures a user supplied mask. It's a
13
%  kind of a complementary of Matlab poly2mask function. The difference is that all
14
%  contour points are returned- wihout missing points for linearly related points. In
15
%  order to get a 100% complementary of poly2mask all points inside straight lines shoud
16
%  be ommited. In my case I actually need all those points, as indexs of ROI. 
17
%  Combinng mask2poly with poly2mask the user can produce a mask from a contour (line with
18
%  X and Y coordinates), and vise-versa.
19
%
20
%% Input arguments:
21
% mask- two dimentional matrix of numbers (all numeric types are supported, though mask is
22
%  usally a matix of logicals).
23
%
24
% countourType- {['Inner'],'Outer','Exact'} a string describing the desired contour type.
25
%  'Inner' (default) will result in a contour inside the mask- the largest shape included
26
%     by the mask.
27
%  'Outer' will result in a contour ouside the mask- the smallest shape including by the
28
%     mask.
29
%  'Exact' option will result in a contour between 'Inner' and 'Outer', and it lies
30
%     exactly on the mask margins. 
31
% Both 'Outer' and 'Inner' results are integers, ready to be used for indexing.
32
% so it can be used for indexing, as oposed to 'Exact' results which are doubles, and
33
% cannot be used for indexing.
34
%
35
% sortPointsMethod- two methds are currently implemented:
36
%  'CW'- Clock Wise- an efficinet and fast, but can create "saw tooth" shaped contour.
37
%  'MINDIST'- minimal siatnce between points- will usally result in a better contour,
38
%     without "saw tooth" shaped contour. but the price to pay is ~X20 times slower run
39
%     time.
40
% other value of sortPointsMethod will skip sorting points.
41
%
42
%% Output arguments
43
% poly- Two dimentional [N,2] matirx with coordinates of all points of the contour. Each
44
%  point is described by an appropriate row. X is described by the first column, Y by the
45
%  second.
46
%
47
%% Issues & Comments (None)
48
%
49
%% Example
50
% x = [76    51    82    97   118   167   180   145   113    92  76];
51
% y = [41    73   115    80   143   173   120    57    40    33  41];
52
% mask = poly2mask(x,y,200,200);
53
% figure;
54
% imshow(mask);
55
% hold on;
56
% poly=mask2poly(mask,'Inner','CW');
57
% plot(poly(:,1),poly(:,2),'v-g','MarkerSize',9,'LineWidth',4);
58
% poly=mask2poly(mask,'Inner','MinDist');
59
% plot(poly(:,1),poly(:,2),'s-k','MarkerSize',12,'LineWidth',2);
60
% poly=mask2poly(mask,'Outer');
61
% plot(poly(:,1),poly(:,2),'*m','MarkerSize',9);
62
% poly=mask2poly(mask,'Exact');
63
% plot(poly(:,1),poly(:,2),'.r','MarkerSize',18);
64
% 
65
% plot(x,y,'O-b','MarkerSize',12,'LineWidth',3);
66
% hold off;
67
% legend('mask2poly- Inner- CCW','mask2poly- Inner- MinDist','mask2poly- Outer','mask2poly- Exact','poly2mask');
68
% title('mask2poly Vs. poly2mask','FontSize',14);
69
%
70
%% See also
71
% poly2mask;            % Matlab function
72
% imrect;               % Matlab function
73
% imroi;                % Matlab function
74
% sortPoint2ContourCW   % Custom function
75
% sortPointMinDist      % Custom function
76
%
77
%% Revision history
78
% First version: Nikolay S. 2011-07-07.
79
% Last update:   Nikolay S. 2011-07-25.
80
%
81
% *List of Changes:*
82
%   ------------------2011-07-25-------------------------
83
% - Ordering points accourding to rule of "nearest point" (acurate but slow) added.
84
%   ------------------2011-07-14-------------------------
85
% - An option to reorder the points so it will define a CW contour.
86
%   ------------------2011-07-13-------------------------
87
% - "Inner" and "Outer" options replaced isIndex option
88
% - Diff based edges calculation replaced contour based calculation for "Inner" and
89
%  "Outer" options, which resulted in ~x3 shorter run time.
90
% 
91
92
if nargin<3
93
   sortPointsMethod='None';
94
   if nargin<2
95
      countourType='Inner'; %{'Inner','Outer','Exact'}
96
   end
97
end
98
99
%% Pad mask to deal with edges on contours
100
paddedMask=false(2+size(mask));
101
paddedMask(1+(1:size(mask,1)),1+(1:size(mask,2)),:)=mask;
102
doubleMask=double(paddedMask);
103
countourType=upper(countourType);
104
105
switch (countourType)
106
   case({'INNER','OUTER'})
107
      %% Caculate via Gradient fast but up-to indesx exact 
108
      maskEdges=abs(doubleMask-circshift(doubleMask,[1,0,0]))+...
109
         abs(doubleMask-circshift(doubleMask,[0,1,0]))+...
110
         abs(doubleMask-circshift(doubleMask,[-1,0,0]))+...
111
         abs(doubleMask-circshift(doubleMask,[0,-1,0]));
112
      if strcmpi(countourType,'OUTER')
113
         paddedMask=~paddedMask; % Outer edges mark
114
      end
115
      [edgeRows,edgeCols]=find(maskEdges>0 & paddedMask);
116
      maskContours=cat(2,edgeCols,edgeRows); 
117
      
118
      switch(upper(sortPointsMethod))
119
         case('CW')
120
            [xCW,yCW]=sortPoint2ContourCW(maskContours(:,1),maskContours(:,2));
121
            maskContours=cat(2,xCW,yCW);
122
         case('MINDIST')
123
            [xCW,yCW]=sortPointMinDist(maskContours(:,1),maskContours(:,2));
124
            maskContours=cat(2,xCW,yCW);
125
      end % switch(upper(sortPointsMethod))
126
      
127
   otherwise
128
      %% Caculate via contour- slow yet accurate and easy to implement
129
      contourTresh=0.5*max(doubleMask(:));
130
      maskContours=contourc(doubleMask,[contourTresh,contourTresh]);
131
      maskContours=transpose(maskContours); % Convert to standart Pos coordinates system
132
end
133
134
%% Fix the inacurities caused by padding
135
maskContours=maskContours-1;
136
137
poly=maskContours;