Подсчёт объектов (людей), пересекающих линию (People counting)

advertisement
Подсчёт объектов (людей), пересекающих линию (People
counting)
Самый простейший путь при подсчёте объектов – это использование детектирования движений.
Например, используя ту же функцию update_mhi из примеров OpenCV. Собственно решение
напрашивается само – следить за выделяемыми областями движения, и как только происходит
пересечение заданной линии, то увеличивать значение счётчика. Однако функция update_mhi не
предназначена для слежения за объектами, поэтому эту часть придётся делать самостоятельно. На
рисунке 1 показано обнаруженные центра движений (а), и изменения положений центров движений
(б).
Рис. 1. Центры движений в кадре (а), изменение движений (b)
Красные центры – старое местоположение, чёрные – новое. Одной из красных точек не
соответствует чёрной, т.к. объект остановился и не двигается. R – максимальное расстояние, на
которое может сместиться объект за один кадр.
Для наблюдения за объектами будет использоваться следующая структура:
struct _OBJECT_
{
int x,y; //Координаты центра объекта
int w,h; //Ширина, высота объекта
int timer; //Задержка, позволяющая следить за объектом после остановки
int num; //Номер объекта
int object;//Соответствие с новым объектом
int inn; //Переменная, показывающая где находится объект относительно линии
http://recog.ru
Создание документа: 30 декабря 2011 (Кручинин Александр)
пересечения
}VObject[MAX_OBJECTS],BVObject[MAX_OBJECTS];
VObject – текущий массив объектов, BVObject – предыдущий массив объектом. При каждом
анализе детектируемых зон, необходимо сначала сохранить предыдущий массив, например так:
memcpy(BVObject,VObject,sizeof(_OBJECT_)*MAX_OBJECTS);
Если в предыдущем массиве нет ни одного объекта, то при анализе детектируемых зон можно
вызвать следующий листинг:
if (all_object<MAX_OBJECTS){
VObject[all_object].num=end_object;
VObject[all_object].timer=timer_1;
VObject[all_object].x=xx;
VObject[all_object].y=yy;
VObject[all_object].w=comp_rect.width;
VObject[all_object].h=comp_rect.height;
VObject[all_object].object=-1;
VObject[all_object].inn=2;
cur_object=all_object;
all_object++;
end_object++;
}
Листинг 1
Здесь, end_object – глобальный счётчик номеров объектов (всегда увеличивается); timer_1 –
максимальное время задержки, после которого объект, которому не соответствия движения,
уничтожается; xx, yy – текущие координаты центра движения; comp_rect – размер зоны движения.
Если от предыдущего кадра сохранились объекты, то необходимо проверять соответствие со
старыми объектами:
min=-1;
for(j=0;j<local_all_object;j++)
if (BVObject[j].object==-1)
{
dd=LengthLine(xx,yy,BVObject[j].x,BVObject[j].y);
if (dd<maxdist && (min==-1 || dd1>dd))
http://recog.ru
Создание документа: 30 декабря 2011 (Кручинин Александр)
{
min=j;
dd1=dd;
}
}
if (min==-1) {
VObject[all_object].num=end_object;
VObject[all_object].inn=2;
end_object++;
}
else {
VObject[all_object].num=BVObject[min].num;
VObject[all_object].inn=BVObject[min].inn;
BVObject[min].object=0;
}
VObject[all_object].timer=timer_1;
VObject[all_object].x=xx;
VObject[all_object].y=yy;
VObject[all_object].w=comp_rect.width;
VObject[all_object].h=comp_rect.height;
VObject[all_object].object=-1;
cur_object=all_object;
all_object++;
Листинг 2
Здесь, local_all_object – общее количество старых объектов. Если указатель ссылки на новый
объект (BVObject[j].object) равен -1, то сравнивается его удалённость с текущим объектом, если она
минимальна и меньше расстояния R, заданного переменной maxdist, то соответствие найдено. Если
соответствие не было найдено, то создаётся новый объект, иначе текущему объекту присваиваются
номера и положения относительно граничной линии старого объекта.
Определение пересечения линии достаточно просто – необходимо сравнивать значения inn
текущего и старого объекта. Определить inn относительно положения текущей линии можно по
следующему листингу:
float ang=MakePolarF(center.x-Center.x,center.y-Center.y);
http://recog.ru
Создание документа: 30 декабря 2011 (Кручинин Александр)
byte inn=0;
if ((ang>In_ && ang<In_+PI) || (In_>PI
&& ang<PI-In_)) {
inn=1;
}
if (VObject[cur_object].inn==0 && inn==1) All_In++;
if (VObject[cur_object].inn==1 && inn==0) {
All_Out++;
}
VObject[cur_object].inn=inn;
Листинг 3
Здесь, center – это центр области движения; Center – центр заданной нами линии; In_ - угол в
радианах вектора из центра линии в одну из сторон линии.
Этот метод прост и не лишён недостатков, возможно он не всегда работает
http://recog.ru
Создание документа: 30 декабря 2011 (Кручинин Александр)
Download