210 lines
7.2 KiB
C++
210 lines
7.2 KiB
C++
#include "processing.h"
|
|
|
|
|
|
|
|
|
|
Processing::Processing(/* args */)
|
|
{
|
|
}
|
|
|
|
Processing::~Processing()
|
|
{
|
|
}
|
|
|
|
void Processing::filterReflections(FrameData& frameData)
|
|
{
|
|
//Try to filter reflections from the frame data.
|
|
|
|
std::vector<int> indicesToDelete;
|
|
for(int i = 0; i < frameData.contours.size(); i++)
|
|
{
|
|
|
|
// First approach: correct contours nearly fill their bounding box.
|
|
// So delete all contours with an area smaller than 75% of their bounding box
|
|
double contourArea = cv::contourArea(frameData.contours[i], false);
|
|
double boundingBoxArea = double(frameData.boundingBoxes[i].width*frameData.boundingBoxes[i].height);
|
|
double minRatio = 0.75;
|
|
if(boundingBoxArea/contourArea < minRatio)
|
|
{
|
|
indicesToDelete.push_back(i);
|
|
continue;
|
|
}
|
|
|
|
// Second approach: The contour should be nearly convex
|
|
// So delete all contours with an area smaller than 95% of their convex hull.
|
|
std::vector<Point> hull;
|
|
cv::convexHull(frameData.contours[i], hull);
|
|
double hullArea = cv::contourArea(hull, false);
|
|
double minRatioHull = 0.95;
|
|
if(contourArea/boundingBoxArea < minRatio)
|
|
{
|
|
indicesToDelete.push_back(i);
|
|
continue;
|
|
}
|
|
|
|
}
|
|
|
|
//reverse the vector with the indices so the order isn't messed up when deleting:
|
|
std::reverse(indicesToDelete.begin(), indicesToDelete.end());
|
|
for(int index : indicesToDelete)
|
|
{
|
|
frameData.boundingBoxes.erase(frameData.boundingBoxes.begin() + index);
|
|
frameData.contours.erase(frameData.contours.begin() + index);
|
|
frameData.leftEdges.erase(frameData.leftEdges.begin() + index);
|
|
frameData.middlePoints.erase(frameData.middlePoints.begin() + index);
|
|
}
|
|
return;
|
|
}
|
|
|
|
bool Processing::checkIntersection(const std::vector<std::vector<Point>>& lines, const std::vector<Point>& outline)
|
|
{
|
|
|
|
/* TODO:
|
|
* Was ich mir hier vorstelle:
|
|
* Wir haben die konturen und die hough linien
|
|
* Konturen haben schwäche mit Reflektionen, hough linien sind unvollständig.
|
|
* Irgendwie sollten die beiden Datensätze gemerged werden, um das "gute" aus beiden zu vereinen.
|
|
* Evtl in richtung "Schau den Bereich der Contour (+ Toleranz?) im hough bild an. Wenn keine Linie im Bereich ist, ist die Contour eine Reflektion"
|
|
*
|
|
* Aktuell nehmen wir die abkürzung, die segmente rauszuwerfen, sobald keine Linie im Bild ist.
|
|
* Funktioniert für unsere Daten auch ziemlich gut
|
|
*/
|
|
|
|
if(lines.size() == 0)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Processing::calcAngles(FrameData &data, int imageColums, int imageRows, bool turnLeft)
|
|
{
|
|
|
|
if(data.contours.size() > 0)
|
|
{
|
|
int angle = 0;
|
|
int index;
|
|
if(turnLeft){
|
|
// get the most left/right contour
|
|
int leftmostEdge = imageColums;
|
|
|
|
for (int i = 0; i < data.leftEdges.size(); i++)
|
|
{
|
|
int edge = data.leftEdges[i].x;
|
|
|
|
if (edge <= leftmostEdge)
|
|
{
|
|
leftmostEdge = edge;
|
|
index = i;
|
|
}
|
|
}
|
|
}else
|
|
{
|
|
int rightmostEdge = 0;
|
|
|
|
for (int i = 0; i < data.leftEdges.size(); i++)
|
|
{
|
|
int edge = data.leftEdges[i].x;
|
|
|
|
if (edge >= rightmostEdge)
|
|
{
|
|
rightmostEdge = edge;
|
|
index = i;
|
|
}
|
|
}
|
|
}
|
|
// Find the Top-Left and Buttom-Left Point of the Contour
|
|
|
|
std::vector<cv::Point> leftMostContour = data.contours[index];
|
|
int xleftButtom = imageColums;
|
|
int xleftTop = imageColums;
|
|
int yButtom = data.boundingBoxes[index].y;
|
|
int yTop = data.boundingBoxes[index].height;
|
|
|
|
for (int i = 0; i < leftMostContour.size(); i++){
|
|
if(leftMostContour[i].y == 0 && leftMostContour[i].x < xleftButtom)
|
|
{
|
|
xleftButtom = leftMostContour[i].x;
|
|
}else if(leftMostContour[i].y > yTop -4 && leftMostContour[i].x < xleftTop){
|
|
xleftTop = leftMostContour[i].x;
|
|
}
|
|
}
|
|
|
|
// calculate angle
|
|
int deltaX = abs(xleftButtom - xleftTop);
|
|
int deltaY = yTop;
|
|
angle = Calcs::calcAngle(deltaX, deltaY);
|
|
|
|
//Write to Data
|
|
data.angle = angle;
|
|
data.index = index;
|
|
}
|
|
}
|
|
|
|
|
|
void Processing::processImage(Mat& inputPicture, int thresholdBinary, int gaussKernelSize)
|
|
{
|
|
//Idea here is: Processing module consists of two methods:
|
|
// One (this) to do all kinds of stuff to the picture (grayscale conversion, threshold, gauss etc etc)
|
|
// And one (the other one) to segment the lines.
|
|
// No return value here as the input is passed by reference -> directly modified.
|
|
cvtColor(inputPicture, inputPicture, COLOR_BGR2GRAY);
|
|
GaussianBlur(inputPicture, inputPicture, Size(gaussKernelSize, gaussKernelSize), 0);
|
|
threshold(inputPicture, inputPicture, thresholdBinary, 255, THRESH_BINARY);
|
|
|
|
//Perform an opening
|
|
Mat kernel(5,5, CV_8UC1,1);
|
|
morphologyEx(inputPicture, inputPicture, 2, kernel);
|
|
}
|
|
|
|
FrameData Processing::calculateLineSegments(Mat& inputPicture, const cv::Rect& roi)
|
|
{
|
|
|
|
FrameData data;
|
|
Mat inputPictureRoi = inputPicture(roi);
|
|
cv::findContours(inputPictureRoi, data.contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
|
|
|
|
vector<Vec4i> lines;
|
|
std::vector<std::vector<Point>> houghLines;
|
|
Canny(inputPicture, inputPicture, 50, 100, 3);
|
|
HoughLinesP(inputPicture, lines, 1, CV_PI/180, 100, 30, 150);
|
|
//Draw lines
|
|
inputPicture = Mat::zeros(inputPicture.size().height, inputPicture.size().width, CV_8UC1);
|
|
|
|
for( size_t i = 0; i < lines.size(); i++ )
|
|
{
|
|
line( inputPicture, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), Scalar(255,255,255), 3, 8 );
|
|
std::vector<Point> line;
|
|
line.push_back(Point(lines[i][0], lines[i][1]));
|
|
line.push_back(Point(lines[i][2], lines[i][3]));
|
|
houghLines.push_back(line);
|
|
}
|
|
|
|
|
|
//Delete the areas that are too small
|
|
auto iterator = data.contours.begin();
|
|
while(iterator != data.contours.end())
|
|
{
|
|
if (contourArea(*iterator) < 7000)
|
|
{
|
|
iterator = data.contours.erase(iterator);
|
|
}
|
|
else if (!checkIntersection(houghLines, *iterator))
|
|
{
|
|
iterator = data.contours.erase(iterator);
|
|
}
|
|
else
|
|
{
|
|
//Check for intersection with lines:
|
|
Rect boundingBox = boundingRect(*iterator);
|
|
boundingBox.x += roi.x;
|
|
boundingBox.y += roi.y;
|
|
data.boundingBoxes.push_back(boundingBox);
|
|
data.middlePoints.push_back(Point(boundingBox.x+boundingBox.width/2, boundingBox.y+boundingBox.height/2));
|
|
data.leftEdges.push_back(Point(boundingBox.x, boundingBox.y+boundingBox.height/2));
|
|
++iterator;
|
|
}
|
|
}
|
|
return data;
|
|
}
|