Я помогаю ветеринарной клинике измерять давление под лапой собаки. Я использую Python для анализа данных, и теперь я застрял, пытаясь разделить лапы на (анатомические) субрегионы.
Я сделал двумерный массив каждой лапы, который состоит из максимальных значений для каждого датчика, который был загружен лапой с течением времени. Вот пример одной лапы, где я использовал Excel, чтобы нарисовать области, которые я хочу «обнаружить». Это 2 на 2 поля вокруг датчика с локальными максимумами, которые вместе имеют наибольшую сумму.
Поэтому я попытался поэкспериментировать и решил просто искать максимумы каждого столбца и строки (не могу смотреть в одном направлении из-за формы лапы). Похоже, это «хорошо» определяет местоположение отдельных пальцев, но также отмечает соседние датчики.
Итак, что будет лучшим способом сказать Python, какие из этих максимумов те, которые я хочу?
Примечание: квадраты 2х2 не могут перекрываться, так как они должны быть отдельными пальцами!
Кроме того, я взял 2x2 для удобства, любое более продвинутое решение приветствуется, но я просто ученый по человеческому движению, поэтому я не являюсь настоящим программистом или математиком, поэтому, пожалуйста, держите его «простым».
Вот версия, которая может быть загружена сnp.loadtxt
Результаты
Поэтому я попробовал решение @ jextee (см. Результаты ниже). Как вы можете видеть, он очень хорошо работает на передних лапах, но хуже работает на задних лапах.
Более конкретно, он не может распознать маленький пик, который является четвертым пальцем ноги. Это, очевидно, присуще тому факту, что цикл смотрит сверху вниз в направлении наименьшего значения, не принимая во внимание, где это находится.
Кто-нибудь знает, как настроить алгоритм @ jextee, чтобы он тоже мог найти 4-й палец?
Поскольку я еще не обработал другие испытания, я не могу предоставить другие образцы. Но данные, которые я давал раньше, были средними для каждой лапы. Этот файл представляет собой массив с максимальными данными 9 лап в порядке их контакта с пластиной.
Это изображение показывает, как они были пространственно распределены по пластине.
Обновить:
Я создал блог для всех, кто интересуется, и я установил SkyDrive со всеми необработанными измерениями. Так что для любого, кто запрашивает больше данных: больше власти для вас!
Новое обновление:
Таким образом , после помощи я получил мои вопросы , касающиеся обнаружений лапы и лапа сортировка , я, наконец , смог проверить обнаружение схождения для каждой лапы! Оказывается, это ни на что не годится, кроме лап размером с ту, что была в моем собственном примере. Конечно, задним числом, я сам виноват в том, что выбрал 2х2 произвольно.
Вот хороший пример того, как все идет не так, как надо: гвоздь распознается как носок, а пятка такая широкая, что его распознают дважды!
Лапа слишком большая, поэтому размер 2х2 без перекрытия приводит к тому, что некоторые пальцы ног обнаруживаются дважды. С другой стороны, у маленьких собак часто не удается найти пятый палец, что, как я подозреваю, вызвано слишком большой площадью 2х2.
После пробного текущего решения на всех моих измерениях я пришел к ошеломляющему выводу , что для почти всех моих маленьких собак он не нашел 5 - й палец и что в более чем 50% от последствий для больших собак были бы найти больше!
Ясно, что мне нужно это изменить. Мое собственное предположение было изменение размера neighborhood
на что-то меньшее для маленьких собак и больше для больших собак. Но generate_binary_structure
не позволил бы мне изменить размер массива.
Поэтому я надеюсь, что у кого-то еще есть лучшее предложение для расположения пальцев ног, возможно, с масштабом области пальцев ног в зависимости от размера лап?
источник
Ответы:
Я обнаружил пики, используя локальный фильтр максимума . Вот результат для вашего первого набора данных из 4 лап:
Я также управлял им на втором наборе данных из 9 лап, и это работало также .
Вот как вы это делаете:
Все, что вам нужно сделать, это использовать
scipy.ndimage.measurements.label
маску для маркировки всех отдельных объектов. Тогда вы сможете играть с ними индивидуально.Обратите внимание, что метод работает хорошо, потому что фон не шумный. Если бы это было так, вы бы обнаружили кучу других нежелательных пиков на заднем плане. Другим важным фактором является размер окрестности . Вам нужно будет отрегулировать его, если размер пика изменяется (он должен оставаться примерно пропорциональным).
источник
Решение
Файл данных: paw.txt . Исходный код:
Вывод без перекрывающихся квадратов. Кажется, что выделены те же области, что и в вашем примере.
Некоторые комментарии
Сложная задача - вычислить суммы всех квадратов 2х2. Я предположил, что вам нужны все из них, так что могут быть некоторые совпадения. Я использовал срезы, чтобы вырезать первые / последние столбцы и строки из исходного 2D-массива, а затем накладывать их все вместе и вычислять суммы.
Чтобы понять это лучше, представим массив 3х3:
Тогда вы можете взять его ломтиками:
Теперь представьте, что вы сложили их один над другим и суммировали элементы в одинаковых позициях. Эти суммы будут точно такими же суммами для квадратов 2x2 с верхним левым углом в той же позиции:
Когда у вас есть суммы более 2х2 квадратов, вы можете использовать,
max
чтобы найти максимум илиsort
, или,sorted
чтобы найти пики.Чтобы запомнить положения вершин, я соединяю каждое значение (сумму) с его порядковым положением в уплощенном массиве (см.
zip
). Затем я снова вычисляю положение строки / столбца при печати результатов.Ноты
Я учел перекрывать квадраты 2х2. Отредактированная версия отфильтровывает некоторые из них так, что в результатах отображаются только непересекающиеся квадраты.
Выбор пальцев (идея)
Другая проблема состоит в том, как выбрать то, что, вероятно, будет пальцами из всех пиков. У меня есть идея, которая может или не может работать. У меня нет времени, чтобы реализовать это прямо сейчас, так что просто псевдокод.
Я заметил, что если передние пальцы остаются на почти идеальном круге, задний палец должен быть внутри этого круга. Кроме того, передние пальцы расположены более или менее равномерно. Мы можем попытаться использовать эти эвристические свойства для обнаружения пальцев.
Псевдокод:
Это подход грубой силы. Если N относительно мало, то я думаю, что это выполнимо. Для N = 12, есть C_12 ^ 5 = 792 комбинации, умноженные на 5 способов выбора заднего пальца, поэтому 3960 случаев нужно оценить для каждой лапы.
источник
Это проблема с регистрацией изображений . Общая стратегия:
Вот грубый и готовый подход , «самая глупая вещь, которая могла бы работать»:
Чтобы противодействовать проблеме ориентации, у вас может быть около 8 начальных настроек для основных направлений (Север, Северо-Восток и т. Д.). Запустите каждый из них по отдельности и отбросьте любые результаты, когда два или более пальцев оказываются в одном пикселе. Я подумаю об этом еще немного, но такие вещи все еще исследуются в обработке изображений - нет правильных ответов!
Немного более сложная идея: (взвешенная) K-означает кластеризацию. Это не так уж плохо.
Затем итерации до сходимости:
Этот метод почти наверняка даст гораздо лучшие результаты, и вы получите массу каждого кластера, которая может помочь в определении пальцев.
(Опять же, вы указали количество кластеров заранее. С кластеризацией вы должны указать плотность так или иначе: либо выберите количество кластеров, подходящее в этом случае, либо выберите радиус кластера и посмотрите, сколько вы заканчиваете вверх с. Примером последнего является среднее смещение .)
Извините за отсутствие деталей реализации или других особенностей. Я бы написал это, но у меня есть крайний срок. Если к следующей неделе ничего не получится, дайте мне знать, и я сделаю это.
источник
Используя постоянную гомологию для анализа вашего набора данных, я получаю следующий результат (нажмите, чтобы увеличить):
Это 2D-версия метода обнаружения пиков, описанного в этом ответе SO . На приведенном выше рисунке просто показаны 0-мерные классы постоянных гомологий, отсортированные по постоянству.
Я увеличил исходный набор данных в 2 раза, используя scipy.misc.imresize (). Тем не менее, обратите внимание, что я рассматривал четыре лапы как один набор данных; разделение его на четыре облегчит проблему.
Методология. Идея этого довольно проста: рассмотрим функциональный график функции, которая назначает каждому пикселю свой уровень. Это выглядит так:
Теперь рассмотрим уровень воды на высоте 255, который постоянно опускается до более низких уровней. На местных максимумах всплывают острова (роды). В седловых точках два острова сливаются; мы считаем, что нижний остров сливается с высшим островом (смерть). Так называемая диаграмма персистентности (классов гомологии 0-го уровня, наши острова) отображает значения смертности по рождению всех островов:
настойчивость островка тогда разница между birth- и смерти уровня; вертикальное расстояние от точки до серой главной диагонали. Фигура обозначает острова, уменьшая постоянство.
Самая первая картинка показывает места рождения островов. Этот метод не только дает локальные максимумы, но также количественно определяет их «значимость» по вышеупомянутой стойкости. Затем можно было бы отфильтровать все острова со слишком низкой устойчивостью. Однако в вашем примере каждый остров (т. Е. Каждый локальный максимум) - это вершина, которую вы ищете.
Код Python можно найти здесь .
источник
Эта проблема была подробно изучена физиками. В ROOT есть хорошая реализация . Посмотрите на классы TSpectrum (особенно TSpectrum2 для вашего случая) и документацию для них.
Ссылки:
... и для тех, у кого нет доступа к подписке на NIM:
источник
Вот идея: вы вычисляете (дискретный) лапласиан изображения. Я ожидал бы, что он будет (отрицательным и) большим в максимумах, таким способом, который будет более драматичным, чем на исходных изображениях. Таким образом, максимумы легче найти.
Вот еще одна идея: если вы знаете типичный размер пятен высокого давления, вы можете сначала сгладить ваше изображение, свернув его с гауссианом того же размера. Это может дать вам более простые изображения для обработки.
источник
Просто пара идей с моей головы:
Возможно, вы также захотите взглянуть на OpenCV , у него довольно приличный Python API и могут быть некоторые функции, которые вы найдете полезными.
источник
Я уверен, что у вас есть достаточно, чтобы продолжить, но я не могу не предложить использовать метод кластеризации k-средних. k-means - это алгоритм неконтролируемой кластеризации, который будет собирать ваши данные (в любом количестве измерений - мне случается делать это в 3D) и распределять их по k кластерам с различными границами. Здесь хорошо, потому что вы точно знаете, сколько пальцев должно быть у этих клыков.
Кроме того, это реализовано в Scipy, что очень приятно ( http://docs.scipy.org/doc/scipy/reference/cluster.vq.html ).
Вот пример того, что он может сделать для пространственного разрешения 3D-кластеров:
То, что вы хотите сделать, это немного по-другому (2D и включает в себя значения давления), но я все еще думаю, что вы могли бы попробовать.
источник
спасибо за необработанные данные. Я нахожусь в поезде, и это так далеко, как я получил (моя остановка подходит). Я помассировал ваш txt-файл с помощью регулярных выражений и поместил его на html-страницу с некоторым javascript для визуализации. Я делюсь этим здесь, потому что некоторые, как и я, могут найти его более легко взломать, чем Python.
Я думаю, что хорошим подходом будет инвариант масштаба и ротации, и мой следующий шаг - исследовать смеси гауссиан. (каждая подушечка лап является центром гауссиана).
источник
Решение физика:
определите 5 маркеров лап, идентифицированных по их позициям,
X_i
и начните их со случайных позиций. Определите некоторую энергетическую функцию, сочетающую некоторую награду за расположение маркеров в положениях лап и некоторое наказание за наложение маркеров; скажем так:(
S(X_i)
средняя сила в квадрате 2x2X_i
,alfa
является параметром, который должен быть экспериментально достигнут)Теперь пора заняться магией Метрополис-Гастингс:
1. Выберите случайный маркер и переместите его на один пиксель в случайном направлении.
2. Рассчитайте dE, разницу энергии, вызванную этим движением.
3. Получите равномерное случайное число от 0 до 1 и назовите его r.
4. Если
dE<0
илиexp(-beta*dE)>r
, примите движение и перейдите к 1; если нет, отмените движение и перейдите к 1.Это должно повторяться до тех пор, пока маркеры не сойдутся в лапы. Бета контролирует сканирование для оптимизации компромисса, поэтому его также следует оптимизировать экспериментально; оно также может постоянно увеличиваться со временем моделирования (имитация отжига).
источник
Вот еще один подход, который я использовал, когда делал нечто подобное для большого телескопа:
1) Поиск самого высокого пикселя. Как только у вас это получится, найдите это для наилучшего соответствия для 2x2 (возможно, максимизируя сумму 2x2), или сделайте 2d гауссовое соответствие внутри подобласти, скажем, 4x4 с центром в верхнем пикселе.
Затем установите те 2х2 пикселя, которые вы нашли на ноль (или, может быть, 3х3) вокруг центра пика
вернитесь к пункту 1) и повторяйте до тех пор, пока самый высокий пик не опустится ниже порога шума, или пока у вас не появятся все необходимые пальцы
источник
Вероятно, стоит попробовать с нейронными сетями, если вы можете создать некоторые обучающие данные ... но для этого нужно много образцов, аннотированных вручную.
источник
грубая схема ...
Вы, вероятно, захотите использовать алгоритм связанных компонентов, чтобы изолировать каждую область лапы. В вики есть достойное описание этого (с некоторым кодом) здесь: http://en.wikipedia.org/wiki/Connected_Component_Labeling
вам придется принять решение о том, использовать 4 или 8 подключений. лично для большинства проблем я предпочитаю 6-связность. в любом случае, после того, как вы выделите каждый «отпечаток лапы» в качестве связанной области, должно быть достаточно легко выполнить итерацию по области и найти максимумы. Найдя максимумы, вы можете многократно увеличивать регион, пока не достигнете заранее определенного порога, чтобы идентифицировать его как заданный «носок».
одна тонкая проблема здесь заключается в том, что как только вы начнете использовать методы компьютерного зрения для определения чего-либо как правой / левой / передней / задней лапы и начнете смотреть на отдельные пальцы ног, вы должны будете принимать во внимание повороты, перекосы и переводы. это достигается путем анализа так называемых «моментов». Есть несколько различных моментов, которые следует учитывать в приложениях для зрения:
центральные моменты: трансляционно-инвариантные нормализованные моменты: скейлинг и трансляционно-инвариантные моменты h: трансляция, масштаб и инвариант вращения
Более подробную информацию о моментах можно найти, выполнив поиск «моменты изображения» в вики.
источник
Возможно, вы можете использовать что-то вроде гауссовых моделей смесей. Вот пакет Python для выполнения GMM (только что сделал поиск Google) http://www.ar.media.kyoto-u.ac.jp/members/david/softwares/em/
источник
Кажется, вы можете немного обмануть, используя алгоритм Jetxee. Он находит первые три пальца в порядке, и вы должны быть в состоянии угадать, где четвертый основан на этом.
источник
Интересная проблема. Решение, которое я бы попробовал, заключается в следующем.
Примените фильтр нижних частот, такой как свертка, с двумерной гауссовой маской. Это даст вам кучу (возможно, но не обязательно с плавающей запятой) значений.
Выполните двумерное немаксимальное подавление, используя известный приблизительный радиус каждой подушечки лап (или носка).
Это должно дать вам максимальные позиции без нескольких кандидатов, которые находятся близко друг к другу. Просто чтобы уточнить, радиус маски на шаге 1 должен быть аналогичен радиусу, используемому на шаге 2. Этот радиус может быть выбран, или ветеринар может явно измерить его заранее (он будет зависеть от возраста / породы / и т. Д.).
Некоторые из предложенных решений (среднее смещение, нейронные сети и т. Д.), Вероятно, будут работать в некоторой степени, но слишком сложны и, вероятно, не идеальны.
источник
Ну, вот несколько простых и не очень эффективных кодов, но для такого размера набора данных это хорошо.
Я просто делаю массив с положением верхнего левого угла и суммой каждого квадрата 2х2 и сортирую его по сумме. Затем я беру квадрат 2х2 с наибольшей суммой из спора, кладу его в
best
массив и удаляю все остальные квадраты 2x2, которые использовали любую часть этого только что удаленного квадрата 2x2.Кажется, что он работает нормально, за исключением последней лапы (с самой маленькой суммой в правом нижнем углу на вашей первой картинке), оказывается, что есть два других приемлемых квадрата 2x2 с большей суммой (и они имеют равную сумму друг с другом). Один из них по-прежнему выбирает один квадрат из вашего квадрата 2x2, а другой - слева. К счастью, по счастливой случайности мы видим, что выбираем больше того, что вам хотелось бы, но для этого может потребоваться использовать другие идеи, чтобы получить то, что вы на самом деле хотите, все время.
источник
Просто хочу сказать вам, ребята, что есть хорошая опция для поиска локальных
maxima
изображений в python:или для лыжного мага
0.8.0
:http://scikit-image.org/docs/0.8.0/api/skimage.feature.peak.html
источник
Возможно, здесь достаточно наивного подхода: составьте список всех квадратов 2х2 на плоскости, упорядочите их по сумме (в порядке убывания).
Сначала выберите самый ценный квадрат в вашем «списке лап». Затем, итеративно выберите 4 из следующих лучших квадратов, которые не пересекаются ни с одним из ранее найденных квадратов.
источник
Существует несколько обширных программных продуктов, доступных от астрономического и космологического сообщества - это значительная область исследований как исторически, так и в настоящее время.
Не пугайтесь, если вы не астроном - некоторые из них легко использовать за пределами поля. Например, вы можете использовать astropy / photutils:
https://photutils.readthedocs.io/en/stable/detection.html#local-peak-detection
[Кажется немного грубым повторять их короткий пример кода здесь.]
Неполный и слегка предвзятый список техник / пакетов / ссылок, которые могут представлять интерес, приведен ниже - добавьте больше комментариев, и я буду обновлять этот ответ по мере необходимости. Конечно, есть компромисс между точностью и вычислительными ресурсами. [Честно говоря, их слишком много, чтобы привести примеры кода в одном ответе, таком как этот, поэтому я не уверен, будет ли этот ответ вылетать или нет.]
Source Extractor https://www.astromatic.net/software/sextractor
MultiNest https://github.com/farhanferoz/MultiNest [+ pyMultiNest]
Задача ASKAP / EMU по поиску источника: https://arxiv.org/abs/1509.03931
Вы также можете искать проблемы с извлечением источника в Планке и / или WMAP.
...
источник
Что делать, если вы продолжите шаг за шагом: сначала найдите глобальный максимум, обработайте, если необходимо, окружающие точки, учитывая их значение, затем установите найденный регион на ноль и повторите для следующего.
источник
Я не уверен, что это отвечает на вопрос, но кажется, что вы можете просто искать n самых высоких вершин, у которых нет соседей.
Вот суть. Обратите внимание, что это в Ruby, но идея должна быть ясной.
источник