В этом примере показано, как автоматически обнаруживать круги или круглые объекты на изображении и визуализировать обнаруженные круги.
Считывайте и выводите изображение круглых пластиковых фишек различных цветов. Помимо наличия большого количества кругов для обнаружения, в этом изображении происходит несколько интересных вещей с точки зрения обнаружения круга:
Есть фишки разных цветов, которые имеют разные контрасты по отношению к фону. С одной стороны, синие и красные имеют сильный контраст на этом фоне. С другой стороны, некоторые желтые чипсы плохо контрастируют с фоном.
Обратите внимание, как одни фишки находятся друг на друге, а другие - близко друг к другу и почти соприкасаются друг с другом. Перекрывающиеся границы объектов и окклюзия объектов обычно являются сложными сценариями для обнаружения объектов.
rgb = imread('coloredChips.png');
imshow(rgb)
Найдите соответствующий диапазон радиуса окружностей с помощью команды drawline функция. Нарисуйте линию над приблизительным диаметром кристалла.
d = drawline;

Длина линии ROI - это диаметр микросхемы. Типичные чипы имеют диаметры в диапазоне от 40 до 50 пикселей.
pos = d.Position; diffPos = diff(pos); diameter = hypot(diffPos(1),diffPos(2))
diameter = 45.3448
imfindcircles функция ищет круги с диапазоном радиусов. Поиск кругов с радиусами в диапазоне от 20 до 25 пикселей. Перед этим рекомендуется спросить, ярче или темнее объекты, чем фон. Чтобы ответить на этот вопрос, посмотрите на версию этого изображения в градациях серого.
gray_image = rgb2gray(rgb); imshow(gray_image)

Фон довольно яркий и большинство фишек темнее фона. Но, по умолчанию, imfindcircles находит круглые объекты, которые ярче фона. Таким образом, задайте параметру ObjectPolarity значение dark в imfindcircles для поиска темных кругов.
[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark')
centers =
[]
radii =
[]
Обратите внимание, что выходы centers и radii пусты, что означает, что круги не найдены. Это происходит часто, потому что imfindcircles является детектором круга и аналогичен большинству детекторов, imfindcircles имеет внутренний порог обнаружения, который определяет его чувствительность. Говоря простым языком, это означает, что уверенность детектора в определенном (круговом) обнаружении должна быть больше, чем определенный уровень, прежде чем он будет считаться действительным обнаружением. imfindcircles имеет параметр «Sensitivity», который может использоваться для управления этим внутренним порогом и, следовательно, чувствительностью алгоритма. Более высокое значение «Sensitivity» устанавливает порог обнаружения ниже и приводит к обнаружению большего количества кругов. Это аналогично управлению чувствительностью детекторов движения, используемых в домашних системах безопасности.
Возвращаясь к изображению чипа, возможно, что на уровне чувствительности по умолчанию все круги ниже внутреннего порога, поэтому круги не были обнаружены. По умолчанию значение «Чувствительность», которое равно числу от 0 до 1, равно 0,85. Увеличьте чувствительность до 0,9.
[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', ... 'Sensitivity',0.9)
centers = 8×2
146.1895 198.5824
328.8132 135.5883
130.3134 43.8039
175.2698 297.0583
312.2831 192.3709
327.1316 297.0077
243.9893 166.4538
271.5873 280.8920
radii = 8×1
23.1604
22.5710
22.9576
23.7356
22.9551
22.9995
22.9055
23.0298
На этот раз imfindcircles нашли несколько кругов - восемь, если быть точным. centers содержит местоположения центров окружностей и radii содержит оценочные радиусы этих окружностей.
Функция viscircles может использоваться для рисования кругов на изображении. Выходные переменные centers и radii от imfindcircles может быть передан непосредственно в viscircles.
imshow(rgb) h = viscircles(centers,radii);

Центры круга кажутся правильно расположенными, и их соответствующие радиусы, похоже, хорошо совпадают с фактическими фишками. Но все же было упущено довольно много фишек. Попробуйте увеличить «Чувствительность» еще больше, до 0,92.
[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', ... 'Sensitivity',0.92); length(centers)
ans = 16
Таким образом, увеличение «Чувствительности» дает нам еще больше кругов. Снова нанесите эти круги на изображение.
delete(h) % Delete previously drawn circles
h = viscircles(centers,radii);
Этот результат выглядит лучше. imfindcircles имеет два разных метода нахождения кругов. До сих пор для обнаружения кругов использовался метод по умолчанию, называемый методом фазового кодирования. Есть еще один метод, обычно называемый двухэтапным, который доступен в imfindcircles. Используйте двухэтапный метод и просмотрите результаты.
[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', ... 'Sensitivity',0.92,'Method','twostage'); delete(h) h = viscircles(centers,radii);

Двухэтапный метод обнаруживает больше кругов, при чувствительности 0,92. В общем, эти два метода являются взаимодополняющими в том смысле, что они имеют разные сильные стороны. Способ фазового кодирования обычно является более быстрым и немного более устойчивым к шуму, чем двухступенчатый способ. Но также может потребоваться более высокий уровень чувствительности, чтобы получить такое же количество обнаружений, что и двухэтапный метод. Например, способ фазового кодирования также находит те же элементарные сигналы, если уровень «чувствительности» повышен, скажем, до 0,95.
[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', ... 'Sensitivity',0.95); delete(h) viscircles(centers,radii);

Обратите внимание, что оба метода в imfindcircles точно найти центры и радиусы частично видимых (окклюдированных) чипов.
Глядя на последний результат, любопытно, что imfindcircles не находит желтых фишек на изображении. Желтые фишки не имеют сильного контраста с фоном. На самом деле они, похоже, имеют очень похожую интенсивность, как фон. Возможно ли, что желтые фишки на самом деле не «темнее», чем фон, как предполагалось? Для подтверждения снова отобразите версию этого изображения в градациях серого.
imshow(gray_image)

Желтые фишки почти такой же интенсивности, может быть даже ярче, по сравнению с фоном. Поэтому для обнаружения желтых фишек измените 'ObjectPolarity' на 'яркий'.
[centersBright,radiiBright] = imfindcircles(rgb,[20 25], ... 'ObjectPolarity','bright','Sensitivity',0.92);
Нарисуйте яркие круги другого цвета, изменив параметр «Цвет» в viscircles.
imshow(rgb) hBright = viscircles(centersBright, radiiBright,'Color','b');

Отметим, что три из недостающих желтых фишек были найдены, но одна желтая фишка до сих пор отсутствует. Эти желтые фишки трудно найти, потому что они не выделяются так хорошо, как другие на этом фоне.
В есть еще один параметр imfindcircles что может быть полезно здесь, а именно «EdgeThreshold». Чтобы найти круги, imfindcircles использует только краевые пикселы в изображении. Эти краевые пиксели по существу являются пикселями с высоким значением градиента. Параметр «EdgeThreshold» определяет, насколько высоким должно быть значение градиента в пикселе, прежде чем он будет считаться краевым пикселем и включенным в расчет. Высокое значение (ближе к 1) для этого параметра позволит включить только сильные края (более высокие значения градиента), в то время как низкое значение (ближе к 0) является более разрешительным и включает даже более слабые края (более низкие значения градиента) в расчет. В случае отсутствия желтой микросхемы, поскольку контраст низок, некоторые граничные пиксели (на окружности микросхемы), как ожидается, будут иметь низкие значения градиента. Поэтому уменьшите параметр «EdgeThreshold», чтобы обеспечить включение в вычисления большинства краевых пикселей для желтой микросхемы.
[centersBright,radiiBright,metricBright] = imfindcircles(rgb,[20 25], ... 'ObjectPolarity','bright','Sensitivity',0.92,'EdgeThreshold',0.1); delete(hBright) hBright = viscircles(centersBright, radiiBright,'Color','b');

Сейчас imfindcircles находит все желтые, и зеленую тоже. Нарисовать эти фишки синим цветом, вместе с другими фишками, которые были найдены ранее (с 'ObjectPolarity', установленным на 'dark'), красным.
h = viscircles(centers,radii);

Все круги обнаружены. Последнее слово - следует отметить, что изменение параметров на более агрессивные в обнаружении может найти больше кругов, но это также увеличивает вероятность обнаружения ложных кругов. Существует компромисс между количеством истинных окружностей, которые могут быть найдены (частота обнаружения), и количеством ложных окружностей, которые найдены с ними (частота ложных тревог).
Счастливый круг охоты!