0

у меня есть бинарное изображение и мне нужно найти число пикселей между подключенными объектами я использую MATLAB и вот моим образомОпределение количества пикселей между подключенными объектами

enter image description here

Thx

+0

Я вернулся к предыдущей версии. Было бы полезно показать всем, как выглядит ваш образ, а не удалять его со своего поста. – rayryeng

ответ

1

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

  1. Найти все круги в изображении с помощью Circular Hough Transform - imfindcircles
  2. Удалить круги из вашего изображения
  3. Использование regionprops для вычисления площадей оставшихся квадратных объектов и определить минимальный ограничивающий прямоугольник, необходимый для инкапсуляции квадратов, где у них были круги, перекрывающиеся с ними.
  4. Эти минимальные координаты ограничительной рамки были бы верхними левыми и нижними правыми координатами квадрата , если он должен быть полностью заполнен. Поскольку круги, которые перекрываются на квадраты, мы можем найти область перекрытия, просто взяв полную площадь каждого ограничивающего прямоугольника и вычтем с обнаруженной областью. Остающаяся сумма будет областями, которые пересекаются с кругами.
  5. Чтобы определить область, которая перекрывается двумя кругами, нужно всего лишь нарисовать оба круга на изображении и выполнить логическую операцию AND. Это найдет области, где пересекаются оба круга. Как только мы получим их, мы просто подсчитаем оставшиеся пиксели, и это будет перекрывающаяся область для двух кругов.

Я собираюсь предположить, что у вас есть Image Processing Toolbox, или мой метод не будет работать. Вам также необходимо, по крайней мере, MATLAB R2012a для Circular Hough Transform, которое будет включено в ваш дистрибутив MATLAB.


Шаг № 1

Мы должны сначала инвертировать изображение таким образом, что белый соответствует объекту пикселей и черные соответствует фону. В противном случае 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.

Это цифра, мы получим:

enter image description here

Круто!


Шаг № 2

Самый простой способ будет петля над всеми своими кругами, создать круглую сетку координат и установить эти пиксели в изображении, чтобы 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. Однако то, что изображение выглядит как сейчас:

enter image description here

Есть некоторые краевые артефакты из кругов из-за квантования шума. Мы можем удалить эти пиксели, используя bwareaopen. Любые области, области которых находятся ниже определенной величины, удалите их из изображения. Мы можем выбрать что-то вроде 50, потому что эти квадраты, конечно же, превышают 50 пикселей, а ложные пиксели - нет. После этого сделаем морфологическое открытие с imopen, чтобы избавиться от любых шумных пикселей, которые связаны с каждым из квадратов, чтобы мы могли действительно получить квадратные фигуры без каких-либо кругов.

Итак:

im_no_circles_open = bwareaopen(im_no_circles, 50); 
im_open = imopen(im_no_circles_open, strel('square', 5)); 

Это, наконец, что мы получаем:

enter image description here

Шаг № 3

Мы называем 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 пикселей для каждого ограничивающего прямоугольника, чтобы полностью инкапсулировать объект. Это также равно общей площади , если полная граница была заполнена.

Шаг № 4

Как MATLAB обнаруживает коробки в том, что она идет сверху вниз, слева направо. Таким образом, есть только два поля, которые перекрываются с любыми кругами, и поэтому это первые два поля в обнаруженном результате, который нам нужно посмотреть. Таким образом, для квадрата и круга в верхнем левом углу, которые были перекрытием, общая площадь будет:

overlap1 = bb(1,3)*bb(1,4) - areas(1) 

overlap1 = 

311 

Помните, что мы можем найти общую площадь квадрата простого умножения его ширины и высоты вместе. Когда мы вычитаем это с фактической площадью, занятой квадратом без круга, мы получаем пиксели, которые были взяты по кругу.

Аналогично, для коробки на дне:

overlap2 = bb(2,3)*bb(2,4) - areas(2) 

overlap2 = 

351 

Шаг # 5

Наконец, то, что осталось сами по себе являются фактическими кругами. Все, что нам нужно сделать, это создать пустое изображение, нарисовать оба круга в этом изображении вместе с логическим оператором 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; 

Если мы покажем это изображение, это то, что мы получаем:

enter image description here

Это визуализируя перекрытие между двумя кругами. Что теперь осталось, это просто подсчитать перекрытие:

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; 

Вот что первая пересекалась область выглядит следующим образом:

enter image description here


Вы можете применить ту же логику выше остальных квадратные и круговые области, в верхней части. Вам просто нужно выбрать правильный квадрат и круг. Это будет четвертый обнаруженным круг и первая обнаруженная площадь:

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; 

Это то, что мы получаем:

enter image description here

+0

это было потрясающе !! спасибо ! но что, если я хочу все пересечения? и еще раз спасибо за потрясающее решение! – geekslot

+0

Вы имеете в виду пересечения, такие как изображение с двумя кругами? – rayryeng

+0

ну, как пересечение между кругом и квадратом внизу – geekslot

0

Гораздо проще решения найти перекрывающиеся участки между 2 бинарными изображениями будут добавьте оба изображения по элементам (простое добавление матриц в python, я думаю, что это одно и то же в MATLAB). Все перекрывающиеся пиксели получат значение 2. Примените двоичное пороговое значение для полученного изображения с порогом, установленным в 1. Это даст вам перекрывающиеся области.