Jump to content
Compvision.ru

MD. KirkA

Пользователи
  • Content count

    19
  • Joined

  • Last visited

Community Reputation

0 Новичек

About MD. KirkA

  • Rank
    Бывалый
  1. Порадовала, спасибо.) А eigenface уже обсуждались?
  2. Мде, печально. Чувак убил кучу времени, причём он имел готовые базы из инета. То есть самому на собственных экспериментах в отдельно взятом помещении сделать такое практически нереально...( А были ли какие то источники самообучающихся программ по распознаванию? Или это из жанра фантастики?
  3. Есть ли обученные каскады для распознавания лица с углом около 45 градусов над лицом, т.е. если камера висит выше лица где-то на метр-полтора? И если нет, то дайте пожалуйста почитать литературу по обучению каскадов в opencv.
  4. Трекинг объектов.

    Спасибо.) Почитаю, сообщу о результатах.)
  5. Трекинг объектов.

    С августа текущего года начал программировать. С августа и решаю задачу подсчета посетителей. Сейчас нахожусь на этапе оптимизации программы. Не поленился и прочитал данную тему целиком. Жалко, что в ней так редко пишут, но надеюсь мой пост увидят и обсуждение не затянется на месяц, потому что нужен ваш совет - работаю один, и весьма тяжко без коллективного мышления. Выкладываю свои наработки не только потому, что нужен совет, а ещё и потому, что данный форум мне много раз помогал, хочу теперь и я как то помочь вам, поделиться своими соображениями. После прочтения темы первый вопрос - на кой черт располагать камеры сверху, если это подсчет посетителей. Обратите внимание на тот пример, где куча людей выделяется на улице. От расположения камеры очень многое зависит, в частности, использование каскадов. Поэтому в моем варианте камера располагается напротив входа, а не над ним. Для подсчета посетителей мною использовались несколько вариантов: 1.1 Я сам представлял кадр с камеры как матрицу коэффициентов свечения пикселей, потом пробовал пересчитывать смещение отдельных групп элементов. Не углубляясь в дальнейшее объяснение скажу, что это хрень получается, особенно, если делать это в одиночку. 1.2 Метод статичного фона из примеров опенцэвэ. Очень много шумов, нет границ объектов, да и вычленение отдельных объектов - задача практически невыполнимая, овчинка выделки не стоит. 2. Меня весьма спас метод кодовой книги (codebook). Действенная штука, шаблоны движения, всё такое. Но опять же - даже если подбирать определенные параметры среднестатистического человека и ставить ограничение по размерам движущихся областей с учетом масштаба и расстояния от камеры до объекта слежения - всё равно очень сильно косячит. В счетчике посетителей не должно быть деление одного объекта на два. Программа должна четко распознавать одного человека как один объект, и тут только один выход - третий пункт моих экспериментов, каскады 3. Каскады. В моём случае каскады Хаара, а именно распознавание лиц. Программа делает дополнительную фишечку - через область интересов распознанное каскадами лицо сохраняется в базу данных посетителей. Так вот на нем я и остановился. Теперь особенности разработки: в моем случае используются 6 IP камер от шведов (Axis). Быстродействие, даже с самым современным компьютером, тут играет огромную роль, поэтому сразу отбрасываю вариант использования Лукаса-Канаде, ибо он, по отзывам, жрет очень много ресурсов. Итак, есть лица или же upperbody\lowerbody. Проблема с подсчетом заключается только в трекинге. Реализация моего счетчика идет через пересечение объектом границы, проведенной через весь кадр горизонтально приблизительно посередине. В моем случае трекинг осуществляется покадровым методом, т.е. поиск признаков Хаара сам выдает прямоугольную область объекта, следовательно проблема моя только в том, что мне несколько раз при пересечении границы попадается один и тот же человек. Причем люди бывают разные - кто-то проходит данную границу шириной в 8 пикселей за один кадр, кто-то за три кадра ну и так далее. Следовательно, мои соображения сделать временнОй дедлайн для нахождения в кадре посетителя (это считается чисто логически - сколько здравомыслящий человек может простоять на входе в торговый центр, где люди обычно не задерживаются, а так же учитвать среднюю скорость движения человека и расстояние с учетом масштаба от верхнего края плоскости, по которой ходят посетители, до нижнего). Это определит максимальное количество кадров для работы "отсеивателя", который будет работать для уничтожения схожих объектов. Отсеиватель я сейчас думаю построить на SURF\SIFT, поскольку фактически для трех-пяти кадров проблема эта позволяет использовать область интересов лица и само лицо как плоский объект для вычленения похожих. Уважаемые знатоки, внимание, вопрос: я правильно думаю или мне надо думать в другую сторону?
  6. Шаблоны движения (motion templates)

    Помогите пожалуйста кто-нибудь...
  7. Шаблоны движения (motion templates)

    Вот пример функции update_mhi: void update_mhi1( IplImage* img, IplImage* dst, int diff_threshold, int sb4pos, int sb5pos) { double timestamp = (double)clock()/CLOCKS_PER_SEC; // get current time in seconds CvSize size = cvSize(img->width,img->height); // get current frame size int i, idx1 = last1, idx2; IplImage* silh=0; CvSeq* seq=0; CvRect comp_rect; double count; double angle; CvPoint center; double magnitude; CvScalar color; // number of cyclic frame buffer used for motion detection // (should, probably, depend on FPS) // allocate images at the beginning or // reallocate them if the frame size is changed if( !mhi1 || mhi1->width != size.width || mhi1->height != size.height ) { if( buf1 == 0 ) { buf1 = (IplImage**)malloc(N*sizeof(buf1[0])); memset( buf1, 0, N*sizeof(buf1[0])); } for( i = 0; i < N; i++ ) { cvReleaseImage( &buf1[i] ); buf1[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 ); cvZero( buf1[i] ); } cvReleaseImage( &mhi1 ); cvReleaseImage( &orient1 ); cvReleaseImage( &segmask1 ); cvReleaseImage( &mask1 ); mhi1 = cvCreateImage( size, IPL_DEPTH_32F, 1 ); cvZero( mhi1 ); // clear MHI at the beginning orient1 = cvCreateImage(size, IPL_DEPTH_32F, 1 ); segmask1 = cvCreateImage(size, IPL_DEPTH_32F, 1 ); mask1 = cvCreateImage(size, IPL_DEPTH_8U, 1 ); } cvCvtColor( img, buf1[last1], CV_BGR2GRAY ); // convert frame to grayscale idx2 = (last1 + 1) % N; // index of (last - (N-1))th frame last1 = idx2; silh = buf1[idx2]; cvAbsDiff( buf1[idx1], buf1[idx2], silh ); // get difference between frames cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY ); // and threshold it cvUpdateMotionHistory( silh, mhi1, timestamp, MHI_DURATION ); // update MHI // convert MHI to blue 8u image cvCvtScale( mhi1, mask1, 255./MHI_DURATION, (MHI_DURATION - timestamp)*255./MHI_DURATION ); cvZero( dst ); cvCvtPlaneToPix( mask1, 0, 0, 0, dst ); // calculate motion gradient orientation and valid orientation mask cvCalcMotionGradient( mhi1, mask1, orient1, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 ); if( !storage1 ) storage1 = cvCreateMemStorage(0); else cvClearMemStorage(storage1); // segment motion: get sequence of motion components // segmask is marked motion components map. It is not used further seq = cvSegmentMotion( mhi1, segmask1, storage1, timestamp, MAX_TIME_DELTA ); // iterate through the motion components, // One more iteration (i == -1) corresponds to the whole image (global motion) for( i = -1; i < seq->total; i++ ) { if( i < 0 ) { // case of the whole image comp_rect = cvRect( 0, 0, size.width, size.height ); color = CV_RGB(255,255,255); magnitude = 100; } else { // i-th motion component comp_rect = ((CvConnectedComp*)cvGetSeqElem( seq, i ))->rect; if( (comp_rect.width + comp_rect.height > sb4pos ) && (comp_rect.width + comp_rect.height < sb5pos) ) // reject very small and very big components continue; color = CV_RGB(0,255,0); magnitude = 100; } // select component ROI cvSetImageROI( silh, comp_rect ); cvSetImageROI( mhi1, comp_rect ); cvSetImageROI( orient1, comp_rect ); cvSetImageROI( mask1, comp_rect ); // calculate orientation angle = cvCalcGlobalOrientation( orient1, mask1, mhi1, timestamp,MHI_DURATION); //angle = 360.0 - angle; // adjust for images with top-left origin count = cvNorm( silh, 0, CV_L1, 0 ); // calculate number of points within silhouette ROI cvResetImageROI( mhi1 ); cvResetImageROI( orient1 ); cvResetImageROI( mask1 ); cvResetImageROI( silh ); // check for the case of little motion if( count < comp_rect.width*comp_rect.height * 0.05 ) continue; // draw a clock with arrow indicating the direction center = cvPoint( (comp_rect.x + comp_rect.width/2),(comp_rect.y + comp_rect.height/2) ); cvCircle( dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0 ); cvLine( dst, center, cvPoint( cvRound( center.x + magnitude*cos(angle*CV_PI/180)), cvRound( center.y - magnitude*sin(angle*CV_PI/180))), color, 3, CV_AA,0 ); cvLine(dst,cvPoint(0,trackleft1pos),cvPoint(640, trackright1pos), color, 2, CV_AA,0); if (onkey) if (((center.x*k1+trackleft1pos<center.y+2)&&((center.x*k1+trackleft1pos>center.y-2)))&&(angle>-1)&&(angle<181)) {incount1++; allcount=allcount++;} if (onkey) if (((center.x*k1+trackleft1pos<center.y+2)&&((center.x*k1+trackleft1pos>center.y-2)))&&(angle>180)&&(angle<360)) {outcount1++; allcount=allcount++;} } }
  8. Шаблоны движения (motion templates)

    А куда смотреть то конкретно? Лучше один раз увидеть, поэтому... В прикрепленном: проект под OpenCV 2.4 в MVS 2010 6 реализаций update_mhi в отдельности для каждой камеры. Вызов функции из первого таймера. Работает с файлом 18.avi, производит сохранение на D:\ Вот целиком проект: Скачать (~350Mb) Скачать с другого файлообменника (~350Mb)
  9. Шаблоны движения (motion templates)

    По данному сабжу возникла проблема. При использовании update_mhi потребовалось изменять размеры захватываемых объектов в пикселях. Причина в том, что на одном и том же человеке (речь об алгоритме пересечения границы) выделяются от двух и более точек движения. Идея в том, чтобы ограничить comp_rect, чтобы не менее 100 пикселей и не более 300 пикселей. конкретно в этом условии стандартной функции: if( (comp_rect.width + comp_rect.height > sb4pos ) && (comp_rect.width + comp_rect.height < sb5pos) ) Проблема в том, что возвращаемое значение comp_rect.width превышает 3 миллиона, а comp_rect.height=1920. Вопрос: почему так происходит и что необходимо исправить, чтобы всё заработало?
  10. Проблема с динамической памятью

    Нежданчик. Проблема решена. Дело в таймере и создании новых и новых утечек. update_mhi, draw_data и файловые потоки ни при чем.
  11. Проблема с динамической памятью

    попробую. Но моя проблема пока что актуальна.
  12. Проблема с динамической памятью

    присвоение нулевых значений для silh и seq тоже результата не дало. всё по прежнему печально
  13. Проблема с динамической памятью

    Изначально storage1=0. Если ставить storage1=0 после очистки ClearMemStorage, то программа вылетает сразу же.
  14. Проблема с динамической памятью

    Прилинковано всё по мануалу - для Release opencv_*242.dll, для Debug opencv_*242d.dll. В остальных соображениях по инициализации разберусь по прибытию на работу, попробую...
  15. Проблема появилась при разработке проекта в финальной его стадии. После 6,5 минут программа вылетает с повреждением стека. Последний кадр стека указывает на использование хранилища памяти типа CvMemStorage в функции update_mhi1 где то тут: cvCalcMotionGradient( mhi1, mask1, orient1, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 ); if( !storage1 ) storage1 = cvCreateMemStorage(0); else cvClearMemStorage(storage1); Долго искал соответствующую тему - так и не нашел. Пожалуйста, помогите. З.Ы.: в прикрепленном файле листинг (Visual C++, MS VS 2010 с использованием MFC и OpenCV 2.4.2). Для его создания использовалось руководство от Smorodov и maximator по OpenCV+MFC (без использования потоков, но с таймером) + книга O'Reilly и пример по кодовой книге (update_mhi). Ошибка возникает при Release версии, при Debug может и не вылезти. Но тут, как понимаете, итоговой программы не будет без Release. code-cpp.txt
×