у меня есть бинарное изображение и мне нужно найти число пикселей между подключенными объектами я использую MATLAB и вот моим образомОпределение количества пикселей между подключенными объектами
Thx
у меня есть бинарное изображение и мне нужно найти число пикселей между подключенными объектами я использую MATLAB и вот моим образомОпределение количества пикселей между подключенными объектами
Thx
Интересная проблема, но ее не так сложно решить. Это просто потребует много кода, но каждая строка кода очень проста в понимании. Это базовый алгоритм, который я хотел бы выполнить:
imfindcircles
regionprops
для вычисления площадей оставшихся квадратных объектов и определить минимальный ограничивающий прямоугольник, необходимый для инкапсуляции квадратов, где у них были круги, перекрывающиеся с ними.AND
. Это найдет области, где пересекаются оба круга. Как только мы получим их, мы просто подсчитаем оставшиеся пиксели, и это будет перекрывающаяся область для двух кругов.Я собираюсь предположить, что у вас есть Image Processing Toolbox, или мой метод не будет работать. Вам также необходимо, по крайней мере, MATLAB R2012a для Circular Hough Transform, которое будет включено в ваш дистрибутив MATLAB.
Мы должны сначала инвертировать изображение таким образом, что белый соответствует объекту пикселей и черные соответствует фону. В противном случае regionprops
и imfindcircles
не будут работать. Я буду читать в изображении непосредственно из StackOverflow:
im = imread('http://i.stack.imgur.com/WQtgP.png'); %// Already binary!
im = ~im;
Далее, давайте использовать круговой Хаф преобразования. Мы хотели бы использовать его так:
[centres, radii] = imfindcircles(im, [25 60]);
im
будет бинарное изображение, которое мы только конвертируется и массив [25 60]
обозначает минимальный и максимальный радиусы окружностей, которые мы хотим обнаружить. В этом случае минимальный радиус равен 25, а максимальный радиус равен 60. centres
и radii
обозначают координаты столбца и строки центра каждого круга и радиус каждого круга соответственно. Первый столбец centres
- это координата столбца, а второй столбец - это координата строки. После запуска этого кода мы обнаруживаем 4 круга (как и ожидалось).centres
и radii
выглядеть следующим образом:
centres =
267.5005 67.5005
233.5152 200.4808
83.2850 83.2850
117.6691 118.0193
radii =
33.3178
33.1137
32.9332
32.8488
Это означает, что один круг был обнаружен на колонке 267.50, строка 67.50 с радиусом 33.3178, которая считывается с первой строки каждого результата. Вы можете следить за остальными значениями в каждой переменной. Что отличное в Circular Hough Transform, так это то, что он может обнаружить частичные круги, что очень приятно из-за перекрытия кругов и квадратов. Если вы хотите, чтобы увидеть обнаруженные результаты, вы можете использовать viscircles
так:
imshow(im);
viscircles(centres, radii, 'DrawBackgroundCircle', false);
Я поставил DrawBackgroundCircle
в false
, потому что когда мы рисуем обнаруженные круги, по умолчанию он рисует контур белым по кругу. Я не хочу, чтобы вы путали это с любыми пикселями объекта, поэтому я установил этот флаг на false
.
Это цифра, мы получим:
Круто!
Самый простой способ будет петля над всеми своими кругами, создать круглую сетку координат и установить эти пиксели в изображении, чтобы false
, чтобы удалить их из вашего изображения , Вы можете сделать это, используя meshgrid
, чтобы создать 2D-сетку местоположений строк и столбцов и индексировать их на своем изображении, чтобы установить их на false
. Что-то вроде этого:
[X,Y] = meshgrid(1:size(im,2), 1:size(im,1));
im_no_circles = im;
for idx = 1 : numel(radii)
r = radii(idx);
c = centres(idx,:);
mask = (X - c(1)).^2 + (Y - c(2)).^2 <= r^2;
im_no_circles(mask) = false;
end
Этот код будет принимать каждый круг и установить соответствующие места в изображении, чтобы false
. Однако то, что изображение выглядит как сейчас:
Есть некоторые краевые артефакты из кругов из-за квантования шума. Мы можем удалить эти пиксели, используя bwareaopen
. Любые области, области которых находятся ниже определенной величины, удалите их из изображения. Мы можем выбрать что-то вроде 50, потому что эти квадраты, конечно же, превышают 50 пикселей, а ложные пиксели - нет. После этого сделаем морфологическое открытие с imopen
, чтобы избавиться от любых шумных пикселей, которые связаны с каждым из квадратов, чтобы мы могли действительно получить квадратные фигуры без каких-либо кругов.
Итак:
im_no_circles_open = bwareaopen(im_no_circles, 50);
im_open = imopen(im_no_circles_open, strel('square', 5));
Это, наконец, что мы получаем:
Мы называем regionprops
так:
s = regionprops(im_open, 'Area', 'BoundingBox');
s
будет содержать структуру, описывающую каждый из наших квадратных объектов.Если мы рассмотрим каждый атрибут, это то, что мы получаем:
areas = [s.Area].'
bb = reshape([s.BoundingBox], [], numel(areas)).'
areas =
4178
4138
4489
bb =
134.5000 50.5000 67.0000 67.0000
150.5000 200.5000 67.0000 67.0000
334.5000 59.5000 67.0000 67.0000
Каждый квадрат область находится в массиве areas
в то время как bb
массив, где каждый ряд содержит информацию о каждом квадрате. В частности, первый и второй элементы каждой строки являются координатами столбца и координатами строк в верхнем левом углу каждого ограничивающего прямоугольника, который используется для полного инкапсуляции объекта. Третий и четвертый элементы - это ширина и высота каждого ограничивающего прямоугольника. Таким образом, это говорит нам, что нам нужен ящик размером 67 х 67 пикселей для каждого ограничивающего прямоугольника, чтобы полностью инкапсулировать объект. Это также равно общей площади , если полная граница была заполнена.
Как MATLAB обнаруживает коробки в том, что она идет сверху вниз, слева направо. Таким образом, есть только два поля, которые перекрываются с любыми кругами, и поэтому это первые два поля в обнаруженном результате, который нам нужно посмотреть. Таким образом, для квадрата и круга в верхнем левом углу, которые были перекрытием, общая площадь будет:
overlap1 = bb(1,3)*bb(1,4) - areas(1)
overlap1 =
311
Помните, что мы можем найти общую площадь квадрата простого умножения его ширины и высоты вместе. Когда мы вычитаем это с фактической площадью, занятой квадратом без круга, мы получаем пиксели, которые были взяты по кругу.
Аналогично, для коробки на дне:
overlap2 = bb(2,3)*bb(2,4) - areas(2)
overlap2 =
351
Наконец, то, что осталось сами по себе являются фактическими кругами. Все, что нам нужно сделать, это создать пустое изображение, нарисовать оба круга в этом изображении вместе с логическим оператором AND
и найти общую площадь оставшегося. На первом этапе эти два перекрывающихся круга соответствуют: (x,y) = 83.2850, 83.2850
и (x,y) = 117.6691, 118.0193
. Они соответствуют двум последним кругам, обнаруженным в Circular Hough Transform. Давайте эти два круга и создать нашу маску:
Как например:
centre1 = centres(3,:);
centre2 = centres(4,:);
radii1 = radii(3);
radii2 = radii(4);
circle1 = (X - centre1(1)).^2 + (Y - centre1(2)).^2 <= radii1^2;
circle2 = (X - centre2(1)).^2 + (Y - centre2(2)).^2 <= radii2^2;
final_two = circle1 & circle2;
Если мы покажем это изображение, это то, что мы получаем:
Это визуализируя перекрытие между двумя кругами. Что теперь осталось, это просто подсчитать перекрытие:
overlap3 = sum(final_two(:))
overlap3 =
515
Уф! Это была большая работа!
Вы хотите, чтобы найти те пересекающиеся области, как выше с двумя кругами, но и для остальной части изображения. Есть еще две пересекающиеся области, которые нам нужно найти. Первый находится внизу изображения между кругом и квадратом, а второй - между квадратом и кружком в верхнем левом углу.
Чтобы получить первый, просто создайте круговую маску, как мы делали ранее, и сделаем логический И с заполненным квадратом, который касается этого круга. Круг, который находится внизу, является вторым обнаруженным кружком из выходного сигнала Circular Hough Transform. Кроме того, затронутый квадрат является вторым, обнаруженным от regionprops
. Поэтому:
r = radii(2);
c = centres(2,:);
mask_circle = (X - c(1)).^2 + (Y - c(2)).^2 <= r^2;
mask_square = false(size(im));
mask_square(floor(bb(2,2)):floor(bb(2,2)) + bb(2,4), floor(bb(2,1)):floor(bb(2,1)) + bb(2,3)) = true;
intersect1 = mask_circle & mask_square;
Вот что первая пересекалась область выглядит следующим образом:
Вы можете применить ту же логику выше остальных квадратные и круговые области, в верхней части. Вам просто нужно выбрать правильный квадрат и круг. Это будет четвертый обнаруженным круг и первая обнаруженная площадь:
r = radii(4);
c = centres(4,:);
mask_circle = (X - c(1)).^2 + (Y - c(2)).^2 <= r^2;
mask_square = false(size(im));
mask_square(floor(bb(1,2)):floor(bb(1,2)) + bb(1,4), floor(bb(1,1)):floor(bb(1,1)) + bb(1,3)) = true;
intersect2 = mask_circle & mask_square;
Это то, что мы получаем:
Гораздо проще решения найти перекрывающиеся участки между 2 бинарными изображениями будут добавьте оба изображения по элементам (простое добавление матриц в python, я думаю, что это одно и то же в MATLAB). Все перекрывающиеся пиксели получат значение 2. Примените двоичное пороговое значение для полученного изображения с порогом, установленным в 1. Это даст вам перекрывающиеся области.
Я вернулся к предыдущей версии. Было бы полезно показать всем, как выглядит ваш образ, а не удалять его со своего поста. – rayryeng