Commit 0fcdfaba authored by Thiago Santini's avatar Thiago Santini

Adds per-session user defined maximum pupil size

parent 81e7af3b
......@@ -10,7 +10,6 @@ CameraWidget::CameraWidget(QString id, ImageProcessor::Type type, QWidget* paren
, ui(new Ui::CameraWidget)
, sROI(QPoint(0, 0))
, eROI(QPoint(0, 0))
, settingROI(false)
, lastUpdate(0)
, updateIntervalMs(80)
, maxAgeMs(300)
......@@ -118,8 +117,12 @@ CameraWidget::CameraWidget(QString id, ImageProcessor::Type type, QWidget* paren
connect(this, SIGNAL(newROI(QPointF, QPointF)),
imageProcessor, SIGNAL(newROI(QPointF, QPointF)));
connect(this, SIGNAL(newMaxRadius(double)),
imageProcessor, SIGNAL(newMaxRadius(double)));
// Initial roi
setROI(QPointF(0, 0), QPointF(1, 1));
emit newMaxRadius(0.0f);
QMetaObject::invokeMethod(camera, "loadCfg");
}
......@@ -191,8 +194,7 @@ void CameraWidget::preview(EyeData data)
ui->viewFinder->width() * data.coarseROI.br().x / static_cast<double>(data.input.cols),
ui->viewFinder->height() * data.coarseROI.br().y / static_cast<double>(data.input.rows))
};
eyeOverlay.drawOverlay(data, userROI, coarseROI, scaled);
eyeOverlay.drawOverlay(data, userROI, coarseROI, userMaxPupilRatio * data.input.rows, scaled);
ui->viewFinder->setPixmap(QPixmap::fromImage(scaled));
sendCameraCalibrationSample(data.input);
......@@ -224,7 +226,6 @@ void CameraWidget::preview(const DataTuple& data)
QImage scaled = previewImage(input);
fieldOverlay.drawOverlay(data, scaled);
;
ui->viewFinder->setPixmap(QPixmap::fromImage(scaled));
sendCameraCalibrationSample(input);
......@@ -303,46 +304,68 @@ void CameraWidget::stopRecording()
void CameraWidget::mousePressEvent(QMouseEvent* event)
{
if (ui->viewFinder->underMouse()) {
if (event->button() == Qt::LeftButton && type == ImageProcessor::Field)
emit newClick(gTimer.elapsed(), ui->viewFinder->mapFromGlobal(this->mapToGlobal(event->pos())), ui->viewFinder->size());
if (!ui->viewFinder->underMouse())
return;
if (event->button() == Qt::LeftButton && type == ImageProcessor::Field)
emit newClick(gTimer.elapsed(), ui->viewFinder->mapFromGlobal(this->mapToGlobal(event->pos())), ui->viewFinder->size());
if (event->button() == Qt::LeftButton && type == ImageProcessor::Eye) {
if (type == ImageProcessor::Eye) {
if (event->button() == Qt::LeftButton) {
sROI = ui->viewFinder->mapFrom(this, event->pos());
validatePoint(sROI);
sROI.setX(sROI.x() / ui->viewFinder->width());
sROI.setY(sROI.y() / ui->viewFinder->height());
eROI = sROI;
settingROI = true;
}
if (event->button() == Qt::RightButton) {
userMaxPupilRadius.setP1(ui->viewFinder->mapFrom(this, event->pos()));
userMaxPupilRadius.setP2(ui->viewFinder->mapFrom(this, event->pos()));
}
}
}
void CameraWidget::mouseMoveEvent(QMouseEvent* event)
{
if (ui->viewFinder->underMouse()) {
if (settingROI) {
if (!ui->viewFinder->underMouse())
return;
if (type == ImageProcessor::Eye) {
if (event->buttons() & Qt::LeftButton) {
eROI = ui->viewFinder->mapFrom(this, event->pos());
validatePoint(eROI);
eROI.setX(eROI.x() / ui->viewFinder->width());
eROI.setY(eROI.y() / ui->viewFinder->height());
}
if (event->buttons() & Qt::RightButton) {
userMaxPupilRadius.setP2(ui->viewFinder->mapFrom(this, event->pos()));
userMaxPupilRatio = userMaxPupilRadius.length() / ui->viewFinder->height();
}
}
}
void CameraWidget::mouseReleaseEvent(QMouseEvent* event)
{
if (event->button() == Qt::LeftButton && type == ImageProcessor::Eye) {
eROI = ui->viewFinder->mapFrom(this, event->pos());
validatePoint(eROI);
eROI.setX(eROI.x() / ui->viewFinder->width());
eROI.setY(eROI.y() / ui->viewFinder->height());
settingROI = false;
if (abs(sROI.x() - eROI.x()) < 0.1 || abs(sROI.y() - eROI.y()) < 0.1) {
sROI = QPointF();
eROI = QPointF();
if (type == ImageProcessor::Eye) {
if (event->button() == Qt::LeftButton) {
eROI = ui->viewFinder->mapFrom(this, event->pos());
validatePoint(eROI);
eROI.setX(eROI.x() / ui->viewFinder->width());
eROI.setY(eROI.y() / ui->viewFinder->height());
if (abs(sROI.x() - eROI.x()) < 0.1 || abs(sROI.y() - eROI.y()) < 0.1) {
sROI = QPointF();
eROI = QPointF();
}
setROI(sROI, eROI);
}
if (event->button() == Qt::RightButton) {
userMaxPupilRadius.setP2(ui->viewFinder->mapFrom(this, event->pos()));
userMaxPupilRatio = userMaxPupilRadius.length() / ui->viewFinder->height();
if (userMaxPupilRatio < 0.1)
userMaxPupilRatio = 0;
emit newMaxRadius(min(0.5, userMaxPupilRatio));
userMaxPupilRatio = 0; // reset so the overlay is not drawn anymore
}
setROI(sROI, eROI);
}
}
......
......@@ -6,6 +6,7 @@
#include <QAction>
#include <QCamera>
#include <QFont>
#include <QLineF>
#include <QMainWindow>
#include <QMessageBox>
#include <QMouseEvent>
......@@ -39,12 +40,13 @@ class CameraWidget : public ERWidget, InputWidget {
Q_OBJECT
public:
CameraWidget(QString id, ImageProcessor::Type type, QWidget* parent = 0);
~CameraWidget();
CameraWidget(QString id, ImageProcessor::Type type, QWidget* parent = nullptr);
~CameraWidget() override;
signals:
void setCamera(QCameraInfo cameraInfo);
void newROI(QPointF sROI, QPointF eROI);
void newMaxRadius(double maxRadius);
void newData(EyeData data);
void newData(FieldData data);
void newClick(Timestamp, QPoint, QSize);
......@@ -92,7 +94,6 @@ private:
void updateFrameRate(Timestamp t);
QPointF sROI, eROI;
bool settingROI;
void setROI(const QPointF& s, const QPointF& e)
{
sROI = s;
......@@ -100,6 +101,9 @@ private:
emit newROI(sROI, eROI);
}
QLineF userMaxPupilRadius;
double userMaxPupilRatio;
Timestamp lastUpdate;
Timestamp updateIntervalMs;
Timestamp maxAgeMs;
......
......@@ -9,8 +9,6 @@ EyeImageProcessor::EyeImageProcessor(QString id, QObject* parent)
: QObject(parent)
, cameraCalibration(nullptr)
, id(id)
, sROI(QPointF(0, 0))
, eROI(QPointF(1, 1))
, pupilDetectionMethod(nullptr)
, pupilTrackingMethod(nullptr)
{
......@@ -75,17 +73,18 @@ void EyeImageProcessor::process(Timestamp timestamp, const Mat& frame)
if (data.input.channels() > 1) // TODO: make it algorithm dependent
cvtColor(data.input, data.input, CV_BGR2GRAY);
float minPupilDiameterPx = cfg.minPupilDiameterRatio * min(data.input.rows, data.input.cols);
float maxPupilDiameterPx = cfg.maxPupilDiameterRatio * min(data.input.rows, data.input.cols);
float minPupilDiameterPx = cfg.minPupilDiameterRatio * data.input.rows;
float maxPupilDiameterPx = cfg.maxPupilDiameterRatio * data.input.rows;
data.pupil = Pupil();
data.validPupil = false;
if (pupilDetectionMethod != nullptr) {
Rect userROI = Rect(
Point(static_cast<int>(sROI.x() * data.input.cols),
static_cast<int>(sROI.y() * data.input.rows)),
Point(static_cast<int>(eROI.x() * data.input.cols),
static_cast<int>(eROI.y() * data.input.rows)));
Rect userROI = {
static_cast<int>(cfg.roi.x * data.input.cols),
static_cast<int>(cfg.roi.y * data.input.rows),
static_cast<int>(cfg.roi.width * data.input.cols),
static_cast<int>(cfg.roi.height * data.input.rows)
};
float scalingFactor = 1;
if (cfg.processingDownscalingFactor > 1)
......@@ -139,10 +138,18 @@ void EyeImageProcessor::newROI(QPointF sROI, QPointF eROI)
{
QMutexLocker locker(&cfgMutex);
if (sROI.isNull() || eROI.isNull()) {
this->sROI = QPointF(0, 0);
this->eROI = QPointF(1, 1);
cfg.roi = { 0.0f, 0.0f, 1.0f, 1.0f };
} else {
this->sROI = sROI;
this->eROI = eROI;
cfg.roi = {
static_cast<float>(min(sROI.x(), eROI.x())),
static_cast<float>(min(sROI.y(), eROI.y())),
static_cast<float>(abs(eROI.x() - sROI.x())),
static_cast<float>(abs(eROI.y() - sROI.y()))
};
}
}
void EyeImageProcessor::newMaxRadius(double maxRadius)
{
cfg.maxPupilDiameterRatio = 2 * maxRadius;
}
......@@ -96,8 +96,9 @@ public:
, processingDownscalingFactor(1)
, pupilDetectionMethod(PuRe::desc.c_str())
, tracking(true)
, minPupilDiameterRatio(0.f)
, maxPupilDiameterRatio(1.0f)
, roi(0.0f, 0.0f, 1.f, 1.f)
, minPupilDiameterRatio(0.0f)
, maxPupilDiameterRatio(0.0f)
{
}
......@@ -108,6 +109,8 @@ public:
double processingDownscalingFactor;
QString pupilDetectionMethod;
bool tracking;
// these are per session!
cv::Rect2f roi;
float minPupilDiameterRatio;
float maxPupilDiameterRatio;
......@@ -289,11 +292,11 @@ public slots:
void process(Timestamp t, const cv::Mat& frame);
void updateConfig();
void newROI(QPointF sROI, QPointF eROI);
void newMaxRadius(double maxRadius);
private:
QString id;
QMutex cfgMutex;
QPointF sROI, eROI;
std::shared_ptr<PupilDetectionMethod> pupilDetectionMethod;
std::shared_ptr<PupilTrackingMethod> pupilTrackingMethod;
......
......@@ -7,7 +7,7 @@ ImageProcessor::ImageProcessor(QString id, Type type, QObject* parent)
, eyeProcessor(nullptr)
, fieldProcessor(nullptr)
, eyeProcessorUI(nullptr)
, fieldProcessorUI(nullptr){
, fieldProcessorUI(nullptr) {
Q_UNUSED(parent)
}
......@@ -42,6 +42,8 @@ void ImageProcessor::create()
eyeProcessor, SLOT(process(Timestamp, const cv::Mat&)));
connect(this, SIGNAL(newROI(QPointF, QPointF)),
eyeProcessor, SLOT(newROI(QPointF, QPointF)));
connect(this, SIGNAL(newMaxRadius(double)),
eyeProcessor, SLOT(newMaxRadius(double)));
connect(this, SIGNAL(updateConfig()),
eyeProcessor, SLOT(updateConfig()));
......
......@@ -26,6 +26,7 @@ signals:
void process(Timestamp t, cv::Mat frame);
void showOptions(QPoint pos);
void newROI(QPointF sROI, QPointF eROI);
void newMaxRadius(double maxRadius);
void newData(EyeData data);
void newData(FieldData data);
void updateConfig();
......
......@@ -56,12 +56,29 @@ void EyeOverlay::drawPupil()
}
}
void EyeOverlay::drawOverlay(const EyeData& data, const QRectF& userROI, const QRectF& coarseROI, QPaintDevice& paintDevice)
void EyeOverlay::drawMaxPupil(const float maxPupilRadius)
{
if (maxPupilRadius <= 0)
return;
painter.setPen(QPen(QColor(255, 255, 0, alpha), refPx, Qt::DotLine));
painter.setBrush(Qt::NoBrush);
cv::RotatedRect pupil;
if (eyeData->pupil.confidence < minConfidence)
pupil.center = { 0.5f * eyeData->input.cols, 0.5f * eyeData->input.rows };
else
pupil.center = eyeData->pupil.center;
pupil.size = { 2 * maxPupilRadius, 2 * maxPupilRadius };
drawEllipse(pupil);
}
void EyeOverlay::drawOverlay(const EyeData& data, const QRectF& userROI, const QRectF& coarseROI, const float maxPupilRadius, QPaintDevice& paintDevice)
{
epilogue(data.input, paintDevice);
eyeData = &data;
drawROI(userROI, QColor(255, 255, 0, alpha));
drawROI(coarseROI, QColor(0, 255, 0, alpha));
drawMaxPupil(maxPupilRadius);
drawPupil();
prologue();
}
......
......@@ -26,16 +26,17 @@ protected:
QSizeF scale;
QFont font;
float refPx = 1;
float alpha = 0.75f * 255;
int alpha = static_cast<int>(0.75f * 255);
};
class EyeOverlay : private Overlay {
public:
void drawOverlay(const EyeData& data, const QRectF& roi, const QRectF& coarseROI, QPaintDevice& paintDevice);
void drawOverlay(const EyeData& data, const QRectF& roi, const QRectF& coarseROI, const float maxPupilRadius, QPaintDevice& paintDevice);
private:
EyeData const* eyeData;
void drawPupil();
void drawMaxPupil(const float maxPupilRadius);
float minConfidence = 0.66f;
};
......
......@@ -669,6 +669,7 @@ void PuRe::detect(Pupil& pupil)
// Scoring
sort(candidates.begin(), candidates.end());
PupilCandidate selected = candidates.back();
candidates.pop_back();
//for ( auto c = candidates.begin(); c != candidates.end(); c++)
// c->draw(dbg);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment