|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- #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 index;
- // get the most left/right contour
-
- int leftmostEdge = imageColums;
- int rightmostEdge = 0;
-
- for (int i = 0; i < data.leftEdges.size(); i++)
- {
- int edge = data.leftEdges[i].x;
-
- if (edge <= leftmostEdge && turnLeft)
- {
- leftmostEdge = edge;
- index = i;
- }
- else if(edge >= rightmostEdge && !turnLeft)
- {
- rightmostEdge = edge;
- index = i;
- }
- }
-
- // Find the Top-Left and Bottom-Left Point of the Contour
-
- std::vector<cv::Point> leftMostContour = data.contours[index];
-
- /*
- Not going to dive into that part to fix it.
- Trying to use centroid instead.
- int xleftBottom = imageColums;
- int xleftTop = imageColums;
- int yBottom = 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 < xleftBottom)
- {
- xleftBottom = leftMostContour[i].x;
- }
- else if(leftMostContour[i].y > yTop -4 && leftMostContour[i].x < xleftTop)
- {
- xleftTop = leftMostContour[i].x;
- }
- }
-
- // calculate angle
- int deltaX = abs(xleftBottom - xleftTop);
- int deltaY = yTop;
- angle = Calcs::calcAngle(deltaX, deltaY);
- */
-
- //Get the contours center using moments:
- cv::Moments moments=cv::moments(leftMostContour);
- LFRPoint contourCenter(moments.m10/moments.m00, moments.m01/moments.m00);
- LFRPoint imageCenter(double(imageColums)/2.0, double(imageRows)/2.0);
- LFRPoint focusPoint(imageCenter.x, imageCenter.y+1000.0);
-
- LFRVector a(imageCenter-focusPoint);
- LFRVector b(contourCenter-focusPoint);
-
- double angle = a.angle(b);
- if (b.x < 0.0)
- {
- angle *= -1.0;
- }
-
- //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;
- }
|