Обнаружение пиков в двумерном массиве - PullRequest
813 голосов
/ 10 сентября 2010

Я помогаю ветеринарной клинике измерять давление под лапой собаки.Я использую Python для анализа данных, и теперь я застрял, пытаясь разделить лапы на (анатомические) субрегионы.

Я сделал двухмерный массив каждой лапы, который состоит из максимальных значений для каждого датчика, который имеетбыл загружен лапой с течением времени.Вот пример одной лапы, где я использовал Excel, чтобы нарисовать области, которые я хочу «обнаружить».Это 2 на 2 поля вокруг датчика с локальными максимумами, которые вместе имеют наибольшую сумму.

alt text

Поэтому я попытался поэкспериментировать и решил просто искать максимумы каждогостолбец и строка (не может смотреть в одном направлении из-за формы лапы).Похоже, что это «хорошо» определяет местоположение отдельных пальцев, но также отмечает соседние датчики.

alt text

Итак, как лучше всего сказать Python, какие из этих максимумов я хочу получить?

Примечание: квадраты 2x2 не могут перекрываться, поскольку они должны быть отдельными пальцами!

Также для удобства я взял 2x2, приветствуется любое более сложное решение, но я просто ученый по человеческому движению, так что я не настоящий программист и не математик, поэтому, пожалуйста, держите это «простым».

Вот версия, которую можно загрузить с np.loadtxt


Результаты

Итак, я попробовал решение @ jextee (см. Результаты ниже)).Как вы можете видеть, он очень хорошо работает на передних лапах, но хуже работает на задних лапах.

Точнее говоря, он не может распознать маленькую вершину четвертого пальца.Это, очевидно, присуще тому факту, что цикл смотрит сверху вниз в направлении наименьшего значения, не принимая во внимание, где это находится.

Кто-нибудь знает, как настроить алгоритм @ jextee, чтобы он тоже мог найти 4-й палец?

alt text

Поскольку я не обработалникаких других испытаний пока нет, я не могу предоставить другие образцы.Но данные, которые я давал раньше, были средними для каждой лапы.Этот файл представляет собой массив с максимальными данными в 9 лап в порядке их контакта с пластиной.

На этом изображении показано, как они были пространственно распределены по пластине.

alt text

Обновление:

Я создал блог для всех, кто интересуется и Я установил SkyDrive со всеми необработанными измерениями. Так что для любого, кто запрашивает больше данных: больше энергии для вас!


Новое обновление:

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

Вот хороший пример того, как все идет не так: гвоздь распознается как носок, а пятка такая широкая, чтораспознается дважды!

alt text

Лапа слишком большая, поэтому при размере 2х2 без наложения некоторые пальцы могут быть обнаружены дважды.С другой стороны, у маленьких собак часто не удается найти пятый палец, что, как я подозреваю, вызвано слишком большой площадью 2х2.

После попытки использовать текущее решение для всех моих измерений Я пришел к ошеломляющему выводу, что почти для всех моих маленьких собак он не нашел 5-го пальца ноги и что в более чем 50% ударов для крупных собак он нашел бы больше!

Так ясно, что янужно поменять.Мое собственное предположение состояло в том, чтобы изменить размер neighborhood на что-то меньшее для маленьких собак и больше для больших собак.Но generate_binary_structure не позволил бы мне изменить размер массива.

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

Ответы [ 22 ]

6 голосов
/ 10 сентября 2010

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

6 голосов
/ 10 сентября 2010

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

1) Поиск самого высокого пикселя.Как только у вас это получится, найдите это для наилучшего соответствия для 2x2 (возможно, максимизируя сумму 2x2), или сделайте 2d гауссовое соответствие внутри подобласти, скажем, 4x4 с центром в верхнем пикселе.

Затем установите те2x2 пикселя, которые вы нашли равными нулю (или, может быть, 3x3) вокруг центра пика

, вернитесь к 1) и повторяйте до тех пор, пока самый высокий пик не упадет ниже порога шума, или у вас есть все необходимые пальцы

6 голосов
/ 10 сентября 2010

грубый контур ...

Вы, вероятно, захотите использовать алгоритм подключенных компонентов, чтобы изолировать каждую область лапы. В вики есть достойное описание этого (с некоторым кодом) здесь: http://en.wikipedia.org/wiki/Connected_Component_Labeling

вам придется принять решение о том, использовать 4 или 8 подключений. лично для большинства проблем я предпочитаю 6-связность. в любом случае, после того, как вы выделите каждый «отпечаток лапы» в качестве связанной области, должно быть достаточно легко выполнить итерацию по области и найти максимумы. Найдя максимумы, вы можете многократно увеличивать регион, пока не достигнете заранее определенного порога, чтобы идентифицировать его как заданный «носок».

одна тонкая проблема здесь заключается в том, что как только вы начинаете использовать методы компьютерного зрения для определения чего-либо как правой / левой / передней / задней лапы, и вы начинаете смотреть на отдельные пальцы ног, вы должны начать принимать повороты, перекосы и переводы в учетную запись. это достигается путем анализа так называемых «моментов». В приложениях для зрения есть несколько моментов, которые следует учитывать:

центральные моменты: инвариант перевода нормированные моменты: масштабирование и перевод-инвариант моменты h: инвариант перемещения, масштабирования и вращения

Более подробную информацию о моментах можно найти, выполнив поиск «моменты изображения» в вики.

5 голосов
/ 10 сентября 2010

Возможно, вы можете использовать что-то вроде гауссовых моделей смесей.Вот пакет Python для выполнения GMM (только что сделал поиск Google) http://www.ar.media.kyoto -u.ac.jp / members / david / softwares / em /

4 голосов
/ 10 сентября 2010

Кажется, вы можете немного обмануть, используя алгоритм jetxee. Он находит первые три пальца в порядке, и вы должны быть в состоянии угадать, где находится четвертый.

4 голосов
/ 11 сентября 2010

Интересная проблема. Решение, которое я бы попробовал, заключается в следующем.

  1. Примените фильтр нижних частот, такой как свертка, с двумерной гауссовой маской. Это даст вам кучу (возможно, но не обязательно с плавающей запятой) значений.

  2. Выполните двумерное немаксимальное подавление, используя известный приблизительный радиус каждой лапки (или пальца ноги).

Это должно дать вам максимальные позиции без нескольких кандидатов, которые находятся близко друг к другу. Просто чтобы уточнить, радиус маски на шаге 1 должен быть аналогичен радиусу, используемому на шаге 2. Этот радиус может быть выбран, или ветеринар может явно измерить его заранее (он будет зависеть от возраста / породы / и т. Д.).

Некоторые из предложенных решений (среднее смещение, нейронные сети и т. Д.), Вероятно, будут работать в некоторой степени, но слишком сложны и, вероятно, не идеальны.

3 голосов
/ 05 апреля 2018

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

from skimage.feature import peak_local_max

или для лыжного мага 0.8.0

from skimage.feature.peak import peak_local_max

http://scikit -image.org / документы / 0.8.0 / апи / skimage.feature.peak.html

3 голосов
/ 10 сентября 2010

Хорошо, вот простой и не очень эффективный код, но для такого размера набора данных это хорошо.

import numpy as np
grid = np.array([[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
              [0,0,0,0,0,0,0,0,0.4,0.4,0.4,0,0,0],
              [0,0,0,0,0.4,1.4,1.4,1.8,0.7,0,0,0,0,0],
              [0,0,0,0,0.4,1.4,4,5.4,2.2,0.4,0,0,0,0],
              [0,0,0.7,1.1,0.4,1.1,3.2,3.6,1.1,0,0,0,0,0],
              [0,0.4,2.9,3.6,1.1,0.4,0.7,0.7,0.4,0.4,0,0,0,0],
              [0,0.4,2.5,3.2,1.8,0.7,0.4,0.4,0.4,1.4,0.7,0,0,0],
              [0,0,0.7,3.6,5.8,2.9,1.4,2.2,1.4,1.8,1.1,0,0,0],
              [0,0,1.1,5,6.8,3.2,4,6.1,1.8,0.4,0.4,0,0,0],
              [0,0,0.4,1.1,1.8,1.8,4.3,3.2,0.7,0,0,0,0,0],
              [0,0,0,0,0,0.4,0.7,0.4,0,0,0,0,0,0]])

arr = []
for i in xrange(grid.shape[0] - 1):
    for j in xrange(grid.shape[1] - 1):
        tot = grid[i][j] + grid[i+1][j] + grid[i][j+1] + grid[i+1][j+1]
        arr.append([(i,j),tot])

best = []

arr.sort(key = lambda x: x[1])

for i in xrange(5):
    best.append(arr.pop())
    badpos = set([(best[-1][0][0]+x,best[-1][0][1]+y)
                  for x in [-1,0,1] for y in [-1,0,1] if x != 0 or y != 0])
    for j in xrange(len(arr)-1,-1,-1):
        if arr[j][0] in badpos:
            arr.pop(j)


for item in best:
    print grid[item[0][0]:item[0][0]+2,item[0][1]:item[0][1]+2]

Я в основном просто делаю массив с положением верхнего левого угла и суммой каждого квадрата 2х2 и сортирую его по сумме. Затем я вынимаю квадрат 2x2 с наибольшей суммой из состязаний, помещаю его в массив best и удаляю все остальные квадраты 2x2, которые использовали любую часть этого только что удаленного квадрата 2x2.

Кажется, что он работает нормально, за исключением последней лапы (с самой маленькой суммой в правом нижнем углу на вашем первом снимке), получается, что есть два других приемлемых квадрата 2x2 с большей суммой (и у них есть равные суммы друг другу). Один из них по-прежнему выбирает один квадрат из вашего квадрата 2x2, а другой - слева. К счастью, по счастливой случайности мы выбираем больше того, что вам хотелось бы, но это может потребовать использования некоторых других идей, чтобы получить то, что вы на самом деле хотите все время.

1 голос
/ 10 сентября 2010

Может быть, здесь достаточно наивного подхода: составьте список всех квадратов 2х2 на плоскости, упорядочите их по сумме (в порядке убывания).

Сначала выберите наиболее ценный квадрат в вашем «списке лап».Затем, итеративно выберите 4 из следующих лучших квадратов, которые не пересекаются ни с одним из ранее найденных квадратов.

0 голосов
/ 08 февраля 2019

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

Не пугайтесь, если вы не астроном - некоторыелегко использовать вне поля.Например, вы можете использовать astropy / photutils:

https://photutils.readthedocs.io/en/stable/detection.html#local-peak-detection

[Кажется немного грубым повторять здесь их короткий пример кода.]

Неполный и немногоПристрастный список методов / пакетов / ссылок, которые могут представлять интерес, приведен ниже - добавьте больше в комментариях, и я буду обновлять этот ответ по мере необходимости.Конечно, есть компромисс между точностью и вычислительными ресурсами.[Честно говоря, их слишком много, чтобы привести примеры кода в одном ответе, таком как этот, поэтому я не уверен, будет ли этот ответ летать или нет.]

Source Extractor https://www.astromatic.net/software/sextractor

MultiNesthttps://github.com/farhanferoz/MultiNest [+ pyMultiNest]

Задача поиска источника ASKAP / EMU: https://arxiv.org/abs/1509.03931

Вы также можете выполнить поиск задач извлечения источника из Планка и / или WMAP.

...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...