Pull to refresh

Comments 38

Можно было попробовать Матлабом с Image Processing Toolbox, или ImageJ
Здесь как я понял задачка описать алгоритм и представить реализацию. С готовыми тулзами, ясен хобот, все проще :)
У вас кое-где съелись внешние круги.

А что, если разрыв будет сильнее?
Надо делать более умную заливку — чтобы не точка распространялась, а окружность определённого радиуса. Где она целиком пролезет — туда и зальёт.

Автору по поводу «морфологий» — я бы порекомендовал не blur'ить результат, а построить дерево вложенности залитых областей, после чего оставить только самую внешнюю связную область (фон) и первичных потомков этого корня (волшебные пузырьки).
Да, если разрыв будет сильнее, то некоторые точки теряются. Я старался брать тестовые картинки с максимальным разнообразием частиц (по форме и размерам), и на них результат получился просто отличный. Но несколько фотографий через два дня показали, что нужно алгоритм совершенствовать: действительно часть областей получается совсем чуть-чуть разомкнутой, и они теряются.
Я уже думал применить метод, похожий по существу на то, что предложил Harkonnen: с помощью той же математической морфологии замкнуть слегка разомкнутые границы. Но всё оказалось сложнее: плотность частиц может быть очень высокой, и вместе с нужными границами ещё выделяется много «мусора», в котором наш диск попросту застревает, приводя таким образом к обнаружению абсолютно «левых» частиц (которых на самом деле нет).
Примеры фоток и примеры результатов, может чего-то подскажем)
Добавил пример ещё одной фотографии в комментариях к такому же алгоритму для тех же целей в среде MATLAB.
Интересно и познавательно, спасибо, но а где программа? хотел почувствовать себя химиком :)
А мне вот как не химику интересно, а что же за «волшебные пузырьки» на этих фотках?
Сферические округлости в вакууме, разве не понятно?
Это инновации. И без всяких кавычек. Действительно.
Если у меня получится автоматизировать процесс… Я не готов говорить что точно будет, но будет просто великолепно :)
Эх, а я прочел анонс в твиттере, и на минутку помечтал, что в статье речь совсем о других «округлостях» пойдет…
Только тссс! А то борцы за духовную безопасность интернета возьмут на вооружение.
Да-да. Последующая фраза про электронный микроскоп все испортила.
Аналогично. Заходил в топик с намерением откомментировать пост соответствующей картинкой.
Берем программу автора по детектированию округлостей, берем 3D-принтер, заправляем его силиконом — профитъ!
В нашей лабе один из студентов занимается подобными изысканиями. Направлю ка я ему эту ссылку. Одно плохо — он русского не знает… :) Он кстати тоже на Матлабе делает.
Рекомендую не опираться на алгоритмы основанные на гистерезисе без лишней надобности (non-maximum suppression в canny edge detector'е).
Хоть вы и говорите что ваши объекты могут «быть совершенно непохожими на окружности», попробуйте сделать так:
1. Возьмите экземпляр объекта высокого разрешения (шаблон), примените к нему преобразование (о нем позже)
2. Для каждого квадратного окна входного изображения А. уменьшите его до размера шаблона и Б. посчитайте над ним тоже самое преобразование, а затем корреляцию результата и преобразованного шаблона. Если корреляция велика, то перед вами экземпляр объекта

Преобразование может быть например таким:
1. Перевод RGB-Luma
2. OutPix = dx*dx + dy*dy, где dx — это результат применения оператора Собеля по горизонтали (например с ядром 3х3), а dy — по вертикали. Таким образом в каждом пикселе будет записан квадрат производной по направлению, т.е. грубо говоря сила границы.
Класс! Надо обязательно осилить себя и сделать это! Большое спасибо за идею!
Для каждого квадратного окна? Я так понимаю нужно перебирать и позиции окна и размеры? Сразу встает вопрос — в каких границах размеры окна перебирать? Сколько все это будет по времени длится?
На лабах делали такое — очень плохо работало даже для обычных бинарных шаблонов типа самолет и колечко.
как насчёт пересекающихся кругов (т.е. если объекты «наложены»)?
Они не определяются. Или, вернее, если границы четкие, то конечно определяются, но ведь заодно я считаю площадь частицы, а также её полярные точки. Как из площади, так и из крайних точек я получаю значение диаметра окружности (из предположения, конечно, что это окружность), и если эти два диаметра отличаются не больше чем на 80%, то объект засчитывается. Если нет — отбрасывается.
о, пытаюсь решать похожую задачу, только каждая частица у меня представляет собой агрегат из нескольких слипшихся шариков.
и присоединяюсь к вопросу, что представляет из себя объект вашего исследования.
Детектирование циркулярностей на пикче. тоже вроде понятно)
>«Canny Edge Detector» (как по-русски я не знаю, не бейте)
«хитрый определитель границ»
виноват, не знал, перевел дословно
>«Canny Edge Detector» — всего лишь детектор краев Канни, один из методов выделения границ
Насчет заливки — я еще одну использовал для цифровой обработки изображений — заливка с затравкой, вот реализация на джаве pastebin.com/WaLgEEzr
Попробуйте натравить на сканы Плэйбоя — сколько округлостей найдет?:) А вообще спасибо, было интересно почитать.
А на самом деле это же для поиска сисек, да?
Подобная задача встречается у микроскопистов, работающих с клетками. Нужно подсчитать общее количество клеток, количество окрашенных и т.д. При этом клетки хоть и округлые, но могу быть достаточно замысловатых форм, слипаться и т.д. Возможно, что в программах для биологов можно будет найти интересные алгоритмы.
Очень, очень интересная и актуальная статья! Про заливку и про этот алгоритм поиска в ширину расскажите пожалуйста, не соображу как задачу над изображением преобразовать к задаче над графом.
Довольно несложно: простым перебором всех точек (и их соседей) изображения. Для упрощения задачи изображение должно быть двуцветным. В качестве примера реализации можно привести код, предложенный alexeygrigorev, в этом комментарии.
Как я и написал, для заливки я воспользовался готовым классом (они, кстати, очень похожи).
Пользоваться им очень просто:

FloodFill rere = new FloodFill(whereDetectToFillWhite); // whereDetectToFillWhite - объект java.awt.Image;
Color white = new Color(255, 255, 255);
rere.fill(1, 1, white); // Здесь вроде всё понятно: (икс_заливки, игрек_заливки, объект_цвета)
Image whereDetectJustFilled = rere.getImage();
Спасибо, идею понял по исходникам, совсем забыл начала программирования.
Я вот как придумал избавится от рваных контуров:
1. Выделяем контура,
2. Делаем Дилатацию — расширяем границы — скорее всего после этого контура соединятся, но станут толстыми.
3. Потом делаем заливку — толстые и замкнутые контура не позволят залить объект.
4. Потом по бинарному изображению опять выделяем контура — совсем простым образом, они вот эти уже контура не должна быть рваные.
Предполагаемый недостаток — контур слегка сместится, но это не очень страшно, его потом можно уточнить.
Как думаете — будет работать? Сейчас реализовываю потихонечку.
Я так уже пробовал, и уже писал здесь в комментариях. К сожалению, в моём случае это ведёт также к «обнаружению» несуществующих окружностей…
Only those users with full accounts are able to leave comments. Log in, please.