A simple approach would be:
- Rotate the image in accordance with the main axis
- Calculate the difference of points on the contour line
- Find the peaks in the differences vector and save the latter.
Here's the code (version 2):
% Read the image img = imread(path_to_image); % Binarize the image bw = img > 127; % Compute principal component orientation and rotate orientation = regionprops(bw, 'Orientation'); centroid = regionprops(bw,'centroid'); % Correct rotation according to centroid rotationAngle = -90 - orientation.Orientation; if(centroid.Centroid(1) < size(img,2)/2) rotationAngle = 90 - orientation.Orientation; end rotated = imrotate(bw, rotationAngle); rows = size(rotated,1); dist = zeros(rows, 1); % vector of distances of contour points imshow(rotated); hold on; % Compute the distances for r=1:rows s = find(rotated(r,:), 1, 'first'); e = find(rotated(r,:), 1, 'last'); if(~isempty(s) && ~isempty(e)) dist(r) = e - s; plot(s, r, 'xg'); plot(e, r, 'xr'); end end % Smooth for cleaner peaks %dist = smooth(dist, 15); % Find peaks [pks, locs] = findpeaks(-dist); % Select the peak carefully... th = 20; % A threshold on the distance among peaks loc = locs(end); for i = length(locs)-1 : -1 : 1 if(abs(locs(i) - loc) > th) break; else loc = locs(i); end end % Keep best ycut = loc; plot([1, size(rotated,2)], [ycut, ycut], 'b'); hold off; figure(); plot(dist); hold on; plot(locs, -pks, 'vg'); hold off;
Result

source share