Как найти центроиды кластеров пикселей в двоичном изображении - PullRequest
1 голос
/ 06 мая 2019

Я написал некоторый код в MATLAB, который преобразует изображение (звезд) в двоичное изображение, используя установленный порог, а затем маркирует каждое скопление пикселей (звезд), которое находится выше этого порога. Маркировка производит вывод: например,

[1 1 1 0 0 0 0 0 0
 1 1 0 0 0 2 2 2 0
 0 0 0 3 3 0 2 0 0
 0 0 0 3 3 0 0 0 0]

Таким образом, каждая группа из 1, 2, 3 и т. Д. Представляет собой звезду. Я использовал ответ, предоставленный по этой ссылке: Как найти все подключенные компоненты в двоичном изображении в Matlab? , чтобы пометить пиксели. Я также не могу использовать набор инструментов для обработки изображений. Код, который у меня есть, показан ниже.

Как мне теперь найти центроиды каждого кластера пикселей на изображении?

clc
clear all
close all
img=imread('star.jpg');
binary_image=convert2binary(img);
imshow(binary_image);
visited = false(size(binary_image));
[rows, cols] = size(binary_image);
B = zeros(rows, cols);
ID_counter = 1;
for row = 1:rows
    for col = 1:cols
        if binary_image(row, col) == 0
            visited(row, col) = true;
        elseif visited(row, col)
            continue;
        else
            stack = [row col];

            while ~isempty(stack)
                loc = stack(1,:);
                stack(1,:) = [];

                if visited(loc(1),loc(2))
                    continue;
                end

                visited(loc(1),loc(2)) = true;
                B(loc(1),loc(2)) = ID_counter;

                [locs_y, locs_x] = meshgrid(loc(2)-1:loc(2)+1, loc(1)-1:loc(1)+1);
                locs_y = locs_y(:);
                locs_x = locs_x(:);

                out_of_bounds = locs_x < 1 | locs_x > rows | locs_y < 1 | locs_y > cols;
                locs_y(out_of_bounds) = [];
                locs_x(out_of_bounds) = [];
                is_visited = visited(sub2ind([rows cols], locs_x, locs_y));

                locs_y(is_visited) = [];
                locs_x(is_visited) = [];

                is_1 = binary_image(sub2ind([rows cols], locs_x, locs_y));
                locs_y(~is_1) = [];
                locs_x(~is_1) = [];

                stack = [stack; [locs_x locs_y]];
            end

            ID_counter = ID_counter + 1;
        end
    end
end

function [binary] = convert2binary(img)

    [x, y, z]=size(img);
    if z==3
        img=rgb2gray(img);
    end

    img=double(img);
    sum=0;
    for i=1:x
        for j=1:y
            sum=sum+img(i, j);
        end
    end


    threshold=100  % or sum/(x*y);
    binary=zeros(x,y);

    for i=1:x
        for j=1:y
            if img(i, j) >= threshold
                binary(i, j) = 1;
            else
                binary(i, j)=0;
            end
        end
    end
end

1 Ответ

1 голос
/ 06 мая 2019

Центроид - это момент первого порядка.Он вычисляется как

sum(x*v)/sum(v) , sum(y*v)/sum(v)

Для двоичного изображения вы можете сделать это (я использую тривиальный цикл, а не векторизованный код, поэтому мы можем легко расширить его позже):

img = [1 1 1 0 0 0 0 0 0
       1 1 0 0 0 2 2 2 0
       0 0 0 3 3 0 2 0 0
       0 0 0 3 3 0 0 0 0]; % Op's example data

bin = img==1;              % A binary image

% Algorithm
sum_v = 0;
sum_iv = 0;
sum_jv = 0;
for jj=1:size(bin,2)
   for ii=1:size(bin,1)
      sum_v = sum_v + bin(ii,jj);
      sum_iv = sum_iv + ii * bin(ii,jj);
      sum_jv = sum_jv + jj * bin(ii,jj);
   end
end
centroid = [sum_iv, sum_jv] / sum_v;

Конечно, вы можете перебирать каждую из меток помеченного изображения img и применять приведенный выше код.Но это крайне неэффективно.Вместо этого мы можем пройти по изображению один раз и вычислить все центроиды одновременно.Мы конвертируем sum_v и т. Д. В векторы, содержащие по одной бегущей сумме на метку:

N = max(img(:));     % number of labels
sum_v = zeros(N,1);
sum_iv = zeros(N,1);
sum_jv = zeros(N,1);
for jj=1:size(img,2)
   for ii=1:size(img,1)
      index = img(ii,jj);
      if index>0
         sum_v(index) = sum_v(index) + 1;
         sum_iv(index) = sum_iv(index) + ii;
         sum_jv(index) = sum_jv(index) + jj;
      end
   end
end
centroids = [sum_iv, sum_jv] ./ sum_v;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...