function C = CornerDet(X)
% CornerDet detects corners of traced outlines using the SAM04 algorithm.
% The outline is assumed to constitute a discrete closed curve where each
% point is included just once.
%
%
% INPUT: X (A traced outline forming a discrete closed curve)
%
% OUTPUT: C (The indices of X that consitute corner points)
%
n = length(X);
% Sets the parameters of the algorithm. Increasing D and R will give the
% same number of corners or fewer corners.
L = 80; % Controls the scale at which corners are measured.
R = 30; % Controls how close corners can appear.
D = 14; % The lower bound for the corner metric. Corner candidates with
% lower metric than this are rejected.
% Finds corner candidates
d = zeros(1,n);
for i = 1:n
if i+L <= n
k = i+L;
index = i+1:k-1;
else
k = i+L-n;
index = [i+1:n,1:k-1];
end
M = X(:,k)-X(:,i);
if M(1) == 0
dCand = abs(X(1,index)-X(1,i));
else
m = M(2)/M(1);
dCand = abs(X(2,index)-m*X(1,index)+m*X(1,i)-X(2,i))/sqrt(m^2+1);
end
[Y,I] = max(dCand);
if Y > d(index(I))
d(index(I)) = Y;
end
end
% Rejects candidates which do not meet the lower metric bound D.
index = d < D;
d(index) = 0;
C = 1:n;
index = ~logical(index);
C = C(index);
% Rejects corners that are too close to a corner with larger metric.
l = length(C);
j = 1;
while j < l
if abs(C(j)-C(j+1)) <= R
if d(C(j)) > d(C(j+1))
C = C([1:j,j+2:l]);
else
C = C([1:j-1,j+1:l]);
end
l = l-1;
else
j = j+1;
end
end
if l > 1 && abs(C(1)+n-C(end)) <=R
if d(C(end)) > d(C(1))
C = C(2:end);
else
C = C(1:end-1);
end
end
end