Projektarbeit Line Following Robot bei Prof. Chowanetz im WS22/23
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

processing.cpp 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include "processing.h"
  2. Processing::Processing(/* args */)
  3. {
  4. }
  5. Processing::~Processing()
  6. {
  7. }
  8. static double angle( Point pt1, Point pt2, Point pt0 )
  9. {
  10. double dx1 = pt1.x - pt0.x;
  11. double dy1 = pt1.y - pt0.y;
  12. double dx2 = pt2.x - pt0.x;
  13. double dy2 = pt2.y - pt0.y;
  14. return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
  15. }
  16. void Processing::filterReflections(FrameData& frameData)
  17. {
  18. //Try to filter reflections from the frame data.
  19. std::vector<int> indicesToDelete;
  20. for(int i = 0; i < frameData.contours.size(); i++)
  21. {
  22. // First approach: correct contours nearly fill their bounding box.
  23. // So delete all contours with an area smaller than 75% of their bounding box
  24. double contourArea = cv::contourArea(frameData.contours[i], false);
  25. double boundingBoxArea = double(frameData.boundingBoxes[i].width*frameData.boundingBoxes[i].height);
  26. double minRatio = 0.75;
  27. if(boundingBoxArea/contourArea < minRatio)
  28. {
  29. indicesToDelete.push_back(i);
  30. continue;
  31. }
  32. // Second approach: The contour should be nearly convex
  33. // So delete all contours with an area smaller than 95% of their convex hull.
  34. std::vector<Point> hull;
  35. cv::convexHull(frameData.contours[i], hull);
  36. double hullArea = cv::contourArea(hull, false);
  37. double minRatioHull = 0.95;
  38. if(contourArea/boundingBoxArea < minRatio)
  39. {
  40. indicesToDelete.push_back(i);
  41. continue;
  42. }
  43. // Third approach:
  44. // Calculate the HoughLinesP of the contour.
  45. // There should be 4 lines
  46. // This one is not really working yet.
  47. Rect boundingRect = cv::boundingRect(frameData.contours[i]);
  48. Point offset(-boundingRect.x, -boundingRect.y);
  49. Mat contourMat = Mat::zeros(frameData.boundingBoxes[i].height, frameData.boundingBoxes[i].width, CV_8UC1);
  50. drawContours(contourMat, frameData.contours, i, Scalar(255,255,255), 1, 8, noArray(), 0, offset);
  51. std::vector<Vec4i> linesP;
  52. HoughLinesP(contourMat, linesP, 1, CV_PI/180, 20, 10, 5 );
  53. //imshow("Some window", contourMat);
  54. if(linesP.size() < 4)
  55. {
  56. //indicesToDelete.push_back(i);
  57. //continue;
  58. //std::cout << linesP.size();
  59. }
  60. }
  61. //reverse the vector with the indices so the order isn't messed up when deleting:
  62. std::reverse(indicesToDelete.begin(), indicesToDelete.end());
  63. for(int index : indicesToDelete)
  64. {
  65. frameData.boundingBoxes.erase(frameData.boundingBoxes.begin() + index);
  66. frameData.contours.erase(frameData.contours.begin() + index);
  67. frameData.leftEdges.erase(frameData.leftEdges.begin() + index);
  68. frameData.middlePoints.erase(frameData.middlePoints.begin() + index);
  69. }
  70. return;
  71. }
  72. void Processing::processImage(Mat& inputPicture, int thresholdBinary, int gaussKernelSize)
  73. {
  74. //Idea here is: Processing module consists of two methods:
  75. // One (this) to do all kinds of stuff to the picture (grayscale conversion, threshold, gauss etc etc)
  76. // And one (the other one) to segment the lines.
  77. // No return value here as the input is passed by reference -> directly modified.
  78. cvtColor(inputPicture, inputPicture, COLOR_BGR2GRAY);
  79. GaussianBlur(inputPicture, inputPicture, Size(gaussKernelSize, gaussKernelSize), 0);
  80. threshold(inputPicture, inputPicture, thresholdBinary, 255, THRESH_BINARY);
  81. //Perform an opening
  82. Mat kernel(5,5, CV_8UC1,1);
  83. morphologyEx(inputPicture, inputPicture, 2, kernel);
  84. }
  85. FrameData Processing::calculateLineSegments(Mat& inputPicture, const cv::Rect& roi)
  86. {
  87. FrameData data;
  88. Mat inputPictureRoi = inputPicture(roi);
  89. cv::findContours(inputPictureRoi, data.contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
  90. /* TODO:
  91. * Was ich mir hier vorstelle:
  92. * Wir haben die konturen und die hough linien
  93. * Konturen haben schwäche mit Reflektionen, hough linien sind unvollständig.
  94. * Irgendwie sollten die beiden Datensätze gemerged werden, um das "gute" aus beiden zu vereinen.
  95. * Evtl in richtung "Schau den Bereich der Contour (+ Toleranz?) im hough bild an. Wenn keine Linie im Bereich ist, ist die Contour eine Reflektion"
  96. */
  97. vector<Vec4i> lines;
  98. Canny(inputPicture, inputPicture, 50, 100, 3);
  99. HoughLinesP(inputPicture, lines, 1, CV_PI/180, 100, 30, 150);
  100. //Draw lines
  101. inputPicture = Mat::zeros(inputPicture.size().height, inputPicture.size().width, CV_8UC1);
  102. for( size_t i = 0; i < lines.size(); i++ )
  103. {
  104. line( inputPicture, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), Scalar(255,255,255), 3, 8 );
  105. }
  106. //Delete the areas that are too small
  107. auto iterator = data.contours.begin();
  108. while(iterator != data.contours.end())
  109. {
  110. if (contourArea(*iterator) < 3500)
  111. {
  112. iterator = data.contours.erase(iterator);
  113. }
  114. else
  115. {
  116. Rect boundingBox = boundingRect(*iterator);
  117. boundingBox.x += roi.x;
  118. boundingBox.y += roi.y;
  119. data.boundingBoxes.push_back(boundingBox);
  120. data.middlePoints.push_back(Point(boundingBox.x+boundingBox.width/2, boundingBox.y+boundingBox.height/2));
  121. data.leftEdges.push_back(Point(boundingBox.x, boundingBox.y+boundingBox.height/2));
  122. ++iterator;
  123. }
  124. }
  125. return data;
  126. }