# Find boundary of curve-forming points

14 views (last 30 days)
Zhenghao Yang on 6 May 2022
Commented: Zhenghao Yang on 6 Jun 2022
I want to extract the boundary points, namely the most outer parts of the points, which form a closed curve. I have tried to use boundary function but it always misses some of the points. I put 3 plotings below, the first one is the data, the second one explains the boundary I need to find out, the third one is a matlab result using boundary function with tolerance=0.8.   Image Analyst on 7 May 2022
Try using movmin() to get the lower boundary, and movmax() to get the upper boundary. Or try boundary():
s = struct with fields:
beta: [149×1 double]
x = real(s.beta);
y = imag(s.beta);
boundaryIndexes = boundary(x, y);
plot(x, y, 'b.');
grid on;
hold on;
boundaryIndexes = boundary(x, y, 0.9);
plot(x(boundaryIndexes), y(boundaryIndexes), 'm-') Star Strider on 7 May 2022
This is not perfect, however it is the best I can do with these data —
beta = LD.beta;
r = abs(beta);
a = angle(beta);
[Ua,ix] = unique(a);
Ur = r(ix);
ra = [Ur Ua];
ra = sortrows(ra,2);
av = linspace(min(ra(:,2)), max(ra(:,2)), 500).';
rv = interp1(ra(:,2), ra(:,1), av(:));
rai = [rv av];
winmax = 17;
rmax = movmax(rai(:,1),winmax);
xv = rmax.*cos(rai(:,2));
yv = rmax.*sin(rai(:,2));
figure
plot(beta, '.')
hold on
plot(xv, yv, '-r')
hold off
The approach is to determine the angles and radii based on the centre being at (0,0) then finding the maximum radius in each ‘window’ defined by ‘winmax’ and using the movmax function to get the maximum radius in that region. I use interpolation with interp1 to create an angle vector with increased resolution and regularly-spaced angles. The interpolation is not absolutely necessary (although they make creating the boundary easiier), however the unique and sort calls are. Experiment with this approach to get the desired result.
The plot: .

Image Analyst on 7 May 2022
Here's a way you can get exactly the points you want by having the user encircle the points you want to exclude:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 15;
markerSize = 30;
fprintf('Beginning to run %s.m ...\n', mfilename);
x = real(s.beta);
y = imag(s.beta);
boundaryIndexes = boundary(x, y);
hFig = figure;
plot(x, y, 'b.', 'MarkerSize', markerSize);
grid on;
hold on;
hFig.WindowState = 'maximized';
drawnow;
instructions = 'Draw a polygon. Double click to finish it.';
title(instructions, 'FontSize', fontSize)
xlabel('x', 'FontSize', fontSize)
ylabel('y', 'FontSize', fontSize)
uiwait(helpdlg('Draw a polygon. Double click to finish it.'));
hpoly = drawpolygon()
xPoly = hpoly.Position(:, 1);
yPoly = hpoly.Position(:, 2);
rowsToExclude = false(length(x));
for k = 1 : length(x)
rowsToExclude(k) = inpolygon(x(k), y(k), xPoly, yPoly);
end
% Delete the points encircled by the user.
x(rowsToExclude) = [];
y(rowsToExclude) = [];
plot(x, y, 'r.', 'MarkerSize', markerSize);
title('Red Points are the Extracted (Kept) (x,y)', 'FontSize', fontSize) Zhenghao Yang on 6 Jun 2022
That's a good method, but the problem is that I have 400 data groups all of this kind when the parameter of my system is defined. Not to mention when the parameter is varied. So if possible I would prefer an automatic method rather than a manual one.