Перейти к содержимому
Compvision.ru
virt

Тормозит приложение с методом Лукас-Канад

Recommended Posts

Привет всем.Написал приложение с использованием алгоритма Лукас-Канад.Очень тормозит приложение,никто не посмотрит в чем дело?Вроде бы все динамически выделленые переменные удаляю.

detect_motion.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

В функции FindMotion вы каждый раз выделяете память под множество изображений динамически, а затем её удаляете, хотя это и не сильно ухудьшает её скорость. Лучше сделать "ленивое" выделение памяти (использовать статик, использовать все изображения в классе с деструктором, или другой, более щадящий менеджер памяти ОС подход) или InitFound, ReleaseFound функции, либо лучше обернуть функцию в класс, тогда она будет потокобезопасной.

Ну и третье что менял, - это кол-во итераций и эпсилон.

Еще у вас c = cvWaitKey(1); ждет аж 33 мсек, хотя каждый кадр у вас и так прилично обрабатывается по времени.

Может кто еще что-то подскажет.

Main.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Сделал распознавание по своему более простому чем у вас алгоритму. По-моему у вас переставлен up++ и down++.

По упрощенному алгоритму будет хуже результат (там общее направление движения (sum) / суммарное кол-во движений (total) > некоторого порога (min_trigging_amount) ) - тогда есть движение.

Взмах руки детектируется у меня уже, пишет вверх или вниз, но я закомментил много вашего кода. См. вложение.

P.S.: мне кажется, ваш алгоритм рассчитан на большее кол-во Features в движении (ваш all), чем удается извлечь из кадра...

P.P.S.: почитал внимательно ваш алгоритм, у вас похоже просто слишком высокое требование к (double)up / total > 0.4. У меня из 45 признаков до 10 на одно движение (up или down) получается (а часто и вовсе до 6). Думаю к total (или all, по-вашему) стоит добавлять только линии длинны больше некоторой минимально определенной, а у вас эта переменная равна, по сути, corner_count.

Main_v2.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Огромное спасибо.Постараюсь разобраться и через пару дней отпишусь.Еще раз спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Здравтсвуйте,Executor.

Не подскажите ли каким образом вы определили значение min_trigging_amount?

И еще,для того,чтобы выявленное движение производилось по истечению скажем 10кадров с начала движения стоит сделать часть параметров (как total) глобальными и накапливать в цикле?или какой то еще счетчик добавить в цикле в main?

Какие будут предложения?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Здравствуйте, Virt.

При движении руки,можно как то в debbug прогонять?

Не могу сказать, что я спец в отладке, но полезными мне кажутся такие инструменты: conditional breakpoint (вы задаете условие в брейкпоинте, и когда, например переменная достигает некоторой величины, - программа останавливается на этом брейкпоинте), variable watch (не всегда оно, правда, хорошо работает, особенно, когда переменная локальная и выполнение выходит за пределы функции). Часто использую вывод отладочной информации в заголовок окна или вывод текста в консоль на каждом шаге. Вы можете попытаться логить каждую секунду (или меньший интервал) в файлик, и на каждом этапе просматривать значения, при этом постоянно искать максимальные и минимальные значения за какой-то определенный период времени.

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

Не подскажите ли каким образом вы определили значение min_trigging_amount?

min_trigging_amount я просто подбирал, когда взмахивал рукой, и искал значения (оно выводилось в консоль). Я заметил что реакция на взмах вниз на моей камере хуже идет чем взмах вверх. Поэтому, может быть, целесообразно разделить min_trigging_amount_down и min_trigging_amount_up. min_trigging_amount_down я бы поставил равным полтора min_trigging_amount_up.

И еще,для того,чтобы выявленное движение производилось по истечению скажем 10кадров с начала движения стоит сделать часть параметров (как total) глобальными и накапливать в цикле? или какой то еще счетчик добавить в цикле в main?

Тут может быть несколько вариантов. Например, что-то на подобии цифрового фильтра, при котором происходит сложная зависимость изменения переменных во времени, а также слежение, например за скоростью изменения величин и продолжительностью их изменения.

Вы можете накапливать несколько параметров, например: количество движений общих движений и распознаных перемещений вверх и вниз, а также их "результирующее перемещение" за последние 0.5 (меньше минимальной длительности жеста), 1 (среднее время жеста) и 4 (больше среднего) секунд.

После этого можно сказать следующее:

если малый участок проверки "заполнен" а средний не заполнен - тогда это шум

если малый заполнен, и средний заполнен, а больший не заполнен - тогда это (возможно) правильное перемещение (можно еще проверить, соблюдалась ли однонаправленность все три интервала времени)

"заполнен" - это значит, что за все время сканирования перемещения система приняла решение что sum > trigging_value.

также вы можете определять скорость перемещения характерных точек за некоторое время (в процентах видимого пространства, то есть например если точка уехала на 30%, - это хороший показатель для определения жеста, а 70% - это человек просто поднялся и ушел (например) )

если вы, например, сможете записывать траекторию перемещения признаков по трем точкам (или больше), и отслеживать, чтобы эта ломаная (состоящая из трех точек) имела угол раскрытия (например) < 140-150 градусов - значит движение было "относительно" однонаправленно.

Скорее всего, придется подбирать несколько ключевых коэффициентов вручную.

Если вы хотите, например, автоматизировать процесс, т.е. обучить систему на взмахи каждого человека индивидуально, то можно было-бы обучить нейронную сеть (даже один слой, нелин. активационная функция). На её входы подавать: <sum, total, up, down, sum1, total1, up1, down1, чувствиельность>, (sum - сумма за последние 0.5 секунд, sum1 - за всю последнюю 1.0 секунду, например), а на выходе единственное значение (float) - коэффициент соответстивя и его знак, например (у нейросети обычно выходы от 0 до 1 (однополярный) или -0.5 ..0.5 (биполярный сигмоид): 0..0.3 - нет движения + шумы, 0.4-0.99 - пользователь оценил движение как "хоршее" и насколько "хорошее". Нейронная сеть, в данном случае лишь метод автоматического подбора коэффициентов.

Писать код нейронной сети (и её обучения) часто не приходится, есть библиотеки FANN, Flood (http://www.cimne.com/flood/). Если вас интересует, я бы мог расписать более подробно, как я вижу эту задачу с подхода нейросетей.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поэтому, может быть, целесообразно разделить min_trigging_amount_down и min_trigging_amount_up. min_trigging_amount_down я бы поставил равным полтора min_trigging_amount_up.

Попробую.

Вы можете накапливать несколько параметров, например: количество движений общих движений и распознаных перемещений вверх и вниз, а также их "результирующее перемещение" за последние 0.5 (меньше минимальной длительности жеста), 1 (среднее время жеста) и 4 (больше среднего) секунд.

Можно немного поподробнее почему вы упоминаете 1,4 секунды?или маленький примерчик,если вас это не очень затруднит.

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

если малый участок проверки "заполнен" а средний не заполнен - тогда это шум

Извиняюсь за возможно глупый вопрос,а какой участок вы имеете ввиду?Имеете ввиду участки

за последние 0.5 (меньше минимальной длительности жеста), 1 (среднее время жеста) и 4 (больше среднего) секунд.

После этого можно сказать следующее:

.Я правильно понимаю?

также вы можете определять скорость перемещения характерных точек за некоторое время (в процентах видимого пространства, то есть например если точка уехала на 30%, - это хороший показатель для определения жеста, а 70% - это человек просто поднялся и ушел (например) )

Не подскажите можно ли где нибудь посмотреть такой пример реализации?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вопрос, как можно вычислить определить матрицы (A^T*A)в методе Лукаса-Канаде, если при подсчете даже в общем виде, он будет равен 0??

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Не будет он равен нулю. Матлабу верите?

>> A=[1 2; 3 4; 5 6; 7 8]

A =

1 2
3 4
5 6
7 8

>> A'*A

ans =

84 100
100 120

>> det(A'*A)

ans =

80.0000[/code]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Не будет он равен нулю. Матлабу верите?

>> A=[1 2; 3 4; 5 6; 7 8]


A =


     1     2

     3     4

     5     6

     7     8


>> A'*A


ans =


    84   100

   100   120


>> det(A'*A)


ans =


   80.0000

да верю )

вчера разобрался с этим.

когда прогал, то сделал сначала суммирование, а потом уже умножение, а нужно: сначала умножение по i, а потом уже суммирование. При ошибочном варианте всегда 0, это логично =)

вот так д б

det [A] = sum I_x^2 * sum I_y^2 — ( sum I_x * I_y ) ^2,

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×