Commit 92bb3991 authored by Thiago Santini's avatar Thiago Santini

Cleaning up pupil detection and tracking interfaces and classes

parent 0064756c
......@@ -22,6 +22,7 @@ class ERWidget : public QMainWindow
Q_OBJECT
public:
explicit ERWidget(QString id, QWidget *parent = 0);
virtual ~ERWidget() {}
signals:
void closed(bool b);
......
......@@ -6,29 +6,30 @@ using namespace cv;
static int gEyeDataId = qRegisterMetaType<EyeData>("EyeData");
EyeImageProcessor::EyeImageProcessor(QString id, QObject *parent)
: id(id),
pupilDetectionMethod(NULL),
pupilTrackingMethod(NULL),
:
QObject(parent),
cameraCalibration(NULL),
id(id),
sROI(QPointF(0,0)),
eROI(QPointF(1,1)),
QObject(parent)
eROI(QPointF(1,1)),
pupilDetectionMethod(NULL),
pupilTrackingMethod(NULL)
{
availablePupilDetectionMethods.push_back(new PuRe());
availablePupilDetectionMethods.push_back(new ElSe());
availablePupilDetectionMethods.push_back(new ExCuSe());
availablePupilDetectionMethods.push_back(std::make_shared<PuRe>());
availablePupilDetectionMethods.push_back(std::make_shared<ElSe>());
availablePupilDetectionMethods.push_back(std::make_shared<ExCuSe>());
#ifdef STARBURST
availablePupilDetectionMethods.push_back(new Starburst());
availablePupilDetectionMethods.push_back(std::make_shared<Starburst>());
#endif
#ifdef SWIRSKI
availablePupilDetectionMethods.push_back(new Swirski());
availablePupilDetectionMethods.push_back(std::make_shared<Swirski>());
#endif
settings = new QSettings(gCfgDir + "/" + id + " ImageProcessor.ini", QSettings::IniFormat);
updateConfig();
pmIdx = gPerformanceMonitor.enrol(id, "Image Processor");
pupilTrackingMethod = new PuReST();
pupilTrackingMethod = std::make_shared<PuReST>();
}
void EyeImageProcessor::updateConfig()
......@@ -44,8 +45,6 @@ void EyeImageProcessor::updateConfig()
EyeImageProcessor::~EyeImageProcessor()
{
for (int i=0; i<availablePupilDetectionMethods.size(); i++)
delete availablePupilDetectionMethods[i];
availablePupilDetectionMethods.clear();
if(settings)
......@@ -78,17 +77,22 @@ 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);
data.pupil = Pupil();
data.validPupil = false;
if (pupilDetectionMethod != NULL) {
Rect userROI = Rect(
Point(sROI.x() * data.input.cols, sROI.y() * data.input.rows),
Point( eROI.x() * data.input.cols, eROI.y() * data.input.rows)
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) )
);
float scalingFactor = 1;
if (cfg.processingDownscalingFactor > 1)
scalingFactor = 1.0 / cfg.processingDownscalingFactor;
scalingFactor = static_cast<float>(1.0 / cfg.processingDownscalingFactor);
/*
* From here on, our reference frame is the scaled user ROI
......@@ -99,6 +103,10 @@ void EyeImageProcessor::process(Timestamp timestamp, const Mat &frame)
INTER_AREA);
Rect coarseROI = {0, 0, downscaled.cols, downscaled.rows };
// Rescale pupil size limits as well
minPupilDiameterPx *= scalingFactor;
maxPupilDiameterPx *= scalingFactor;
// If the user wants a coarse location and the method has none embedded,
// we further constrain the search using the generic one
if (!pupilDetectionMethod->hasCoarseLocation() && cfg.coarseDetection) {
......@@ -110,18 +118,14 @@ void EyeImageProcessor::process(Timestamp timestamp, const Mat &frame)
} else
data.coarseROI = Rect();
if (cfg.tracking && pupilTrackingMethod) {
pupilTrackingMethod->run(timestamp, downscaled, coarseROI, data.pupil, *pupilDetectionMethod);
} else {
pupilDetectionMethod->run( downscaled, coarseROI, data.pupil );
// TODO: expose this to the user
if ( ! pupilDetectionMethod->hasConfidence() )
data.pupil.confidence = PupilDetectionMethod::outlineContrastConfidence(downscaled, data.pupil);
}
if (cfg.tracking && pupilTrackingMethod)
pupilTrackingMethod->detectAndTrack(timestamp, downscaled, coarseROI, data.pupil, pupilDetectionMethod, minPupilDiameterPx, maxPupilDiameterPx);
else
data.pupil = pupilDetectionMethod->detectWithConfidence( downscaled, coarseROI, minPupilDiameterPx, maxPupilDiameterPx);
if (data.pupil.center.x > 0 && data.pupil.center.y > 0) {
// Upscale
data.pupil.resize( 1.0 / scalingFactor );
data.pupil.resize( 1.0f / scalingFactor );
// User region shift
data.pupil.shift( userROI.tl() );
......
......@@ -118,8 +118,10 @@ public:
coarseDetection(false),
processingDownscalingFactor(1),
pupilDetectionMethod(PuRe::desc.c_str()),
tracking(true)
{}
tracking(true),
minPupilDiameterRatio(0.f),
maxPupilDiameterRatio(1.0f)
{}
cv::Size inputSize;
CVFlip flip;
......@@ -128,6 +130,8 @@ public:
double processingDownscalingFactor;
QString pupilDetectionMethod;
bool tracking;
float minPupilDiameterRatio;
float maxPupilDiameterRatio;
void save(QSettings *settings)
{
......@@ -273,7 +277,7 @@ public slots:
cfg.inputSize.width = widthSB->value();
cfg.inputSize.height = heightSB->value();
cfg.processingDownscalingFactor = downscalingSB->value();
cfg.flip = (CVFlip) flipComboBox->currentData().toInt();
cfg.flip = static_cast<CVFlip>(flipComboBox->currentData().toInt());
cfg.coarseDetection = coarseDetectionBox->isChecked();
cfg.pupilDetectionMethod = pupilDetectionComboBox->currentData().toString();
cfg.tracking = trackingBox->isChecked();
......@@ -298,7 +302,7 @@ public:
explicit EyeImageProcessor(QString id, QObject *parent = 0);
~EyeImageProcessor();
QSettings *settings;
QVector<PupilDetectionMethod*> availablePupilDetectionMethods;
QVector<std::shared_ptr<PupilDetectionMethod>> availablePupilDetectionMethods;
EyeImageProcessorConfig cfg;
EyeData data;
std::shared_ptr<CameraCalibration> cameraCalibration;
......@@ -316,8 +320,8 @@ private:
QMutex cfgMutex;
QPointF sROI, eROI;
PupilDetectionMethod *pupilDetectionMethod;
PupilTrackingMethod *pupilTrackingMethod;
std::shared_ptr<PupilDetectionMethod> pupilDetectionMethod;
std::shared_ptr<PupilTrackingMethod> pupilTrackingMethod;
unsigned int pmIdx;
};
......
......@@ -13,7 +13,8 @@ public:
explicit InputData() {
timestamp = maxTimestamp;
processingTimestamp = maxTimestamp;
}
}
virtual ~InputData() {}
Timestamp timestamp;
Timestamp processingTimestamp;
virtual QString header(QString prefix) const = 0;
......@@ -25,7 +26,8 @@ class InputWidget
// When we have the generic synchronizer, we should enforce a signal
// void newData(InputData) here.
public:
virtual void startRecording() = 0;
virtual ~InputWidget() {}
virtual void startRecording() = 0;
virtual void stopRecording() = 0;
};
......
......@@ -1370,7 +1370,7 @@ RotatedRect ElSe::run(const Mat &frame)
ellipse=find_best_edge(&pic, &detected_edges, &magni, start_x, end_x, start_y, end_y,mean_dist, inner_color_range);
if(ellipse.center.x<=0 && ellipse.center.y<=0 || ellipse.center.x>=pic.cols || ellipse.center.y>=pic.rows){
if( (ellipse.center.x<=0 && ellipse.center.y<=0) || (ellipse.center.x>=pic.cols || ellipse.center.y>=pic.rows) ){
ellipse=blob_finder(&pic);
ellipse.angle = 0;
......@@ -1381,22 +1381,19 @@ RotatedRect ElSe::run(const Mat &frame)
return ellipse;
}
void ElSe::run(const cv::Mat &frame, const cv::Rect &roi, Pupil &pupil, const float &minPupilDiameterPx, const float &maxPupilDiameterPx)
Pupil ElSe::implDetect(const cv::Mat &frame, cv::Rect roi, const float &userMinPupilDiameterPx, const float &maxPupilDiameterPx)
{
if (roi.area() < 10) {
qWarning() << "Bad ROI: falling back to regular detection.";
PupilDetectionMethod::run(frame, pupil);
return;
}
if (minPupilDiameterPx > 0 && maxPupilDiameterPx > 0 ) {
minArea = pow(minPupilDiameterPx,2);
if (userMinPupilDiameterPx > 0 && maxPupilDiameterPx > 0 ) {
minArea = pow(userMinPupilDiameterPx,2);
maxArea = pow(maxPupilDiameterPx,2);
} else {
minArea = frame.cols * frame.rows * 0.005;
maxArea = frame.cols * frame.rows * 0.2;
minArea = frame.cols * frame.rows * 0.005f;
maxArea = frame.cols * frame.rows * 0.2f;
}
pupil = run( frame(roi) );
Pupil pupil = run( frame(roi) );
if (pupil.center.x > 0 && pupil.center.y > 0)
pupil.shift( roi.tl() );
return pupil;
}
......@@ -18,15 +18,17 @@
class ElSe : public PupilDetectionMethod
{
public:
ElSe() { mDesc = desc; }
cv::RotatedRect run(const cv::Mat &frame);
void run(const cv::Mat &frame, const cv::Rect &roi, Pupil &pupil, const float &minPupilDiameterPx=-1, const float &maxPupilDiameterPx=-1);
bool hasConfidence() { return false; }
bool hasCoarseLocation() { return false; }
static std::string desc;
static float minArea;
static float maxArea;
ElSe() { mDesc = desc; }
Pupil implDetect(const cv::Mat &frame, cv::Rect roi, const float &userMinPupilDiameterPx, const float &userMaxPupilDiameterPx) override;
bool hasConfidence() override { return false; }
bool hasCoarseLocation() override { return false; }
static std::string desc;
private:
cv::RotatedRect run(const cv::Mat &frame);
};
#endif // ELSE_H
......@@ -1731,18 +1731,14 @@ RotatedRect ExCuSe::run(const Mat &frame)
return runexcuse(&target, &pic_th, &th_edges, 15);
}
void ExCuSe::run(const cv::Mat &frame, const Rect &roi, Pupil &pupil, const float &minPupilDiameterPx, const float &maxPupilDiameterPx)
Pupil ExCuSe::implDetect(const cv::Mat &frame, cv::Rect roi, const float &userMinPupilDiameterPx, const float &userMaxPupilDiameterPx)
{
if (roi.area() < 10) {
qWarning() << "Bad ROI: falling back to regular detection.";
PupilDetectionMethod::run(frame, pupil);
return;
}
(void) userMinPupilDiameterPx;
(void) userMaxPupilDiameterPx;
(void) minPupilDiameterPx;
(void) maxPupilDiameterPx;
pupil = run( frame(roi) );
Pupil pupil = run( frame(roi) );
if (pupil.center.x > 0 && pupil.center.y > 0)
pupil.shift( roi.tl() );
return pupil;
}
......@@ -19,11 +19,13 @@ class ExCuSe : public PupilDetectionMethod
{
public:
ExCuSe() { mDesc = desc;}
cv::RotatedRect run(const cv::Mat &frame);
void run(const cv::Mat &frame, const cv::Rect &roi, Pupil &pupil, const float &minPupilDiameterPx=-1, const float &maxPupilDiameterPx=-1);
bool hasConfidence() { return false; }
bool hasCoarseLocation() { return false; }
Pupil implDetect(const cv::Mat &frame, cv::Rect roi, const float &userMinPupilDiameterPx, const float &userMaxPupilDiameterPx) override;
bool hasConfidence() override { return false; }
bool hasCoarseLocation() override { return false; }
static std::string desc;
private:
cv::RotatedRect run(const cv::Mat &frame);
};
#endif // EXCUSE_H
......@@ -52,9 +52,9 @@ using namespace cv;
string PuRe::desc = "PuRe (Santini et. al 2018a)";
PuRe::PuRe() :
baseSize(320,240),
expectedFrameSize(-1,-1),
outlineBias(5)
outlineBias(5),
baseSize(320,240)
{
mDesc = desc;
......@@ -92,12 +92,12 @@ void PuRe::estimateParameters(const int rows, const int cols)
* 1) The image contains at least both eye corners
* 2) The image contains a maximum of 5cm of the face (i.e., ~= 2x canthi distance)
*/
float d = sqrt( pow(rows,2) + pow(cols,2) );
maxCanthiDistancePx = d;
minCanthiDistancePx = 2*d/3.0;
float d = static_cast<float>(sqrt( pow(rows,2) + pow(cols,2) ));
maxCanthiDistancePx = static_cast<int>(d);
minCanthiDistancePx = static_cast<int>(2.0f*d/3.0f);
maxPupilDiameterPx = maxCanthiDistancePx*(maxPupilDiameterMM/meanCanthiDistanceMM);
minPupilDiameterPx = minCanthiDistancePx*(minPupilDiameterMM/meanCanthiDistanceMM);
maxPupilDiameterPx = static_cast<int>(maxCanthiDistancePx*(maxPupilDiameterMM/meanCanthiDistanceMM));
minPupilDiameterPx = static_cast<int>(minCanthiDistancePx*(minPupilDiameterMM/meanCanthiDistanceMM));
}
void PuRe::init(const Mat &frame)
......@@ -107,9 +107,9 @@ void PuRe::init(const Mat &frame)
expectedFrameSize = Size(frame.cols, frame.rows);
float rw = baseSize.width / (float) frame.cols;
float rh = baseSize.height / (float) frame.rows;
scalingRatio = min<float>( min<float>(rw, rh) , 1.0 );
float rw = baseSize.width / static_cast<float>(frame.cols);
float rh = baseSize.height / static_cast<float>(frame.rows);
scalingRatio = min( min(rw, rh) , 1.0f );
}
......@@ -163,7 +163,7 @@ Mat PuRe::canny(const Mat &in, const bool blurImage, const bool useL2, const int
// Ratio
int sum=0;
int nonEdgePixels = nonEdgePixelsRatio * in.rows * in.cols;
int nonEdgePixels = static_cast<int>(nonEdgePixelsRatio * in.rows * in.cols);
for(int i=0; i<bins; i++){
sum += histogram[i];
if( sum > nonEdgePixels ){
......@@ -201,8 +201,8 @@ Mat PuRe::canny(const Mat &in, const bool blurImage, const bool useL2, const int
float iy = p_y[j];
float ix = p_x[j];
float y = abs( (double) iy );
float x = abs( (double) ix );
float y = abs( iy );
float x = abs( ix );
uchar val = p_res[j] > high_th ? 255 : 128;
......@@ -234,7 +234,7 @@ Mat PuRe::canny(const Mat &in, const bool blurImage, const bool useL2, const int
int pic_x=edgeType.cols;
int pic_y=edgeType.rows;
int area = pic_x*pic_y;
int lines_idx=0;
unsigned int lines_idx=0;
int idx=0;
vector<int> lines;
......@@ -249,7 +249,7 @@ Mat PuRe::canny(const Mat &in, const bool blurImage, const bool useL2, const int
lines_idx = 1;
lines.clear();
lines.push_back(idx+j);
int akt_idx = 0;
unsigned int akt_idx = 0;
while(akt_idx<lines_idx){
int akt_pos=lines[akt_idx];
......@@ -288,13 +288,13 @@ void PuRe::filterEdges(cv::Mat &edges)
for(int i=start_x; i<end_x; i++){
uchar box[9];
box[4]=(uchar)edges.data[(edges.cols*(j))+(i)];
box[4]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i)]);
if(box[4]){
box[1]=(uchar)edges.data[(edges.cols*(j-1))+(i)];
box[3]=(uchar)edges.data[(edges.cols*(j))+(i-1)];
box[5]=(uchar)edges.data[(edges.cols*(j))+(i+1)];
box[7]=(uchar)edges.data[(edges.cols*(j+1))+(i)];
box[1]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i)]);
box[3]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i-1)]);
box[5]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i+1)]);
box[7]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i)]);
if((box[5] && box[7])) edges.data[(edges.cols*(j))+(i)]=0;
......@@ -326,33 +326,33 @@ void PuRe::filterEdges(cv::Mat &edges)
for(int i=start_x; i<end_x; i++){
uchar box[17];
box[4]=(uchar)edges.data[(edges.cols*(j))+(i)];
box[4]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i)]);
if(box[4]){
box[0]=(uchar)edges.data[(edges.cols*(j-1))+(i-1)];
box[1]=(uchar)edges.data[(edges.cols*(j-1))+(i)];
box[2]=(uchar)edges.data[(edges.cols*(j-1))+(i+1)];
box[0]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i-1)]);
box[1]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i)]);
box[2]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i+1)]);
box[3]=(uchar)edges.data[(edges.cols*(j))+(i-1)];
box[5]=(uchar)edges.data[(edges.cols*(j))+(i+1)];
box[3]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i-1)]);
box[5]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i+1)]);
box[6]=(uchar)edges.data[(edges.cols*(j+1))+(i-1)];
box[7]=(uchar)edges.data[(edges.cols*(j+1))+(i)];
box[8]=(uchar)edges.data[(edges.cols*(j+1))+(i+1)];
box[6]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i-1)]);
box[7]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i)]);
box[8]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i+1)]);
//external
box[9]=(uchar)edges.data[(edges.cols*(j))+(i+2)];
box[10]=(uchar)edges.data[(edges.cols*(j+2))+(i)];
box[9]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i+2)]);
box[10]=static_cast<uchar>(edges.data[(edges.cols*(j+2))+(i)]);
box[11]=(uchar)edges.data[(edges.cols*(j))+(i+3)];
box[12]=(uchar)edges.data[(edges.cols*(j-1))+(i+2)];
box[13]=(uchar)edges.data[(edges.cols*(j+1))+(i+2)];
box[11]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i+3)]);
box[12]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i+2)]);
box[13]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i+2)]);
box[14]=(uchar)edges.data[(edges.cols*(j+3))+(i)];
box[15]=(uchar)edges.data[(edges.cols*(j+2))+(i-1)];
box[16]=(uchar)edges.data[(edges.cols*(j+2))+(i+1)];
box[14]=static_cast<uchar>(edges.data[(edges.cols*(j+3))+(i)]);
box[15]=static_cast<uchar>(edges.data[(edges.cols*(j+2))+(i-1)]);
box[16]=static_cast<uchar>(edges.data[(edges.cols*(j+2))+(i+1)]);
......@@ -398,49 +398,49 @@ void PuRe::filterEdges(cv::Mat &edges)
uchar box[33];
box[4]=(uchar)edges.data[(edges.cols*(j))+(i)];
box[4]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i)]);
if(box[4]){
box[0]=(uchar)edges.data[(edges.cols*(j-1))+(i-1)];
box[1]=(uchar)edges.data[(edges.cols*(j-1))+(i)];
box[2]=(uchar)edges.data[(edges.cols*(j-1))+(i+1)];
box[3]=(uchar)edges.data[(edges.cols*(j))+(i-1)];
box[5]=(uchar)edges.data[(edges.cols*(j))+(i+1)];
box[6]=(uchar)edges.data[(edges.cols*(j+1))+(i-1)];
box[7]=(uchar)edges.data[(edges.cols*(j+1))+(i)];
box[8]=(uchar)edges.data[(edges.cols*(j+1))+(i+1)];
box[9]=(uchar)edges.data[(edges.cols*(j-1))+(i+2)];
box[10]=(uchar)edges.data[(edges.cols*(j-1))+(i-2)];
box[11]=(uchar)edges.data[(edges.cols*(j+1))+(i+2)];
box[12]=(uchar)edges.data[(edges.cols*(j+1))+(i-2)];
box[13]=(uchar)edges.data[(edges.cols*(j-2))+(i-1)];
box[14]=(uchar)edges.data[(edges.cols*(j-2))+(i+1)];
box[15]=(uchar)edges.data[(edges.cols*(j+2))+(i-1)];
box[16]=(uchar)edges.data[(edges.cols*(j+2))+(i+1)];
box[17]=(uchar)edges.data[(edges.cols*(j-3))+(i-1)];
box[18]=(uchar)edges.data[(edges.cols*(j-3))+(i+1)];
box[19]=(uchar)edges.data[(edges.cols*(j+3))+(i-1)];
box[20]=(uchar)edges.data[(edges.cols*(j+3))+(i+1)];
box[21]=(uchar)edges.data[(edges.cols*(j+1))+(i+3)];
box[22]=(uchar)edges.data[(edges.cols*(j+1))+(i-3)];
box[23]=(uchar)edges.data[(edges.cols*(j-1))+(i+3)];
box[24]=(uchar)edges.data[(edges.cols*(j-1))+(i-3)];
box[25]=(uchar)edges.data[(edges.cols*(j-2))+(i-2)];
box[26]=(uchar)edges.data[(edges.cols*(j+2))+(i+2)];
box[27]=(uchar)edges.data[(edges.cols*(j-2))+(i+2)];
box[28]=(uchar)edges.data[(edges.cols*(j+2))+(i-2)];
box[29]=(uchar)edges.data[(edges.cols*(j-3))+(i-3)];
box[30]=(uchar)edges.data[(edges.cols*(j+3))+(i+3)];
box[31]=(uchar)edges.data[(edges.cols*(j-3))+(i+3)];
box[32]=(uchar)edges.data[(edges.cols*(j+3))+(i-3)];
box[0]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i-1)]);
box[1]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i)]);
box[2]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i+1)]);
box[3]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i-1)]);
box[5]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i+1)]);
box[6]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i-1)]);
box[7]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i)]);
box[8]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i+1)]);
box[9]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i+2)]);
box[10]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i-2)]);
box[11]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i+2)]);
box[12]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i-2)]);
box[13]=static_cast<uchar>(edges.data[(edges.cols*(j-2))+(i-1)]);
box[14]=static_cast<uchar>(edges.data[(edges.cols*(j-2))+(i+1)]);
box[15]=static_cast<uchar>(edges.data[(edges.cols*(j+2))+(i-1)]);
box[16]=static_cast<uchar>(edges.data[(edges.cols*(j+2))+(i+1)]);
box[17]=static_cast<uchar>(edges.data[(edges.cols*(j-3))+(i-1)]);
box[18]=static_cast<uchar>(edges.data[(edges.cols*(j-3))+(i+1)]);
box[19]=static_cast<uchar>(edges.data[(edges.cols*(j+3))+(i-1)]);
box[20]=static_cast<uchar>(edges.data[(edges.cols*(j+3))+(i+1)]);
box[21]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i+3)]);
box[22]=static_cast<uchar>(edges.data[(edges.cols*(j+1))+(i-3)]);
box[23]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i+3)]);
box[24]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i-3)]);
box[25]=static_cast<uchar>(edges.data[(edges.cols*(j-2))+(i-2)]);
box[26]=static_cast<uchar>(edges.data[(edges.cols*(j+2))+(i+2)]);
box[27]=static_cast<uchar>(edges.data[(edges.cols*(j-2))+(i+2)]);
box[28]=static_cast<uchar>(edges.data[(edges.cols*(j+2))+(i-2)]);
box[29]=static_cast<uchar>(edges.data[(edges.cols*(j-3))+(i-3)]);
box[30]=static_cast<uchar>(edges.data[(edges.cols*(j+3))+(i+3)]);
box[31]=static_cast<uchar>(edges.data[(edges.cols*(j-3))+(i+3)]);
box[32]=static_cast<uchar>(edges.data[(edges.cols*(j+3))+(i-3)]);
if( box[7] && box[2] && box[9] )
edges.data[(edges.cols*(j))+(i)]=0;
......@@ -470,30 +470,30 @@ void PuRe::filterEdges(cv::Mat &edges)
edges.data[(edges.cols*(j))+(i)]=0;
uchar box2[18];
box2[1]=(uchar)edges.data[(edges.cols*(j))+(i-1)];
box2[1]=static_cast<uchar>(edges.data[(edges.cols*(j))+(i-1)]);
box2[2]=(uchar)edges.data[(edges.cols*(j-1))+(i-2)];
box2[3]=(uchar)edges.data[(edges.cols*(j-2))+(i-3)];
box2[2]=static_cast<uchar>(edges.data[(edges.cols*(j-1))+(i-2)]);
box2[3]=static_cast<uchar>(edges.data[(edges.cols*(j-2))