Files
AdvancedVision/NeuralDetector/FeatureExtractor.cpp
T
2017-12-20 16:41:32 +01:00

176 lines
3.7 KiB
C++

#include "FeatureExtractor.h"
FeatureExtractor::FeatureExtractor(vector<Point> contour)
{
FeatureExtractor::contour = contour;
rect = minAreaRect(contour);
}
FeatureExtractor::~FeatureExtractor()
{
}
void FeatureExtractor::Extract(Mat &ref)
{
//Bepaal verschillende features
double ar = AspectRatio();
double cr = Circularity();
double bendingEnergy = getBendingEnergy();
double convexHullBendingEnergy = getConvexHullBendingEnergy();
double radius = getMinEnclosingCircleRadius();
double perimeter = getPerimeter();
double numDefects = convexDefects();
ref = (Mat_<double>(1, 5) << 1.0, ar, cr / 10.0, convexHullBendingEnergy / 100.0, numDefects / 100.0);
}
//Rotatie onafhankelijke aspect ratio
double FeatureExtractor::AspectRatio()
{
double ar = 0;
if(rect.size.width > rect.size.height)
ar = (rect.size.height / rect.size.width);
else
ar = (rect.size.width / rect.size.height);
return ar;
}
//Oppervlakte van de minimale circle gedeeld door het oppervlakte van de bounding box
double FeatureExtractor::Circularity()
{
double radius = getMinEnclosingCircleRadius();
double carea = radius * radius * M_PI;
double rectarea = rect.size.width * rect.size.height;
double cir = carea / rectarea;
return cir;
}
//Rotated bounding box om het object
RotatedRect FeatureExtractor::Rectangle()
{
return rect;
}
//De radius van de minimale circle
double FeatureExtractor::getMinEnclosingCircleRadius()
{
float radius;
Point2f center;
minEnclosingCircle(contour, center, radius);
double rad = (double)radius;
return rad;
}
//De lengte van het contour
double FeatureExtractor::getPerimeter()
{
double per = arcLength(contour, true);
return per;
}
//De bending energy van de contour
double FeatureExtractor::getBendingEnergy()
{
double energy = 0;
int dir = 0;
int prevdir = 0;
Point previousPoint = contour[contour.size() - 1];
for (Point p : contour)
{
dir = discoverNextRelativeDirection(previousPoint, p);
energy += (dir - prevdir + 8) % 8;
prevdir = dir;
previousPoint = p;
}
return energy;
}
//De bending energy van de convex hull
double FeatureExtractor::getConvexHullBendingEnergy() {
vector<Point> convex;
convexHull(contour, convex);
double energy = 0;
int dir = 0;
int prevdir = 0;
Point previousPoint = convex[convex.size() - 1];
for (Point p : convex)
{
dir = discoverNextRelativeDirection(previousPoint, p);
energy += (dir - prevdir + 8) % 8;
prevdir = dir;
previousPoint = p;
}
return energy;
}
//Bending energy support methode, zoekt naar de hoek tussen twee pixels volgens de freeman code
int FeatureExtractor::discoverNextRelativeDirection(const cv::Point &pos, const cv::Point &target)
{
for (int i = 0; i < 8; i++) {
int dir = i;
int newX = pos.x + rotateX[dir];
int newY = pos.y + rotateY[dir];
if (target.x == newX && target.y == newY)
return dir;
}
return -1;
}
//Het aantal defecten die in de convexhull zitten
double FeatureExtractor::convexDefects()
{
vector<int> hullsI(contour.size()); // Indices to contour points
vector<Vec4i> defects;
convexHull(contour, hullsI, false);
convexityDefects(contour, hullsI, defects);
return (double)defects.size();
}
//Statische help functie om het contour te bepalen in een plaatje
void FeatureExtractor::findContour(Mat &image, vector<Point> &contour)
{
Mat canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
Canny(image, canny_output, 20, 150, 3);
findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
int large = 0;
int contouridx = -1;
for (int i = 0; i < contours.size(); i++)
{
double a = arcLength(contours[i], false);
if (a > large)
{
large = a;
contouridx = i;
}
}
contour = contours[contouridx];
}