Permalink
Browse files

re-implement vBlobTracker

  • Loading branch information...
1 parent fcc352c commit b5c750b053621b22e6935fd00815026d9fc4fa0f @vinjn vinjn committed Feb 12, 2012
View
@@ -9,4 +9,23 @@ OSC and TUIO protocol is employed to send reconginzed blob/face information to c
It now supports Kinect and PS3 Camera.
The tutorials are provided at [here](http://www.everbox.com/f/bwy7u4c3xDkmKpKMbtTWu7ojqR)
-But it's a little bit outdated.
+But it's a little bit outdated.
+
+使用说明
+
+CamServer.exe [-i camera/image/video] [-dos] [-log] [-minim] [-delay 5] [-client 192.168.1.122 ][-port 3333] [-face]
+
+第一个参数,可以是
+camera 摄像头的编号,默认为0,即第一个摄像头,同时支持使用CLEye驱动的ps3摄像头
+image 图片路径
+video 视频文件的路径
+如果不指定,则打开第一个摄像头
+
+-client 192.168.1.122 指定客户端的地址,默认为localhost,即本机地址
+-port 3333 指定客户端的端口,默认为3333
+-face 1.5 人脸识别功能,默认不开启,可指定放缩比例(比例未实现)
+-finger 手指识别功能,默认不开启
+-hand 手指识别功能,默认不开启,未实现
+-minim 启动时为程序最小化
+-delay 5 延迟5秒后再运行
+-log 在文件中记录运行状况,默认不适用
View
@@ -1,16 +0,0 @@
-CamServer.exe [-i #camera/image/video] [-dos] [-log] [-minim] [-delay 5] [-client 192.168.1.122 ][-port 3333] [-face]
-
-第一个参数,可以是
-#camera 摄像头的编号,默认为0,即第一个摄像头
-image 图片路径
-video 视频文件的路径
-如果不指定,则打开第一个摄像头
-
--client 192.168.1.122 指定客户端的地址,默认为localhost,即本机地址
--port 3333 指定客户端的端口,默认为3333
--face 1.5 人脸识别功能,默认不开启,可指定放缩比例(比例未实现)
--finger 手指识别功能,默认不开启
--hand 手指识别功能,默认不开启,未实现
--minim 启动时为程序最小化
--delay 5 延迟5秒后再运行
--log 在文件中记录运行状况,默认不适用
@@ -27,8 +27,7 @@ namespace monitor_gui
if(theConfig.fixed_back_mode && Event == CV_EVENT_RBUTTONUP)
{
theApp.onRefreshBack();
- theConfig.bg_mode = REAL_BG;
- param_gui::update();
+ param_gui::on_realbg();
}
else
if( Event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON) )
@@ -303,5 +302,6 @@ namespace param_gui
{
cvDestroyWindow(PARAM_WINDOW);
}
+ update();
}
}
View
@@ -26,6 +26,6 @@ namespace param_gui
void show(bool visible);
void init();
- void on_realbg(int);
+ void on_realbg(int = 0);
}
@@ -270,7 +270,7 @@ void VideoApp::send_custom_msg()
}
//object
- vector<vTrackedBlob>* pTrackBlobs[] = {&blobTracker.trackedBlobs, &blobTracker.leaveBlobs};
+ vector<vTrackedBlob>* pTrackBlobs[] = {&blobTracker.trackedBlobs, &blobTracker.deadBlobs};
for (int v=0;v<2;v++)
{
vector<vTrackedBlob>* pTb = pTrackBlobs[v];
@@ -368,11 +368,11 @@
Name="doc"
>
<File
- RelativePath="..\..\doc\manual.txt"
+ RelativePath="..\..\doc\osc_protocol.txt"
>
</File>
<File
- RelativePath="..\..\doc\osc_protocol.txt"
+ RelativePath="..\..\..\README.md"
>
</File>
<File
@@ -116,7 +116,7 @@ struct vTrackedBlob : public vBlob
{
enum
{
- BLOB_UN_NAMED = -3,
+ BLOB_NEW_ID = -3,
BLOB_TO_DELETE = -2,
};
@@ -133,20 +133,14 @@ struct vTrackedBlob : public vBlob
vector<int> neighbors; // ids of the closest points, sorted
vTrackedBlob():vBlob() {
- id = BLOB_UN_NAMED;
+ id = BLOB_NEW_ID;
status = statusStill;
markedForDeletion = false;
framesLeft = 0;
}
vTrackedBlob( const vBlob& b ):vBlob(b) {
- area = b.area;
- // box = b.box;
- // center = b.center;
- isHole = b.isHole;
- // pts = b.pts;
-
- id = BLOB_UN_NAMED;
+ id = BLOB_NEW_ID;
status = statusStill;
markedForDeletion = false;
framesLeft = 0;
@@ -165,6 +159,11 @@ struct vTrackedBlob : public vBlob
else return "";
}
+ bool isDead() const
+ {
+ return id == BLOB_TO_DELETE;
+ }
+
int getMinDistance() {
int best=-1;
float best_v=99999.0f;
@@ -1,18 +1,21 @@
#include "BlobTracker.h"
#include "point2d.h"
#include <list>
+#include <functional>
#if defined _DEBUG
#pragma comment(lib,"opencv_video232d.lib")
#pragma comment(lib,"opencv_objdetect232d.lib")
+#pragma comment(lib,"opencv_features2d232d.lib")
#else
#pragma comment(lib,"opencv_video232.lib")
#pragma comment(lib,"opencv_objdetect232.lib")
+#pragma comment(lib,"opencv_features2d232.lib")
#endif
using namespace cv;
-//Just some convienience macros
+//Just some convenient macros
#define CV_CVX_WHITE CV_RGB(0xff,0xff,0xff)
#define CV_CVX_BLACK CV_RGB(0x00,0x00,0x00)
@@ -268,7 +271,7 @@ bool vFingerDetector::findFingers (const vBlob& blob, int k/* = 10*/)
for(int i=k; i<nPts-k; i++)
{
- //calculating angre between vectors
+ //calculating angles between vectors
v1.set(blob.pts[i].x-blob.pts[i-k].x, blob.pts[i].y-blob.pts[i-k].y);
v2.set(blob.pts[i].x-blob.pts[i+k].x, blob.pts[i].y-blob.pts[i+k].y);
@@ -547,9 +550,9 @@ vBlobTracker::vBlobTracker()
}
//assigns IDs to each blob in the contourFinder
-void vBlobTracker::trackBlobs(const vector<vBlob>& _newBlobs)
+void vBlobTracker::trackBlobs2(const vector<vBlob>& _newBlobs)
{
- leaveBlobs.clear();
+ deadBlobs.clear();
vector<vTrackedBlob> newBlobs;
int nNewBlobs = _newBlobs.size();
@@ -580,7 +583,7 @@ void vBlobTracker::trackBlobs(const vector<vBlob>& _newBlobs)
{
//if winning new blob was labeled winner by another track\
//then compare with this track to see which is closer
- if(newBlobs[winner].id != vTrackedBlob::BLOB_UN_NAMED)
+ if(newBlobs[winner].id != vTrackedBlob::BLOB_NEW_ID)
{
//find the currently assigned blob
int j; //j will be the index of it
@@ -678,7 +681,7 @@ void vBlobTracker::trackBlobs(const vector<vBlob>& _newBlobs)
//have ID of -1... if the ID is -1... we need to make a new track
for(int i=0; i<nNewBlobs; i++)
{
- if(newBlobs[i].id == vTrackedBlob::BLOB_UN_NAMED)
+ if(newBlobs[i].id == vTrackedBlob::BLOB_NEW_ID)
{
//add new track
newBlobs[i].id=IDCounter++;
@@ -800,11 +803,94 @@ void vBlobTracker::doBlobMoved( vTrackedBlob& b ) {
void vBlobTracker::doBlobOff( vTrackedBlob& b ) {
b.status = statusLeave;
- leaveBlobs.push_back(b);
+ deadBlobs.push_back(b);
printf("blob: %d leave-\n" , b.id);
b.id = vTrackedBlob::BLOB_TO_DELETE;
}
+void vBlobTracker::trackBlobs( const vector<vBlob>& newBlobs )
+{
+ deadBlobs.clear();
+ const int n_old = trackedBlobs.size();
+ const int n_new = newBlobs.size();
+ vector<vTrackedBlob> newTrackedBlobs(n_new);
+ std::copy(newBlobs.begin(), newBlobs.end(), newTrackedBlobs.begin());
+
+ vector<int> nn_of_a(n_old);//nearest neighbor of pta in ptb
+ vector<int> dist_of_a(n_old);//nearest neighbor of pta in ptb
+ fill(nn_of_a.begin(), nn_of_a.end(),-1);
+ fill(dist_of_a.begin(), dist_of_a.end(),INT_MAX);
+
+ if (n_old != 0 && n_new != 0)
+ {
+ Mat ma(trackedBlobs.size(),2,CV_32SC1);
+ Mat mb(newBlobs.size(),2,CV_32SC1);
+ for (int i=0;i<n_old;i++)
+ {
+ ma.at<int>(i,0) = trackedBlobs[i].center.x;
+ ma.at<int>(i,1) = trackedBlobs[i].center.y;
+ }
+ for (int i=0;i<n_new;i++)
+ {
+ mb.at<int>(i,0) = newTrackedBlobs[i].center.x;
+ mb.at<int>(i,1) = newTrackedBlobs[i].center.y;
+ }
+
+ BruteForceMatcher<L2<int> > matcher;
+ vector<DMatch> matches;
+ matcher.match(mb, ma, matches);
+ const int n_matches = matches.size();
+ for (int i=0;i<n_matches;i++)
+ {
+ const DMatch& match = matches[i];
+ int t_id = match.trainIdx;
+ int q_id = match.queryIdx;
+ float dist = match.distance;
+
+ if (dist < 500 && dist < dist_of_a[t_id])
+ {
+ dist_of_a[t_id] = dist;
+ nn_of_a[t_id] = q_id;
+ }
+ }
+ }
+
+ for (int i=0;i<n_old;i++)
+ {
+ int nn = nn_of_a[i];
+ if (nn != -1)
+ {//moving blobs
+ Point2f lastCenter = trackedBlobs[i].center;
+ newTrackedBlobs[nn].id = trackedBlobs[i].id;//save id, cause we will overwrite the data
+ trackedBlobs[i] = newTrackedBlobs[nn];//update with new data
+ trackedBlobs[i].velocity.x = newBlobs[nn].center.x - lastCenter.x;
+ trackedBlobs[i].velocity.y = newBlobs[nn].center.y - lastCenter.y;
+ doBlobMoved(trackedBlobs[i]);
+ }
+ else
+ {//leaving blobs
+ doBlobOff(trackedBlobs[i]);
+ }
+ }
+ trackedBlobs.erase(remove_if(trackedBlobs.begin(), trackedBlobs.end(), std::mem_fun_ref(&vTrackedBlob::isDead)),
+ trackedBlobs.end());
+ //entering blobs
+ for(int i=0; i<n_new; i++)
+ {
+ if (newTrackedBlobs[i].id == vTrackedBlob::BLOB_NEW_ID)
+ {
+ //add new track
+ if (IDCounter > UINT_MAX)
+ IDCounter = 0;
+ newTrackedBlobs[i].id=IDCounter++;
+ trackedBlobs.push_back(newTrackedBlobs[i]);
+
+ //SEND BLOB ON EVENT
+ doBlobOn( trackedBlobs.back());
+ }
+ }
+}
+
CvFGDStatModelParams cvFGDStatModelParams()
{
CvFGDStatModelParams p;
@@ -53,14 +53,15 @@ class vBlobTracker
vBlobTracker();
//assigns IDs to each blob in the contourFinder
+ void trackBlobs2(const vector<vBlob>& newBlobs);
void trackBlobs(const vector<vBlob>& newBlobs);
std::vector<vTrackedBlob> trackedBlobs; //tracked blobs
- std::vector<vTrackedBlob> leaveBlobs;
+ std::vector<vTrackedBlob> deadBlobs;
private:
int trackKnn(const vector<vTrackedBlob>& newBlobs, vTrackedBlob& track, int k, double thresh=0);
- int IDCounter; //counter of last blob
+ unsigned int IDCounter; //counter of last blob
protected:

0 comments on commit b5c750b

Please sign in to comment.