Обнаружение пиков в двумерном массиве - 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 ]

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

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

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

Я не уверен, что это отвечает на вопрос, но кажется, что вы можете просто искать n самых высоких пиков, у которых нет соседей.что это в Ruby, но идея должна быть ясна.

require 'pp'

NUM_PEAKS = 5
NEIGHBOR_DISTANCE = 1

data = [[1,2,3,4,5],
        [2,6,4,4,6],
        [3,6,7,4,3],
       ]

def tuples(matrix)
  tuples = []
  matrix.each_with_index { |row, ri|
    row.each_with_index { |value, ci|
      tuples << [value, ri, ci]
    }
  }
  tuples
end

def neighbor?(t1, t2, distance = 1)
  [1,2].each { |axis|
    return false if (t1[axis] - t2[axis]).abs > distance
  }
  true
end

# convert the matrix into a sorted list of tuples (value, row, col), highest peaks first
sorted = tuples(data).sort_by { |tuple| tuple.first }.reverse

# the list of peaks that don't have neighbors
non_neighboring_peaks = []

sorted.each { |candidate|
  # always take the highest peak
  if non_neighboring_peaks.empty?
    non_neighboring_peaks << candidate
    puts "took the first peak: #{candidate}"
  else
    # check that this candidate doesn't have any accepted neighbors
    is_ok = true
    non_neighboring_peaks.each { |accepted|
      if neighbor?(candidate, accepted, NEIGHBOR_DISTANCE)
        is_ok = false
        break
      end
    }
    if is_ok
      non_neighboring_peaks << candidate
      puts "took #{candidate}"
    else
      puts "denied #{candidate}"
    end
  end
}

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