Download this file

137 lines (130 with data), 5.8 kB

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