Commit 9e40c148 authored by Thiago Santini's avatar Thiago Santini

Homogenizes the outline contrast confidence evaluation

Changes outline contrast evaluation to use Bresenham's algorithm.
PuRe now uses the implementation from the PupilDetectionMethod as well.
parent 8f7f93ab
......@@ -655,7 +655,7 @@ void PuRe::detect(Pupil &pupil)
auto c = candidates[i];
c.drawit(out, c.color);
imwrite(QString("candidate-%1.png").arg(i).toStdString(), out);
c.drawOutlineContrast(input, 5, QString("contrast-%1-%2.png").arg(i).arg(QString::number(c.score)));
//c.drawOutlineContrast(input, 5, QString("contrast-%1-%2.png").arg(i).arg(QString::number(c.score)));
//waitKey(0);
}
*/
......@@ -773,119 +773,6 @@ void PuRe::run(const cv::Mat &frame, const cv::Rect &roi, Pupil &pupil, const fl
*
******************************************************************************/
static const float sinTable[] = {
0.0000000f , 0.0174524f , 0.0348995f , 0.0523360f , 0.0697565f , 0.0871557f ,
0.1045285f , 0.1218693f , 0.1391731f , 0.1564345f , 0.1736482f , 0.1908090f ,
0.2079117f , 0.2249511f , 0.2419219f , 0.2588190f , 0.2756374f , 0.2923717f ,
0.3090170f , 0.3255682f , 0.3420201f , 0.3583679f , 0.3746066f , 0.3907311f ,
0.4067366f , 0.4226183f , 0.4383711f , 0.4539905f , 0.4694716f , 0.4848096f ,
0.5000000f , 0.5150381f , 0.5299193f , 0.5446390f , 0.5591929f , 0.5735764f ,
0.5877853f , 0.6018150f , 0.6156615f , 0.6293204f , 0.6427876f , 0.6560590f ,
0.6691306f , 0.6819984f , 0.6946584f , 0.7071068f , 0.7193398f , 0.7313537f ,
0.7431448f , 0.7547096f , 0.7660444f , 0.7771460f , 0.7880108f , 0.7986355f ,
0.8090170f , 0.8191520f , 0.8290376f , 0.8386706f , 0.8480481f , 0.8571673f ,
0.8660254f , 0.8746197f , 0.8829476f , 0.8910065f , 0.8987940f , 0.9063078f ,
0.9135455f , 0.9205049f , 0.9271839f , 0.9335804f , 0.9396926f , 0.9455186f ,
0.9510565f , 0.9563048f , 0.9612617f , 0.9659258f , 0.9702957f , 0.9743701f ,
0.9781476f , 0.9816272f , 0.9848078f , 0.9876883f , 0.9902681f , 0.9925462f ,
0.9945219f , 0.9961947f , 0.9975641f , 0.9986295f , 0.9993908f , 0.9998477f ,
1.0000000f , 0.9998477f , 0.9993908f , 0.9986295f , 0.9975641f , 0.9961947f ,
0.9945219f , 0.9925462f , 0.9902681f , 0.9876883f , 0.9848078f , 0.9816272f ,
0.9781476f , 0.9743701f , 0.9702957f , 0.9659258f , 0.9612617f , 0.9563048f ,
0.9510565f , 0.9455186f , 0.9396926f , 0.9335804f , 0.9271839f , 0.9205049f ,
0.9135455f , 0.9063078f , 0.8987940f , 0.8910065f , 0.8829476f , 0.8746197f ,
0.8660254f , 0.8571673f , 0.8480481f , 0.8386706f , 0.8290376f , 0.8191520f ,
0.8090170f , 0.7986355f , 0.7880108f , 0.7771460f , 0.7660444f , 0.7547096f ,
0.7431448f , 0.7313537f , 0.7193398f , 0.7071068f , 0.6946584f , 0.6819984f ,
0.6691306f , 0.6560590f , 0.6427876f , 0.6293204f , 0.6156615f , 0.6018150f ,
0.5877853f , 0.5735764f , 0.5591929f , 0.5446390f , 0.5299193f , 0.5150381f ,
0.5000000f , 0.4848096f , 0.4694716f , 0.4539905f , 0.4383711f , 0.4226183f ,
0.4067366f , 0.3907311f , 0.3746066f , 0.3583679f , 0.3420201f , 0.3255682f ,
0.3090170f , 0.2923717f , 0.2756374f , 0.2588190f , 0.2419219f , 0.2249511f ,
0.2079117f , 0.1908090f , 0.1736482f , 0.1564345f , 0.1391731f , 0.1218693f ,
0.1045285f , 0.0871557f , 0.0697565f , 0.0523360f , 0.0348995f , 0.0174524f ,
0.0000000f , -0.0174524f , -0.0348995f , -0.0523360f , -0.0697565f , -0.0871557f ,
-0.1045285f , -0.1218693f , -0.1391731f , -0.1564345f , -0.1736482f , -0.1908090f ,
-0.2079117f , -0.2249511f , -0.2419219f , -0.2588190f , -0.2756374f , -0.2923717f ,
-0.3090170f , -0.3255682f , -0.3420201f , -0.3583679f , -0.3746066f , -0.3907311f ,
-0.4067366f , -0.4226183f , -0.4383711f , -0.4539905f , -0.4694716f , -0.4848096f ,
-0.5000000f , -0.5150381f , -0.5299193f , -0.5446390f , -0.5591929f , -0.5735764f ,
-0.5877853f , -0.6018150f , -0.6156615f , -0.6293204f , -0.6427876f , -0.6560590f ,
-0.6691306f , -0.6819984f , -0.6946584f , -0.7071068f , -0.7193398f , -0.7313537f ,
-0.7431448f , -0.7547096f , -0.7660444f , -0.7771460f , -0.7880108f , -0.7986355f ,
-0.8090170f , -0.8191520f , -0.8290376f , -0.8386706f , -0.8480481f , -0.8571673f ,
-0.8660254f , -0.8746197f , -0.8829476f , -0.8910065f , -0.8987940f , -0.9063078f ,
-0.9135455f , -0.9205049f , -0.9271839f , -0.9335804f , -0.9396926f , -0.9455186f ,
-0.9510565f , -0.9563048f , -0.9612617f , -0.9659258f , -0.9702957f , -0.9743701f ,
-0.9781476f , -0.9816272f , -0.9848078f , -0.9876883f , -0.9902681f , -0.9925462f ,
-0.9945219f , -0.9961947f , -0.9975641f , -0.9986295f , -0.9993908f , -0.9998477f ,
-1.0000000f , -0.9998477f , -0.9993908f , -0.9986295f , -0.9975641f , -0.9961947f ,
-0.9945219f , -0.9925462f , -0.9902681f , -0.9876883f , -0.9848078f , -0.9816272f ,
-0.9781476f , -0.9743701f , -0.9702957f , -0.9659258f , -0.9612617f , -0.9563048f ,
-0.9510565f , -0.9455186f , -0.9396926f , -0.9335804f , -0.9271839f , -0.9205049f ,
-0.9135455f , -0.9063078f , -0.8987940f , -0.8910065f , -0.8829476f , -0.8746197f ,
-0.8660254f , -0.8571673f , -0.8480481f , -0.8386706f , -0.8290376f , -0.8191520f ,
-0.8090170f , -0.7986355f , -0.7880108f , -0.7771460f , -0.7660444f , -0.7547096f ,
-0.7431448f , -0.7313537f , -0.7193398f , -0.7071068f , -0.6946584f , -0.6819984f ,
-0.6691306f , -0.6560590f , -0.6427876f , -0.6293204f , -0.6156615f , -0.6018150f ,
-0.5877853f , -0.5735764f , -0.5591929f , -0.5446390f , -0.5299193f , -0.5150381f ,
-0.5000000f , -0.4848096f , -0.4694716f , -0.4539905f , -0.4383711f , -0.4226183f ,
-0.4067366f , -0.3907311f , -0.3746066f , -0.3583679f , -0.3420201f , -0.3255682f ,
-0.3090170f , -0.2923717f , -0.2756374f , -0.2588190f , -0.2419219f , -0.2249511f ,
-0.2079117f , -0.1908090f , -0.1736482f , -0.1564345f , -0.1391731f , -0.1218693f ,
-0.1045285f , -0.0871557f , -0.0697565f , -0.0523360f , -0.0348995f , -0.0174524f ,
-0.0000000f , 0.0174524f , 0.0348995f , 0.0523360f , 0.0697565f , 0.0871557f ,
0.1045285f , 0.1218693f , 0.1391731f , 0.1564345f , 0.1736482f , 0.1908090f ,
0.2079117f , 0.2249511f , 0.2419219f , 0.2588190f , 0.2756374f , 0.2923717f ,
0.3090170f , 0.3255682f , 0.3420201f , 0.3583679f , 0.3746066f , 0.3907311f ,
0.4067366f , 0.4226183f , 0.4383711f , 0.4539905f , 0.4694716f , 0.4848096f ,
0.5000000f , 0.5150381f , 0.5299193f , 0.5446390f , 0.5591929f , 0.5735764f ,
0.5877853f , 0.6018150f , 0.6156615f , 0.6293204f , 0.6427876f , 0.6560590f ,
0.6691306f , 0.6819984f , 0.6946584f , 0.7071068f , 0.7193398f , 0.7313537f ,
0.7431448f , 0.7547096f , 0.7660444f , 0.7771460f , 0.7880108f , 0.7986355f ,
0.8090170f , 0.8191520f , 0.8290376f , 0.8386706f , 0.8480481f , 0.8571673f ,
0.8660254f , 0.8746197f , 0.8829476f , 0.8910065f , 0.8987940f , 0.9063078f ,
0.9135455f , 0.9205049f , 0.9271839f , 0.9335804f , 0.9396926f , 0.9455186f ,
0.9510565f , 0.9563048f , 0.9612617f , 0.9659258f , 0.9702957f , 0.9743701f ,
0.9781476f , 0.9816272f , 0.9848078f , 0.9876883f , 0.9902681f , 0.9925462f ,
0.9945219f , 0.9961947f , 0.9975641f , 0.9986295f , 0.9993908f , 0.9998477f ,
1.0000000f
};
static void inline sincos( int angle, float& cosval, float& sinval )
{
angle += (angle < 0 ? 360 : 0);
sinval = sinTable[angle];
cosval = sinTable[450 - angle];
}
static inline vector<Point> ellipse2Points( const RotatedRect &ellipse, const int &delta )
{
int angle = ellipse.angle;
// make sure angle is within range
while( angle < 0 )
angle += 360;
while( angle > 360 )
angle -= 360;
float alpha, beta;
sincos( angle, alpha, beta );
double x, y;
vector<Point> points;
for( int i = 0; i < 360; i += delta )
{
x = 0.5*ellipse.size.width * sinTable[450-i];
y = 0.5*ellipse.size.height * sinTable[i];
points.push_back(
Point( roundf(ellipse.center.x + x * alpha - y * beta),
roundf(ellipse.center.y + x * beta + y * alpha) )
);
}
return points;
}
inline bool PupilCandidate::isValid(const cv::Mat &intensityImage, const int &minPupilDiameterPx, const int &maxPupilDiameterPx, const int bias)
{
if (points.size() < 5)
......@@ -947,134 +834,9 @@ inline bool PupilCandidate::fastValidityCheck(const int &maxPupilDiameterPx)
inline bool PupilCandidate::validateOutlineContrast(const Mat &intensityImage, const int &bias)
{
int delta = 0.15*minorAxis;
cv::Point c = outline.center;
//#define DBG_OUTLINE_CONTRAST
#ifdef DBG_OUTLINE_CONTRAST
cv::Mat tmp;
cv::cvtColor(intensityImage, tmp, CV_GRAY2BGR);
cv::ellipse(tmp, outline, cv::Scalar(0,255,255));
cv::Scalar lineColor;
#endif
int evaluated = 0;
int validCount = 0;
vector<Point> outlinePoints = ellipse2Points(outline, 10);
for (auto p=outlinePoints.begin(); p!=outlinePoints.end(); p++) {
int dx = p->x - c.x;
int dy = p->y - c.y;
float a = 0;
if (dx != 0)
a = dy / (float) dx;
float b = c.y - a*c.x;
if (a == 0)
continue;
if ( abs(dx) > abs(dy) ) {
int sx = p->x - delta;
int ex = p->x + delta;
int sy = std::roundf(a*sx + b);
int ey = std::roundf(a*ex + b);
cv::Point start = { sx, sy };
cv::Point end = { ex, ey };
evaluated++;
if (!boundaries.contains(start) || !boundaries.contains(end) )
continue;
float m1, m2, count;
m1 = count = 0;
for (int x=sx; x<p->x; x++)
m1 += intensityImage.ptr<uchar>( (int) std::roundf(a*x+b) )[x];
m1 = std::roundf( m1 / delta );
m2 = count = 0;
for (int x=p->x+1; x<=ex; x++) {
m2 += intensityImage.ptr<uchar>( (int) std::roundf(a*x+b) )[x];
}
m2 = std::roundf( m2 / delta );
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,0,255);
#endif
if (p->x < c.x) {// leftwise point
if (m1 > m2+bias) {
validCount ++;
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,255,0);
#endif
}
} else {// rightwise point
if (m2 > m1+bias) {
validCount++;
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,255,0);
#endif
}
}
#ifdef DBG_OUTLINE_CONTRAST
cv::line(tmp, start, end, lineColor);
#endif
} else {
int sy = p->y - delta;
int ey = p->y + delta;
int sx = std::roundf((sy - b)/a);
int ex = std::roundf((ey - b)/a);
cv::Point start = { sx, sy };
cv::Point end = { ex, ey };
evaluated++;
if (!boundaries.contains(start) || !boundaries.contains(end) )
continue;
float m1, m2, count;
m1 = count = 0;
for (int y=sy; y<p->y; y++)
m1 += intensityImage.ptr<uchar>(y)[ (int) std::roundf((y-b)/a) ];
m1 = std::roundf( m1 / delta );
m2 = count = 0;
for (int y=p->y+1; y<=ey; y++)
m2 += intensityImage.ptr<uchar>(y)[ (int) std::roundf((y-b)/a) ];
m2 = std::roundf( m2 / delta );
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,0,255);
#endif
if (p->y < c.y) {// upperwise point
if (m1 > m2+bias) {
validCount++;
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,255,0);
#endif
}
} else {// bottomwise point
if (m2 > m1+bias) {
validCount++;
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,255,0);
#endif
}
}
#ifdef DBG_OUTLINE_CONTRAST
cv::line(tmp, start, end, lineColor);
#endif
}
}
if (evaluated == 0)
outlineContrast = PupilDetectionMethod::outlineContrastConfidence(intensityImage, outline, bias);
if (outlineContrast <= 0)
return false;
outlineContrast = validCount / (float) evaluated;
#ifdef DBG_OUTLINE_CONTRAST
cv::imshow("Outline Contrast", tmp);
cv::waitKey(0);
#endif
return true;
}
......@@ -1118,118 +880,3 @@ inline bool PupilCandidate::validityCheck(const cv::Mat &intensityImage, const i
return true;
}
inline bool PupilCandidate::drawOutlineContrast(const Mat &intensityImage, const int &bias, QString out)
{
double lw = 1;
int delta = 0.15*minorAxis;
cv::Point c = outline.center;
cv::Mat tmp;
cv::cvtColor(intensityImage, tmp, CV_GRAY2BGR);
cv::ellipse(tmp, outline, cv::Scalar(0,255,255), lw);
cv::Scalar lineColor;
int evaluated = 0;
int validCount = 0;
vector<Point> outlinePoints = ellipse2Points(outline, 10);
for (auto p=outlinePoints.begin(); p!=outlinePoints.end(); p++) {
int dx = p->x - c.x;
int dy = p->y - c.y;
float a = 0;
if (dx != 0)
a = dy / (float) dx;
float b = c.y - a*c.x;
if (a == 0)
continue;
if ( abs(dx) > abs(dy) ) {
int sx = p->x - delta;
int ex = p->x + delta;
int sy = std::roundf(a*sx + b);
int ey = std::roundf(a*ex + b);
cv::Point start = { sx, sy };
cv::Point end = { ex, ey };
evaluated++;
if (!boundaries.contains(start) || !boundaries.contains(end) )
continue;
float m1, m2, count;
m1 = count = 0;
for (int x=sx; x<p->x; x++)
m1 += intensityImage.ptr<uchar>( (int) std::roundf(a*x+b) )[x];
m1 = std::roundf( m1 / delta );
m2 = count = 0;
for (int x=p->x+1; x<=ex; x++) {
m2 += intensityImage.ptr<uchar>( (int) std::roundf(a*x+b) )[x];
}
m2 = std::roundf( m2 / delta );
lineColor = cv::Scalar(0,0,255);
if (p->x < c.x) {// leftwise point
if (m1 > m2+bias) {
validCount ++;
lineColor = cv::Scalar(0,255,0);
}
} else {// rightwise point
if (m2 > m1+bias) {
validCount++;
lineColor = cv::Scalar(0,255,0);
}
}
cv::line(tmp, start, end, lineColor, lw);
} else {
int sy = p->y - delta;
int ey = p->y + delta;
int sx = std::roundf((sy - b)/a);
int ex = std::roundf((ey - b)/a);
cv::Point start = { sx, sy };
cv::Point end = { ex, ey };
evaluated++;
if (!boundaries.contains(start) || !boundaries.contains(end) )
continue;
float m1, m2, count;
m1 = count = 0;
for (int y=sy; y<p->y; y++)
m1 += intensityImage.ptr<uchar>(y)[ (int) std::roundf((y-b)/a) ];
m1 = std::roundf( m1 / delta );
m2 = count = 0;
for (int y=p->y+1; y<=ey; y++)
m2 += intensityImage.ptr<uchar>(y)[ (int) std::roundf((y-b)/a) ];
m2 = std::roundf( m2 / delta );
lineColor = cv::Scalar(0,0,255);
if (p->y < c.y) {// upperwise point
if (m1 > m2+bias) {
validCount++;
lineColor = cv::Scalar(0,255,0);
}
} else {// bottomwise point
if (m2 > m1+bias) {
validCount++;
lineColor = cv::Scalar(0,255,0);
}
}
cv::line(tmp, start, end, lineColor, lw);
}
}
if (evaluated == 0)
return false;
outlineContrast = validCount / (float) evaluated;
cv::imwrite(out.toStdString(), tmp);
return true;
}
......@@ -276,127 +276,57 @@ float PupilDetectionMethod::outlineContrastConfidence(const Mat &frame, const Pu
return NO_CONFIDENCE;
Rect boundaries = { 0, 0, frame.cols, frame.rows };
int minorAxis = min<int>(pupil.size.width, pupil.size.height);
int delta = 0.15*minorAxis;
cv::Point c = pupil.center;
float delta = 0.15f*pupil.minorAxis();
//#define DBG_OUTLINE_CONTRAST
#ifdef DBG_OUTLINE_CONTRAST
cv::Mat tmp;
cv::cvtColor(frame, tmp, CV_GRAY2BGR);
cv::ellipse(tmp, pupil, cv::Scalar(0,255,255));
cv::Scalar lineColor;
#endif
int evaluated = 0;
int validCount = 0;
vector<Point> outlinePoints = ellipse2Points(pupil, 10);
for (auto p=outlinePoints.begin(); p!=outlinePoints.end(); p++) {
int dx = p->x - c.x;
int dy = p->y - c.y;
Point &pc = *p;
int dx = pupil.center.x - p->x;
int dy = pupil.center.y - p->y;
float a = 0;
if (dx != 0)
a = dy / (float) dx;
float b = c.y - a*c.x;
float r = delta / sqrt( pow(dx,2) + pow(dy,2) );
Point2f d = { roundf(r * dx), roundf(r * dy) };
Point2f start = Point2f(*p) - d;
Point2f end = Point2f(*p) + d;
if (a == 0)
evaluated++;
if (! ( boundaries.contains(start) && boundaries.contains(end) ) )
continue;
if ( abs(dx) > abs(dy) ) {
int sx = p->x - delta;
int ex = p->x + delta;
int sy = std::roundf(a*sx + b);
int ey = std::roundf(a*ex + b);
cv::Point start = { sx, sy };
cv::Point end = { ex, ey };
evaluated++;
if (!boundaries.contains(start) || !boundaries.contains(end) )
continue;
LineIterator inner(frame, start, pc);
LineIterator outer(frame, pc, end);
float m1, m2, count;
float innerMean = 0;
for (int i=0; i<inner.count; i++, ++inner)
innerMean += *(*inner);
innerMean /= inner.count;
m1 = count = 0;
for (int x=sx; x<p->x; x++)
m1 += frame.ptr<uchar>( (int) std::roundf(a*x+b) )[x];
m1 = std::roundf( m1 / delta );
m2 = count = 0;
for (int x=p->x+1; x<=ex; x++) {
m2 += frame.ptr<uchar>( (int) std::roundf(a*x+b) )[x];
}
m2 = std::roundf( m2 / delta );
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,0,255);
#endif
if (p->x < c.x) {// leftwise point
if (m1 > m2+bias) {
validCount ++;
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,255,0);
#endif
}
} else {// rightwise point
if (m2 > m1+bias) {
validCount++;
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,255,0);
#endif
}
}
float outerMean = 0;
for (int i=0; i<outer.count; i++, ++outer)
outerMean += *(*outer);
outerMean /= outer.count;
#ifdef DBG_OUTLINE_CONTRAST
cv::line(tmp, start, end, lineColor);
#endif
} else {
int sy = p->y - delta;
int ey = p->y + delta;
int sx = std::roundf((sy - b)/a);
int ex = std::roundf((ey - b)/a);
cv::Point start = { sx, sy };
cv::Point end = { ex, ey };
evaluated++;
if (!boundaries.contains(start) || !boundaries.contains(end) )
continue;
float m1, m2, count;
m1 = count = 0;
for (int y=sy; y<p->y; y++)
m1 += frame.ptr<uchar>(y)[ (int) std::roundf((y-b)/a) ];
m1 = std::roundf( m1 / delta );
m2 = count = 0;
for (int y=p->y+1; y<=ey; y++)
m2 += frame.ptr<uchar>(y)[ (int) std::roundf((y-b)/a) ];
m2 = std::roundf( m2 / delta );
if (innerMean > outerMean + bias)
validCount++;
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,0,255);
#endif
if (p->y < c.y) {// upperwise point
if (m1 > m2+bias) {
validCount++;
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,255,0);
#endif
}
} else {// bottomwise point
if (m2 > m1+bias) {
validCount++;
#ifdef DBG_OUTLINE_CONTRAST
lineColor = cv::Scalar(0,255,0);
if (innerMean > outerMean + bias)
line(tmp, start, end, Scalar(0,255,0));
else
line(tmp, start, end, Scalar(0,0,255));
#endif
}
}
#ifdef DBG_OUTLINE_CONTRAST
cv::line(tmp, start, end, lineColor);
#endif
}
}
if (evaluated == 0)
return 0;
......
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