Skip to content

Commit ac652b0

Browse files
committed
add parallel biquad filter, add virtual screen threshold as parameter
1 parent de661de commit ac652b0

6 files changed

Lines changed: 55 additions & 33 deletions

File tree

GestureAlgos.cpp

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
#include <qglobal.h>
22
#include <QDebug>
33
#include "GestureAlgos.h"
4+
#include "VirtualTouchScreen.h"
45

56
GestureAlgos::GestureAlgos() :
67
screen_(0, 0),
78
image_(0,0),
89
scaleFactor_(0.0), offset_(0,0),
910
KF_(cv::KalmanFilter(8, 4, 0)),
10-
measurement_(cv::Mat_<float>(4,1))
11+
measurement_(cv::Mat_<float>(4,1)),
12+
mainWnd_(NULL)
1113
{
1214
}
1315

@@ -124,10 +126,12 @@ void GestureAlgos::initBiquad()
124126
sos_mat_[4][0] = 1.0, sos_mat_[4][1] = 2.0, sos_mat_[4][2] = 1.0, sos_mat_[4][3] = 1.0,
125127
sos_mat_[4][4] = 0.5304, sos_mat_[4][5] = 0.7165;
126128
gain_ = 0.0189;
127-
for (int n = 0; n < SosMat::NB_BIQUADS; ++n) {
128-
biquadState[n].index = n;
129-
memset(biquadState[n].mem_in, 0, sizeof(biquadState[n].mem_in));
130-
memset(biquadState[n].mem_out, 0, sizeof(biquadState[n].mem_out));
129+
for (int i = 0; i < 2; ++i) {
130+
for (int n = 0; n < SosMat::NB_BIQUADS; ++n) {
131+
biquadState[i][n].index = n;
132+
memset(biquadState[i][n].mem_in, 0, sizeof(biquadState[i][n].mem_in));
133+
memset(biquadState[i][n].mem_out, 0, sizeof(biquadState[i][n].mem_out));
134+
}
131135
}
132136
}
133137

@@ -148,7 +152,7 @@ double GestureAlgos::biquad(BiquadState *state, double in)
148152
return out;
149153
}
150154

151-
void GestureAlgos::filterLowPass(qreal &depth)
155+
void GestureAlgos::filterLowPass(qreal &depthThumb, qreal &depthIndex)
152156
{
153157
static bool initDone = false;
154158
if (!initDone) {
@@ -157,15 +161,15 @@ void GestureAlgos::filterLowPass(qreal &depth)
157161
}
158162
//cascade of biquads
159163
for (int n = 0; n < SosMat::NB_BIQUADS; ++n) {
160-
depth = biquad(biquadState+n, depth);
164+
depthThumb = biquad(&(biquadState[0][n]), depthThumb);
165+
depthIndex = biquad(&(biquadState[1][n]), depthIndex);
161166
}
162-
depth = gain_*depth;
167+
depthThumb = gain_*depthThumb;
168+
depthIndex = gain_*depthIndex;
163169
}
164170

165171
GestureAlgos::TouchType GestureAlgos::isTouch(qreal depthThumb, qreal depthIndex)
166172
{
167-
//constants
168-
const static qreal DEPTH_THRESHOLD = 0.45;
169173
//permanent variable
170174
static GestureAlgos::TouchType out = GestureAlgos::TouchType::NONE;
171175

@@ -177,9 +181,11 @@ GestureAlgos::TouchType GestureAlgos::isTouch(qreal depthThumb, qreal depthIndex
177181
}
178182

179183
//process depth information
180-
if ((DEPTH_THRESHOLD >= depthThumb) || (DEPTH_THRESHOLD >= depthIndex)) {
184+
if ((mainWnd_->virtualScreenThreshold_ >= depthThumb) ||
185+
(mainWnd_->virtualScreenThreshold_ >= depthIndex)) {
181186
//touch down
182-
out = ((DEPTH_THRESHOLD >= depthThumb) && (DEPTH_THRESHOLD >= depthIndex))?
187+
out = ((mainWnd_->virtualScreenThreshold_ >= depthThumb) &&
188+
(mainWnd_->virtualScreenThreshold_ >= depthIndex))?
183189
GestureAlgos::TouchType::DOUBLE_DOWN:GestureAlgos::TouchType::SINGLE_DOWN;
184190
} else {
185191
//touch up

GestureAlgos.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <QSize>
55
#include "opencv2/video/tracking.hpp"
66

7+
class VirtualTouchScreen;
8+
79
class GestureAlgos
810
{
911
public:
@@ -29,11 +31,14 @@ class GestureAlgos
2931
scaleFactor_ = scaleFactor;
3032
offset_ = offset;
3133
}
34+
void setMainWindow(const VirtualTouchScreen *w) {
35+
mainWnd_ = w;
36+
}
3237
//transforms to screen coordinates
3338
int imageToScreen(QPointF &pt);
3439
//filters
3540
int filterKalman(QPointF &ptThumb, QPointF &ptIndex);
36-
void filterLowPass(qreal &depth);
41+
void filterLowPass(qreal &depthThumb, qreal &depthIndex);
3742
//detect when the hand touches the virtual touch screen
3843
//the OS decides which gesture has been made
3944
enum TouchType {NONE = 0, SINGLE_DOWN, SINGLE_UP, DOUBLE_DOWN, DOUBLE_UP};
@@ -50,13 +55,14 @@ class GestureAlgos
5055
enum SosMat {NB_BIQUADS = 5};
5156
double sos_mat_[SosMat::NB_BIQUADS][6];
5257
double gain_;
53-
BiquadState biquadState[SosMat::NB_BIQUADS];
58+
BiquadState biquadState[2][SosMat::NB_BIQUADS];//two parallel biquad filters
5459
QSize screen_;
5560
QSize image_;
5661
qreal scaleFactor_;
5762
QPointF offset_;
5863
cv::KalmanFilter KF_;
5964
cv::Mat_<float> measurement_;
65+
const VirtualTouchScreen *mainWnd_;
6066
GestureAlgos(const GestureAlgos&);
6167
GestureAlgos& operator=(const GestureAlgos&);
6268
~GestureAlgos() {};

GestureThread.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,13 @@ void GestureThread::run()
134134
mainWnd->gestureAlgos->imageToScreen(mainWnd->handSkeletonPoints_[i]);
135135
depth[i] = static_cast<qreal>(fingerNode[i].positionWorld.y);
136136
}
137+
//Kalman filter for coordinates
137138
mainWnd->gestureAlgos->filterKalman(
138139
mainWnd->handSkeletonPoints_[VirtualTouchScreen::THUMB],
139140
mainWnd->handSkeletonPoints_[VirtualTouchScreen::INDEX]);
140141
mainWnd->skeletonPointMutex_.unlock();
141-
//TODO: low pass filter depth
142+
//low pass filter for the depth
143+
mainWnd->gestureAlgos->filterLowPass(depth[0], depth[1]);
142144

143145
//request finger position update
144146
emit moveIndex();

VirtualTouchScreen.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ VirtualTouchScreen::VirtualTouchScreen(QWidget *parent)
2222
thumbPointer(new QWidget()),
2323
config(NULL),
2424
handSkeletonPoints_(Hand::POINTS),
25-
touch_(new TouchInputEmulator())
25+
touch_(new TouchInputEmulator()),
26+
virtualScreenThreshold_(0.35)
2627
{
2728
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
2829
thumbPointer->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
@@ -41,6 +42,7 @@ VirtualTouchScreen::VirtualTouchScreen(QWidget *parent)
4142
gestureAlgos = GestureAlgos::instance();
4243
gestureAlgos->setScreenSize(QSize(geom.width(), geom.height()));
4344
gestureAlgos->setCorrectionFactors(scaleFactor, offset);
45+
gestureAlgos->setMainWindow(this);
4446

4547
//config = new ConfigDialog(NULL, this);//screen size must be set
4648

VirtualTouchScreen.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class VirtualTouchScreen : public QMainWindow
1919
Q_OBJECT
2020
friend class GestureThread;
2121
friend class ConfigDialog;
22+
friend class GestureAlgos;
2223
public:
2324
explicit VirtualTouchScreen(QWidget *parent = 0);
2425
~VirtualTouchScreen();
@@ -52,6 +53,7 @@ public slots:
5253
QVector<QPointF> handSkeletonPoints_;
5354
QMutex skeletonPointMutex_;
5455
TouchInputEmulator *touch_;
56+
qreal virtualScreenThreshold_;
5557
};
5658

5759
#endif // VirtualTouchScreen_H

tests/unit_tests.cpp

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,24 @@ private slots:
1717

1818
void TestGestureAlgos::imageToScreenFilterKalman()
1919
{
20-
/*GestureAlgos *algos = GestureAlgos::instance();
20+
GestureAlgos *algos = GestureAlgos::instance();
2121
QVERIFY(NULL != algos);
2222
QPointF pt(0, 0);
23-
QVERIFY(EXIT_FAILURE == algos->filterKalman(pt));
23+
QVERIFY(EXIT_FAILURE == algos->filterKalman(pt, pt));
2424
QVERIFY(EXIT_FAILURE == algos->imageToScreen(pt));
2525
algos->setScreenSize(QSize(1024, 768));
26-
QVERIFY(EXIT_SUCCESS == algos->filterKalman(pt));
26+
QVERIFY(EXIT_SUCCESS == algos->filterKalman(pt, pt));
2727
QVERIFY(EXIT_FAILURE == algos->imageToScreen(pt));
2828
algos->setImageSize(QSize(320, 240));
29-
QVERIFY(EXIT_SUCCESS == algos->filterKalman(pt));
29+
QVERIFY(EXIT_SUCCESS == algos->filterKalman(pt, pt));
3030
QVERIFY(EXIT_FAILURE == algos->imageToScreen(pt));
3131
algos->setCorrectionFactors(1.0, QPoint(0, 0));
32-
QVERIFY(EXIT_SUCCESS == algos->filterKalman(pt));
32+
QVERIFY(EXIT_SUCCESS == algos->filterKalman(pt, pt));
3333
pt.setX(0);
3434
pt.setY(0);
3535
QVERIFY(EXIT_SUCCESS == algos->imageToScreen(pt));
3636
QVERIFY(1024.0 == pt.x());
37-
QVERIFY(0.0 == pt.y());*/
37+
QVERIFY(0.0 == pt.y());
3838
}
3939

4040
void TestGestureAlgos::filterLowPass()
@@ -46,24 +46,28 @@ void TestGestureAlgos::filterLowPass()
4646
const static qreal PI = 3.1415926535;
4747
const static qreal TOL = 1e-3;
4848
int nbSamp = static_cast<int>(10/fn);
49-
qreal val = 0;
50-
qreal sum = 0;
49+
qreal val[] = {0,0};
50+
qreal sum[] = {0,0};
5151
for (int n = 0; n < nbSamp; ++n) {
52-
val = sin(2*PI*fn*n);
53-
algos->filterLowPass(val);
54-
sum += abs(val*val);
52+
val[0] = val[1] = sin(2*PI*fn*n);
53+
algos->filterLowPass(val[0], val[1]);
54+
sum[0] += abs(val[0]*val[0]);
55+
sum[1] += abs(val[1]*val[1]);
5556
}
56-
QVERIFY(fabs(48.5314 - sum) < TOL);
57+
QVERIFY(fabs(48.5314 - sum[0]) < TOL);
58+
QVERIFY(fabs(48.5314 - sum[1]) < TOL);
5759

5860
fn = 0.4;
5961
nbSamp = static_cast<int>(10/fn);
60-
sum = 0;
62+
sum[0] = sum[1] = 0;
6163
for (int n = 0; n < nbSamp; ++n) {
62-
val = sin(2*PI*fn*n);
63-
algos->filterLowPass(val);
64-
sum += abs(val*val);
64+
val[0] = val[1] = sin(2*PI*fn*n);
65+
algos->filterLowPass(val[0], val[1]);
66+
sum[0] += abs(val[0]*val[0]);
67+
sum[1] += abs(val[1]*val[1]);
6568
}
66-
QVERIFY(fabs(1.58709 - sum) < TOL);
69+
QVERIFY(fabs(1.58709 - sum[0]) < TOL);
70+
QVERIFY(fabs(1.58709 - sum[1]) < TOL);
6771
}
6872

6973
int TestGestureAlgos::getData(QVector<int> &x, QVector<int> &y, QVector<qreal> &depth,

0 commit comments

Comments
 (0)