From abde56fca47254e437c8b619729044c7fcbd2a5e Mon Sep 17 00:00:00 2001 From: MPIBR-kretschmerf Date: Wed, 23 Nov 2016 11:57:33 +0100 Subject: [PATCH] First working version --- NotifyingQGraphicsRectItem.h | 20 ++ TrackerPlugin_PupilDiam.cpp | 280 +++++++++++++++++++++++ TrackerPlugin_PupilDiam.h | 95 ++++++++ TrackerPlugin_PupilDiam.pro | 38 ++++ TrackerPlugin_PupilDiam.ui | 416 +++++++++++++++++++++++++++++++++++ TrackerWorker.cpp | 149 +++++++++++++ TrackerWorker.h | 48 ++++ TrackingResults.h | 14 ++ 8 files changed, 1060 insertions(+) create mode 100644 NotifyingQGraphicsRectItem.h create mode 100644 TrackerPlugin_PupilDiam.cpp create mode 100644 TrackerPlugin_PupilDiam.h create mode 100644 TrackerPlugin_PupilDiam.pro create mode 100644 TrackerPlugin_PupilDiam.ui create mode 100644 TrackerWorker.cpp create mode 100644 TrackerWorker.h create mode 100644 TrackingResults.h diff --git a/NotifyingQGraphicsRectItem.h b/NotifyingQGraphicsRectItem.h new file mode 100644 index 0000000..35b9c79 --- /dev/null +++ b/NotifyingQGraphicsRectItem.h @@ -0,0 +1,20 @@ +#ifndef NOTIFYINGQGRAPHICSRECTITEM_H +#define NOTIFYINGQGRAPHICSRECTITEM_H + +#include + +class NotifyingQGraphicsRectItem : public QObject, public QGraphicsRectItem +{ + Q_OBJECT +protected: + QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { + if (change == ItemPositionHasChanged){ + emit itemMoved(); + } + return QGraphicsRectItem::itemChange(change, value); + } +signals: + void itemMoved(); +}; + +#endif // NOTIFYINGQGRAPHICSRECTITEM_H diff --git a/TrackerPlugin_PupilDiam.cpp b/TrackerPlugin_PupilDiam.cpp new file mode 100644 index 0000000..74f7914 --- /dev/null +++ b/TrackerPlugin_PupilDiam.cpp @@ -0,0 +1,280 @@ +#include "TrackerPlugin_PupilDiam.h" + +TrackerPlugin_PupilDiam::TrackerPlugin_PupilDiam(QObject *parent) +{ + ui = new Ui::TrackerPlugin_PupilDiam; + trackerWorker = new TrackerWorker(); + ui->setupUi(this); + + pixmapItem = new QGraphicsPixmapItem(); + + plotPens.push_back(new QPen(Qt::green)); + plotPens.push_back(new QPen(Qt::green)); + plotPens.push_back(new QPen(Qt::magenta)); + plotPens.push_back(new QPen(Qt::magenta)); + plotPens.push_back(new QPen(QColor(127,127,255))); + + for(int i =0;isetWidth(2); + } + + rectPens.push_back(new QPen(Qt::green)); + rectPens.push_back(new QPen(Qt::magenta)); + + for(int i =0;isetWidth(5); + } + + //uiPlots = new QVector(); + uiPlots.push_back(ui->qwtPlot_1); + uiPlots.push_back(ui->qwtPlot_2); + uiPlots.push_back(ui->qwtPlot_3); + uiPlots.push_back(ui->qwtPlot_4); + uiPlots.push_back(ui->qwtPlot_5); + + uiSliders.push_back(ui->Slider_1); + uiSliders.push_back(ui->Slider_2); + + uiSliders_Size.push_back(ui->Slider_Size_1); + uiSliders_Size.push_back(ui->Slider_Size_2); + + + uiLineEdits.push_back(ui->lineEdit_PupilMinArea); + uiLineEdits.push_back(ui->lineEdit_PupilMaxArea); + uiLineEdits.push_back(ui->lineEdit_CorneaMinArea); + uiLineEdits.push_back(ui->lineEdit_CorneaMaxArea); + + /*Position signalmapper*/ + signalMapperPosition = new QSignalMapper(this); + + uiPlots.at(0)->setAxisTitle(0, "Pupil x [px]"); + uiPlots.at(1)->setAxisTitle(0, "Pupil y [px]"); + uiPlots.at(2)->setAxisTitle(0, "Cornea x [px]"); + uiPlots.at(3)->setAxisTitle(0, "Cornea y [px]"); + uiPlots.at(4)->setAxisTitle(0, "Pupil diam [px]"); + + + /*Prepare rects*/ + for(int i=0;i<2;i++){ + rectItems.push_back(new NotifyingQGraphicsRectItem()); + rectItems.at(i)->setRect(QRect(0,0,maxRectWidth,maxRectWidth)); + rectItems.at(i)->setPen(*rectPens.at(i)); + rectItems.at(i)->setFlag(QGraphicsItem::ItemIsMovable, true); + rectItems.at(i)->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); + /*Signalmapper position*/ + connect(rectItems.at(i), SIGNAL(itemMoved()), signalMapperPosition, SLOT(map())); + signalMapperPosition->setMapping(rectItems.at(i), i); + } + connect(signalMapperPosition, SIGNAL(mapped(int)), this, SLOT(onItemPositionChanged(int))); + + + /*Prepare curves*/ + for(int i=0;isetPen(*plotPens.at(i)); + curves.at(i)->setRenderHint( QwtPlotItem::RenderAntialiased ); + rectData.push_back(new QwtPointSeriesData); + rectSamples.push_back(new QVector); + curves.at(i)->attach(uiPlots.at(i)); + } + + /*Checkboxes signalmapper*/ + signalMapperCheckBoxes = new QSignalMapper(this); + /*Connect checkboxes and sliders*/ + connect(ui->checkBox_1, SIGNAL(clicked()), signalMapperCheckBoxes, SLOT(map())); + connect(ui->checkBox_2, SIGNAL(clicked()), signalMapperCheckBoxes, SLOT(map())); + connect(ui->checkBox_3, SIGNAL(clicked()), signalMapperCheckBoxes, SLOT(map())); + connect(ui->checkBox_4, SIGNAL(clicked()), signalMapperCheckBoxes, SLOT(map())); + connect(ui->checkBox_5, SIGNAL(clicked()), signalMapperCheckBoxes, SLOT(map())); + signalMapperCheckBoxes->setMapping(ui->checkBox_1, 0); + signalMapperCheckBoxes->setMapping(ui->checkBox_2, 1); + signalMapperCheckBoxes->setMapping(ui->checkBox_3, 2); + signalMapperCheckBoxes->setMapping(ui->checkBox_4, 3); + signalMapperCheckBoxes->setMapping(ui->checkBox_5, 4); + connect(signalMapperCheckBoxes, SIGNAL(mapped(int)), this, SLOT(onCheckBoxClicked(int))); + + /*Sliders signalmapper*/ + signalMapperSliders = new QSignalMapper(this); + /*Connect checkboxes and sliders*/ + connect(ui->Slider_1, SIGNAL(sliderMoved(double)), signalMapperSliders, SLOT(map())); + connect(ui->Slider_2, SIGNAL(sliderMoved(double)), signalMapperSliders, SLOT(map())); + signalMapperSliders->setMapping(ui->Slider_1, 0); + signalMapperSliders->setMapping(ui->Slider_2, 1); + connect(signalMapperSliders, SIGNAL(mapped(int)), this, SLOT(onThreshSliderMoved(int))); + + /*Sliders Size signalmapper*/ + signalMapperSliders_Size = new QSignalMapper(this); + /*Connect checkboxes and sliders*/ + connect(ui->Slider_Size_1, SIGNAL(sliderMoved(double)), signalMapperSliders_Size, SLOT(map())); + connect(ui->Slider_Size_2, SIGNAL(sliderMoved(double)), signalMapperSliders_Size, SLOT(map())); + signalMapperSliders_Size->setMapping(ui->Slider_Size_1, 0); + signalMapperSliders_Size->setMapping(ui->Slider_Size_2, 1); + connect(signalMapperSliders_Size, SIGNAL(mapped(int)), this, SLOT(onSizeSliderMoved(int))); + + /*LineEdit signalmapper*/ + /*The signalmapper is an overkill at this point but since we used them for everything else, we'll stick to them for now*/ + signalMapperLineEdit = new QSignalMapper(this); + connect(ui->lineEdit_PupilMinArea, SIGNAL(editingFinished()), signalMapperLineEdit, SLOT(map())); + connect(ui->lineEdit_PupilMaxArea, SIGNAL(editingFinished()), signalMapperLineEdit, SLOT(map())); + connect(ui->lineEdit_CorneaMinArea, SIGNAL(editingFinished()), signalMapperLineEdit, SLOT(map())); + connect(ui->lineEdit_CorneaMaxArea, SIGNAL(editingFinished()), signalMapperLineEdit, SLOT(map())); + signalMapperLineEdit->setMapping(ui->lineEdit_PupilMinArea, 0); + signalMapperLineEdit->setMapping(ui->lineEdit_PupilMaxArea, 1); + signalMapperLineEdit->setMapping(ui->lineEdit_CorneaMinArea, 2); + signalMapperLineEdit->setMapping(ui->lineEdit_CorneaMaxArea, 3); + connect(signalMapperLineEdit, SIGNAL(mapped(int)), this, SLOT(onAreaConstraintsEditingFinished(int))); + + QIntValidator *intValidator = new QIntValidator(0, 2147483647 ,this); + ui->lineEdit->setValidator(intValidator); + + + /*Connection TrackingGui - TrackingWorker*/ + connect(this, SIGNAL(thresholdChanged(int, int)), trackerWorker, SLOT(onThresholdChanged(int, int))); +// //connect(ui->widget_trackingGui, SIGNAL(roiChanged(int, QRectF)), trackingWorker, SLOT(onRoisChanged(int, QRectF))); + connect(this, SIGNAL(posChanged(int, QPoint)), trackerWorker, SLOT(onPosChanged(int, QPoint))); + connect(this, SIGNAL(sizeChanged(int, QSize)), trackerWorker, SLOT(onSizeChanged(int, QSize))); + connect(this, SIGNAL(areaContraintsChanged(int,int)), trackerWorker, SLOT(onAreaConstraintsChanged(int,int))); + connect(ui->checkBox_showBinary, SIGNAL(clicked(bool)), trackerWorker, SLOT(onShowBinary(bool))); +// connect(trackerWorker, SIGNAL(trackingResult(QVector)), this, SLOT(onTrackingResult(QVector))); + connect(trackerWorker, SIGNAL(trackingResult(TrackingResults)), this, SLOT(onTrackingResult(TrackingResults))); +} + +QObject *TrackerPlugin_PupilDiam::worker() +{ + return trackerWorker; +} + +void TrackerPlugin_PupilDiam::initializeUI(QLayout *layout, QGraphicsScene *cameraScene, QSize cameraResolution) +{ + this->cameraResolution = cameraResolution; + layout->addWidget(this); + this->cameraScene = cameraScene; + + for(int i=0;icameraScene->addItem(rectItems.at(i)); + + emit(thresholdChanged(i, uiSliders.at(i)->value())); + emit(sizeChanged(i, QSize(rectItems.at(i)->rect().width(), rectItems.at(i)->rect().height()))); + emit(posChanged(i, QPoint(rectItems.at(i)->pos().rx(),rectItems.at(i)->pos().ry()))); + } + + /*Resize rectangles according to the correct size*/ + if(cameraResolution.width()>cameraResolution.height()){ + this->maxRectWidth = cameraResolution.height()/2; + }else{ + this->maxRectWidth = cameraResolution.width()/2; + } + for(int i=0;isetRect(QRect(0,0,maxRectWidth,maxRectWidth)); + } +} + + + +void TrackerPlugin_PupilDiam::onTrackingResult(TrackingResults result) +{ + int nPlots = 5; + + /*window is full - stop */ + if(frameCount>wndLength){ + for(int i=0;ipop_front(); + } + } + + rectSamples.at(0)->push_back(QPointF(t, result.cPupil.x)); + rectSamples.at(1)->push_back(QPointF(t, result.cPupil.y)); + rectSamples.at(2)->push_back(QPointF(t, result.cCornea.x)); + rectSamples.at(3)->push_back(QPointF(t, result.cCornea.y)); + rectSamples.at(4)->push_back(QPointF(t, result.pDiam)); + + + for(int i = 0; i< nPlots; i++){ + rectData.at(i)->setSamples(*rectSamples.at(i)); + curves.at(i)->setData(rectData.at(i)); + } + + ui->qwtPlot_1->replot(); + ui->qwtPlot_2->replot(); + ui->qwtPlot_3->replot(); + ui->qwtPlot_4->replot(); + ui->qwtPlot_5->replot(); + t++; + frameCount++; + +} + + +void TrackerPlugin_PupilDiam::onCheckBoxClicked(int index) +{ + + bool isVisible = !uiPlots.at(index)->isVisible(); + + switch ( index ){ + case 0: + rectItems.at(index)->setVisible(isVisible); + uiSliders.at(index)->setVisible(isVisible); + uiSliders_Size.at(index)->setVisible(isVisible); + break; + case 2: + rectItems.at(1)->setVisible(isVisible); + uiSliders.at(1)->setVisible(isVisible); + uiSliders_Size.at(1)->setVisible(isVisible); + break; + } + + + uiPlots.at(index)->setVisible(isVisible); + + + +} + +void TrackerPlugin_PupilDiam::onThreshSliderMoved(int index) +{ + float value = uiSliders.at(index)->value(); + emit(thresholdChanged(index, value)); +} + +void TrackerPlugin_PupilDiam::onSizeSliderMoved(int index) +{ + float value = uiSliders_Size.at(index)->value(); + if((rectItems.at(index)->pos().x() + maxRectWidth*value < cameraScene->width()) & + (rectItems.at(index)->pos().y() + maxRectWidth*value < cameraScene->height())) { + + rectItems.at(index)->setRect(QRect(0,0,maxRectWidth*value,maxRectWidth*value)); + emit(sizeChanged(index, QSize(rectItems.at(index)->rect().width(),rectItems.at(index)->rect().height()))); + } +} + +void TrackerPlugin_PupilDiam::on_lineEdit_editingFinished() +{ + wndLength = ui->lineEdit->text().toDouble(); + for(int i=0;iclear(); + frameCount = 0; + } +} + +void TrackerPlugin_PupilDiam::onAreaConstraintsEditingFinished(int index) +{ + emit(areaContraintsChanged(index, uiLineEdits.at(index)->text().toInt())); +} + +void TrackerPlugin_PupilDiam::onItemPositionChanged(int index) +{ + if(rectItems.at(index)->pos().x() < 0){ + rectItems.at(index)->setX(0); + } + if(rectItems.at(index)->pos().y() < 0){ + rectItems.at(index)->setY(0); + } + if ((rectItems.at(index)->pos().x() + rectItems.at(index)->rect().width()) >= cameraResolution.width()){ + rectItems.at(index)->setX(cameraResolution.width()-rectItems.at(index)->rect().width()); + } + if ((rectItems.at(index)->pos().y() + rectItems.at(index)->rect().height()) >= cameraResolution.height()){ + rectItems.at(index)->setY(cameraResolution.height()-rectItems.at(index)->rect().height()); + } + + emit(posChanged(index, QPoint(rectItems.at(index)->pos().x(),rectItems.at(index)->pos().y()))); +} diff --git a/TrackerPlugin_PupilDiam.h b/TrackerPlugin_PupilDiam.h new file mode 100644 index 0000000..e60a097 --- /dev/null +++ b/TrackerPlugin_PupilDiam.h @@ -0,0 +1,95 @@ +#ifndef PUPILDIAMTRACKER_H +#define PUPILDIAMTRACKER_H + +#include "TrackerInterface.h" +#include "TrackerWorker.h" +#include "ui_TrackerPlugin_PupilDiam.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Ui { + class TrackerPlugin_PupilDiam; +} + +class TrackerPlugin_PupilDiam : public QWidget, public TrackerInterface +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.PylonRecorder.TrackerInterface") + Q_INTERFACES(TrackerInterface) + +public: + explicit TrackerPlugin_PupilDiam(QObject *parent = 0); + QObject *worker(); + void initializeUI(QLayout* guiTargetLayout, QGraphicsScene* cameraScene, QSize cameraResolution); + TrackerWorker* trackerWorker; + QSize cameraResolution; + +public slots: + void onFrameGrabbed(cv::Mat); + +private: + Ui::TrackerPlugin_PupilDiam *ui; + QGraphicsScene* cameraScene; + QGraphicsPixmapItem* pixmapItem; + QVector rectItems; + QVector plotPens; + QVector rectPens; + + QVector*> rectSamples; + QVector rectData; + QVector curves; + + /*ui pointers for use with signalmapper*/ + QVector uiPlots; + QVector uiSliders; + QVector uiSliders_Size; + QVector uiCheckboxes; + QVector uiLineEdits; + + int maxRectWidth = 200; + const int bitDepth = 8; + + int t = 0; + int wndLength = 100; + int frameCount = 0; + + QSignalMapper* signalMapperPosition; + QSignalMapper* signalMapperCheckBoxes; + QSignalMapper* signalMapperSliders; + QSignalMapper* signalMapperSliders_Size; + QSignalMapper* signalMapperLineEdit; + +private slots: + void onTrackingResult(TrackingResults result); + void onCheckBoxClicked(int); + void onThreshSliderMoved(int); + void onSizeSliderMoved(int); + void on_lineEdit_editingFinished(); + void onAreaConstraintsEditingFinished(int); + void onItemPositionChanged(int); + +signals: + void sizeChanged(int index, QSize size); + void posChanged(int index, QPoint pos); + void thresholdChanged(int index, int value); + void areaContraintsChanged(int index, int value); + +}; + +#endif // PUPILDIAMTRACKER_H diff --git a/TrackerPlugin_PupilDiam.pro b/TrackerPlugin_PupilDiam.pro new file mode 100644 index 0000000..9f870e7 --- /dev/null +++ b/TrackerPlugin_PupilDiam.pro @@ -0,0 +1,38 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2016-10-24T11:57:07 +# +#------------------------------------------------- + +TEMPLATE = lib +CONFIG += plugin +QT += widgets +TARGET = $$qtLibraryTarget(TrackerPlugin_pupilDiam) +DESTDIR = ../../../../src/build/plugins +CONFIG += c++11 + + +SOURCES += \ + TrackerPlugin_PupilDiam.cpp \ + TrackerWorker.cpp + +HEADERS += \ + TrackerPlugin_PupilDiam.h \ + TrackerWorker.h \ + NotifyingQGraphicsRectItem.h \ + TrackingResults.h + +INCLUDEPATH += ../../../../src/ + +win32 { + INCLUDEPATH += "C:/Qwt-6.1.3/include" + LIBS += -L"C:/Qwt-6.1.3/lib" \ + -lqwt +} + +unix{ + CONFIG += qwt +} + +FORMS += \ + TrackerPlugin_PupilDiam.ui diff --git a/TrackerPlugin_PupilDiam.ui b/TrackerPlugin_PupilDiam.ui new file mode 100644 index 0000000..ae46d20 --- /dev/null +++ b/TrackerPlugin_PupilDiam.ui @@ -0,0 +1,416 @@ + + + TrackerPlugin_PupilDiam + + + + 0 + 0 + 610 + 909 + + + + Form + + + + + + 0 + + + + + + 0 + 150 + + + + + + + + + 0 + 150 + + + + + + + + 0 + + + + + Cornea Y + + + true + + + + + + + + + Min Area + + + + + + + 0 + + + + + + + + + 0 + + + + + + + Max Area + + + + + + + 50000 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + 20 + + + + + + + + 0 + + + + + Pupil X + + + true + + + + + + + 0 + + + + + + + + 0.010000000000000 + + + 1.000000000000000 + + + 2 + + + 0 + + + 1.000000000000000 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + 150 + + + + + + + + 0 + + + + + Pupil Y + + + true + + + + + + + + + Min Area + + + + + + + 0 + + + + + + + + + 0 + + + + + Max Area + + + + + + + 50000 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 0 + + + + + Cornea X + + + true + + + + + + + 0 + + + + + + + + 0.010000000000000 + + + 1.000000000000000 + + + 2 + + + 0 + + + 1.000000000000000 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + 150 + + + + + + + + 0 + + + + + Pupil Diameter + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Qt::Horizontal + + + + + + + 0 + + + + + Binary + + + + + + + Window width [fms]: + + + + + + + 200 + + + + + + + + + + QwtPlot + QFrame +
qwt_plot.h
+ 1 +
+ + QwtSlider + QWidget +
qwt_slider.h
+
+
+ + +
diff --git a/TrackerWorker.cpp b/TrackerWorker.cpp new file mode 100644 index 0000000..6e51efd --- /dev/null +++ b/TrackerWorker.cpp @@ -0,0 +1,149 @@ +#include "TrackerWorker.h" + +using namespace cv; + +TrackerWorker::TrackerWorker(QObject* parent) + : QObject(parent) +{ + qRegisterMetaType < QVector >("QVectorFloat"); + + qRegisterMetaType("TrackingResults"); + + rois.push_back(QRect(0,0,100,100)); + rois.push_back(QRect(0,0,100,100)); + + thresholds.push_back(255); + thresholds.push_back(255); + + areaConstraints.push_back(100); + areaConstraints.push_back(50000); + areaConstraints.push_back(100); + areaConstraints.push_back(50000); +} + +void TrackerWorker::onFrameGrabbed(Mat src) +{ + int pMinArea = areaConstraints.at(0); + int pMaxArea = areaConstraints.at(1); + int cMinArea = areaConstraints.at(2); + int cMaxArea = areaConstraints.at(3); + + TrackingResults eyeTrackingResult; + eyeTrackingResult.cCornea = Point(0,0); + eyeTrackingResult.cPupil = Point(0,0); + eyeTrackingResult.pDiam = 0; + + std::vector rgb; + split(src, rgb); + + /*Pupil*/ + Mat pMask; + Mat pRegion = rgb[0].rowRange(rois.at(0).y(),rois.at(0).y() + rois.at(0).height()).colRange(rois.at(0).x(),rois.at(0).x() + rois.at(0).width()); + cv::threshold(pRegion, pMask, thresholds.at(0), 1, THRESH_BINARY_INV); + + std::vector pHierarchy; + std::vector > pContours; + std::vector pContour; + findContours(pMask, pContours, pHierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) ); + for(uint i=0;i=pMinArea) & (contourArea(pContours[i])<=pMaxArea)){ + pContour = pContours[i]; + for(uint j=0;j4){ + /*Determine centroid by fitting an ellipse*/ + pRect = fitEllipse(pContour); + eyeTrackingResult.cPupil = pRect.center; + eyeTrackingResult.pDiam = (pRect.boundingRect().height + pRect.boundingRect().width) / 2; + } + + + /*Corneal reflection*/ + Mat cMask; + Mat cRegion = rgb[1].rowRange(rois.at(1).y(),rois.at(1).y() + rois.at(1).height()).colRange(rois.at(1).x(),rois.at(1).x() + rois.at(1).width()); + cv::threshold(cRegion, cMask, thresholds.at(1), 1, THRESH_BINARY); + + std::vector cHierarchy; + std::vector > cContours; + std::vector cContour; + findContours(cMask, cContours, cHierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) ); + + + for(uint i=0;i=cMinArea)&(contourArea(cContours[i])4){ + /*Determine centroid with boundingRect*/ + Rect cRect = boundingRect(cContour); + eyeTrackingResult.cCornea.x = cRect.x + (cRect.width / 2); + eyeTrackingResult.cCornea.y = cRect.y + (cRect.height / 2); + } + + emit(trackingResult(eyeTrackingResult)); + + /*Generate preview image*/ + Mat previewIm(src.size(), CV_8U, double(0)); + previewIm(Rect(rois.at(0).x(),rois.at(0).y(), rois.at(0).width(), rois.at(0).height())) = pMask*255; + previewIm(Rect(rois.at(1).x(),rois.at(1).y(), rois.at(1).width(), rois.at(1).height())) = cMask*127; + + Mat outputIm; + + if(showBinary){ + outputIm = Mat(src.size(), CV_8UC3); + cvtColor(previewIm, outputIm, CV_GRAY2RGB); + }else{ + outputIm = src; + } + + circle(outputIm, eyeTrackingResult.cPupil, 10, Scalar(0,255,0), -1, 8, 0); + circle(outputIm, eyeTrackingResult.cCornea, 10, Scalar(255,0,255), -1, 8, 0); + + //std::vector > pContourV = std::vector >(1, pContour); + //drawContours(outputIm, pContourV, -1, Scalar(0,255,0), 2, 8); + + std::vector > cContourV = std::vector >(1, cContour); + drawContours(outputIm, cContourV, -1, Scalar(255,0,255), 2, 8); + + ellipse(outputIm, pRect, Scalar(0,255,0), 10, 8); + + emit(trackingPreview(outputIm)); + emit(trackingResult(eyeTrackingResult)); +} + +void TrackerWorker::onThresholdChanged(int index, int value) +{ + thresholds.replace(index, value); +} + +void TrackerWorker::onAreaConstraintsChanged(int index, int area) +{ + areaConstraints.replace(index, area); +} + +void TrackerWorker::onPosChanged(int index, QPoint pos) +{ + rois.replace(index, QRect(pos.x(), pos.y(), rois.at(index).width(), rois.at(index).height())); +} + +void TrackerWorker::onSizeChanged(int index, QSize size) +{ + rois.replace(index, QRect(rois.at(index).x(), rois.at(index).y(), size.width(), size.height())); +} + +void TrackerWorker::onShowBinary(bool showBinary) +{ + this->showBinary = showBinary; +} diff --git a/TrackerWorker.h b/TrackerWorker.h new file mode 100644 index 0000000..8a0c36f --- /dev/null +++ b/TrackerWorker.h @@ -0,0 +1,48 @@ +#ifndef TRACKERWORKER_H +#define TRACKERWORKER_H +#include "TrackerWorkerInterface.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TrackingResults.h" + +using namespace cv; + +class TrackerWorker : public QObject, public TrackerWorkerInterface +{ + Q_OBJECT + +public: + TrackerWorker(QObject* parent = 0); + +private: + QVector rois; + QVector thresholds; + QVector areaConstraints; /*Pupil minArea, maxArea, Cornea minArea, maxArea*/ + bool showBinary = false; + +public slots: + void onFrameGrabbed(Mat); + void onThresholdChanged(int index, int value); + void onAreaConstraintsChanged(int minSize, int maxSize); + void onPosChanged(int index, QPoint pos); + void onSizeChanged(int index, QSize size); + void onShowBinary(bool showBinary); + + +signals: + //void trackingResult(QVector); + void trackingResult(TrackingResults eyeTrackingResults); + void trackingPreview(Mat); + void trackingRois(QVector); + +}; + +#endif // TRACKERWORKER_H diff --git a/TrackingResults.h b/TrackingResults.h new file mode 100644 index 0000000..621ddff --- /dev/null +++ b/TrackingResults.h @@ -0,0 +1,14 @@ +#ifndef TRACKINGRESULTS_H +#define TRACKINGRESULTS_H +#include + + +struct TrackingResults{ + cv::Point cPupil; + cv::Point cCornea; + double pDiam; +}; + + + +#endif // TRACKINGRESULTS_H