Наименьшее расстояние между конкретным объектом и другими объектами - PullRequest
1 голос
/ 02 июня 2019

После этих двух постов, посвященных поиску расстояния между объектами в двоичном изображении, как я могу вывести / рассчитать только самое короткое расстояние между конкретным объектом и остальными (например, {1-> 3}, {2 -> 5}, {3-> 1}, {4-> 7)?

Сценарий:

clc;
clear all;
I = rgb2gray(imread('E:/NCircles.png'));
imshow(I);
BW = imbinarize(I,'adaptive');
BW = imfill(BW, 'holes');
BW = bwlabel(BW); 

s = regionprops(BW,'Area', 'BoundingBox', 'Eccentricity', 'MajorAxisLength', 'MinorAxisLength', 'Orientation', 'Perimeter','Centroid');


imshow(BW)
hold on
for k = 1:numel(s)
    c = s(k).Centroid;
    text(c(1), c(2), sprintf('%d', k), 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle');
end

boundaries = bwboundaries(BW);
numberOfBoundaries = size(boundaries, 1);
for k = 1 : numberOfBoundaries
    thisBoundary = boundaries{k};
    plot(thisBoundary(:,2), thisBoundary(:,1), 'r', 'LineWidth', 3);
end
hold off;

% Define object boundaries
numberOfBoundaries = size(boundaries, 1)

for b1 = 1 : numberOfBoundaries
    for b2 = 1 : numberOfBoundaries
        if b1 == b2
            % Can't find distance between the region and itself
            continue;
        end
        boundary1 = boundaries{b1};
        boundary2 = boundaries{b2};
        boundary1x = boundary1(:, 2);
        boundary1y = boundary1(:, 1);
        x1=1;
        y1=1;
        x2=1;
        y2=1;
        overallMinDistance = inf; % Initialize.
        % For every point in boundary 2, find the distance to every point in boundary 1.
        for k = 1 : size(boundary2, 1)
            % Pick the next point on boundary 2.
            boundary2x = boundary2(k, 2);
            boundary2y = boundary2(k, 1);
            % For this point, compute distances from it to all points in boundary 1.
            allDistances = sqrt((boundary1x - boundary2x).^2 + (boundary1y - boundary2y).^2);
            % Find closest point, min distance.
            [minDistance(k), indexOfMin] = min(allDistances);
            if minDistance(k) < overallMinDistance
                x1 = boundary1x(indexOfMin);
                y1 = boundary1y(indexOfMin);
                x2 = boundary2x;
                y2 = boundary2y;
                overallMinDistance = minDistance(k);
            end
        end
        % Find the overall min distance
        minDistance = min(minDistance);
        % Report to command window.
        fprintf('The minimum distance from region %d to region %d is %.3f pixels\n', b1, b2, minDistance);

        % Draw a line between point 1 and 2
        line([x1, x2], [y1, y2], 'Color', 'y', 'LineWidth', 3);
    end
end 

enter image description here

1 Ответ

1 голос
/ 02 июня 2019

Дано BW и boundaries, как определено выше, и исходный объект, из которого можно рассчитать расстояния до всех других объектов:

source_object = 1;   % label of source object in BW

Создайте дистанционное изображение таким образом, чтобы значение каждого пикселя было его расстоянием от исходного объекта, используя bwdist:

% anonymous function to convert cell array of subsripts
% into cell array of indices
indsfun = @(a) sub2ind(size(BW), a(:,1), a(:,2));

% use function on all of the cell's boundary objects
object_inds = cellfun(indsfun, boundaries, 'UniformOutput', false);


source_image = zeros(size(BW));   % create image containing only source object
source_image(object_inds{source_object}) = 1;

% compute distance from source to all other pixels in image
dist_image = bwdist(source_image, 'euclidean');   % replace with desired metric
imagesc(dist_image);   % not necessary, but gives a cool image

Теперь для каждого объекта в исходном изображении найдите минимальное расстояние от его границы до границы исходного объекта:

min_dist = zeros(1,numel(boundaries));   % hold minimum distances

for target_object = 1:numel(boundaries)
   % get the distance values at the indices of the target object
   % and store the minimum.
   min_dist(target_object) = min(dist_image(object_inds{target_object}));
end

В конце концов, min_dist будет содержать минимальное (граничное) расстояние от исходного объекта до всех других объектов. Пробный прогон на вашем изображении дает следующие евклидовы расстояния:

min_dist =

 Columns 1 through 7:
     0.00000    67.54258    60.00000   207.23416   154.48625   168.79869   319.01410

 Columns 8 through 13:
   236.05296   324.71063   344.05814   367.00000   469.07996   509.00000
...