virt 1 Жалоба Опубликовано March 5, 2011 Привет всем.Написал приложение с использованием алгоритма Лукас-Канад.Очень тормозит приложение,никто не посмотрит в чем дело?Вроде бы все динамически выделленые переменные удаляю.detect_motion.rar Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
executor 5 Жалоба Опубликовано March 5, 2011 В прикрепленном файле, в целом скорость чуть поднял (в 2-4 раза), изменял размеры блоков, кол-во Features. В функции FindMotion вы каждый раз выделяете память под множество изображений динамически, а затем её удаляете, хотя это и не сильно ухудьшает её скорость. Лучше сделать "ленивое" выделение памяти (использовать статик, использовать все изображения в классе с деструктором, или другой, более щадящий менеджер памяти ОС подход) или InitFound, ReleaseFound функции, либо лучше обернуть функцию в класс, тогда она будет потокобезопасной. Ну и третье что менял, - это кол-во итераций и эпсилон. Еще у вас c = cvWaitKey(1); ждет аж 33 мсек, хотя каждый кадр у вас и так прилично обрабатывается по времени. Может кто еще что-то подскажет.Main.zip Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
virt 1 Жалоба Опубликовано March 5, 2011 Спасибо огромное.Действительно лучше стало.Надеюсь еще лучше получиться реализовать.Извините,а не подскажите где может быть ошибка в алгоритме?-не определяется взмах руки. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
executor 5 Жалоба Опубликовано March 5, 2011 Сделал распознавание по своему более простому чем у вас алгоритму. По-моему у вас переставлен 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 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
virt 1 Жалоба Опубликовано March 7, 2011 Огромное спасибо.Постараюсь разобраться и через пару дней отпишусь.Еще раз спасибо. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
virt 1 Жалоба Опубликовано March 7, 2011 Только вот еще вопрос.При движении руки,можно как то в debbug прогонять?у меня вышло слишком долго и нецелесообразно.Кроме как проверки алгоритма,можно как то проверять программу практически?поделись опытом. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
virt 1 Жалоба Опубликовано March 9, 2011 Здравтсвуйте,Executor. Не подскажите ли каким образом вы определили значение min_trigging_amount? И еще,для того,чтобы выявленное движение производилось по истечению скажем 10кадров с начала движения стоит сделать часть параметров (как total) глобальными и накапливать в цикле?или какой то еще счетчик добавить в цикле в main? Какие будут предложения? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
executor 5 Жалоба Опубликовано March 9, 2011 Здравствуйте, 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/). Если вас интересует, я бы мог расписать более подробно, как я вижу эту задачу с подхода нейросетей. 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
virt 1 Жалоба Опубликовано March 10, 2011 Огромное спасибо за столь подробный ответ.Да меня интересует и это направление для данной программы.Мне конечно же хочется код попроще и поэффективнее,но любой совет выслушаю внимательно. Поэтому, может быть, целесообразно разделить 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% - это человек просто поднялся и ушел (например) ) Не подскажите можно ли где нибудь посмотреть такой пример реализации? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
kosmar 0 Жалоба Опубликовано April 5, 2012 Вопрос, как можно вычислить определить матрицы (A^T*A)в методе Лукаса-Канаде, если при подсчете даже в общем виде, он будет равен 0?? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано April 5, 2012 Не будет он равен нулю. Матлабу верите? >> 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] Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
kosmar 0 Жалоба Опубликовано April 6, 2012 Не будет он равен нулю. Матлабу верите? >> 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, Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах