В этом примере показано, как автоматически обнаружить круги или округлые объекты в изображении и визуализировать обнаруженные круги.
Считывайте и отображайте изображение круглых пластиковых чипов различных цветов. Помимо того, что есть много кругов, чтобы обнаружить, есть несколько интересных вещей, происходящих в этом изображении с точки зрения обнаружения круга:
Существуют фишки разных цветов, которые имеют разные контрасты относительно фона. На одном конце синие и красные таковые имеют сильную контрастность на этом фоне. На другом конце некоторые желтые фишки плохо контрастируют с фоном.
Заметьте, как одни фишки находятся на верхнюю часть друг друга, а другие - близко друг к другу и почти касаются друг друга. Перекрываемые контуры объектов и окклюзия объектов обычно являются сложными сценариями для обнаружения объектов.
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
The 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' устанавливает порог обнаружения ниже и приводит к обнаружению большего количества кругов. Это похоже на управление чувствительностью на детекторах движения, используемых в домашних системах безопасности.
Возвращаясь к чиповому изображению, возможно, что на уровне чувствительности по умолчанию все круги ниже внутреннего порога, из-за чего круги не были обнаружены. По умолчанию 'Sensitivity', которое является числом от 0 до 1, устанавливается на 0,85. Увеличьте 'Sensitivity' до 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);
Центры окружностей кажутся правильно расположенными, и их соответствующие радиусы, кажется, хорошо соответствуют фактическим фишкам. Но все же было пропущено довольно много фишек. Попробуйте увеличить 'Sensitivity' еще больше, до 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. В целом, эти два метода являются взаимодополняющими, в которых они имеют различные сильные стороны. Метод фазового кодирования обычно быстрее и немного более устойчивый к шуму, чем двухэтапный метод. Но ему также могут потребоваться более высокие уровни 'Sensitivity', чтобы получить то же количество обнаружений, что и двухэтапному методу. Для примера способ фазы кодирования также находит те же микросхемы, если уровень 'Sensitivity' повышен, скажем, до 0,95.
[centers,radii] = imfindcircles(rgb,[20 25],'ObjectPolarity','dark', ... 'Sensitivity',0.95); delete(h) viscircles(centers,radii);
Обратите внимание, что оба метода в imfindcircles
точно найти центры и радиусы частично видимых (окклюдированных) чипов.
Глядя на последний результат, любопытно, что imfindcircles
не находит желтые фишки на изображении. Желтые фишки не имеют сильной контрастности с фоном. На самом деле они, кажется, имеют очень похожую интенсивность, как фон. Возможно ли, что желтые фишки на самом деле не «темнее» фона, как предполагалось? Чтобы подтвердить, снова отобразите полутоновую версию этого изображения.
imshow(gray_image)
Желтые фишки почти такой же интенсивности, может быть, даже ярче, по сравнению с фоном. Поэтому, чтобы обнаружить желтые чипы, смените 'ObjectPolarity' на 'bright'.
[centersBright,radiiBright] = imfindcircles(rgb,[20 25], ... 'ObjectPolarity','bright','Sensitivity',0.92);
Нарисуйте яркие круги в другом цвете, изменив параметр 'Color' в 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
находит все желтые таковые и зеленые тоже. Нарисуйте эти фишки синим цветом, вместе с другими фишками, которые были найдены ранее (с установленным на 'dark' значением 'ObjectPolarity'), красным цветом.
h = viscircles(centers,radii);
Все круги обнаруживаются. Конечное слово - следует отметить, что изменение параметров, чтобы быть более агрессивными в обнаружении, может найти больше кругов, но это также увеличивает вероятность обнаружения ложных кругов. Существует компромисс между количеством истинных кругов, которые могут быть найдены (частота обнаружения) и количеством ложных кругов, которые найдены с ними (частота ложных предупреждений).
Счастливая охота за кругом!