ipa_coverage_planning 算法解读(四) RoomRotator::computeRoomMainDirection


avatar
GuoYulong 2024-07-19 262

RoomRotator::computeRoomMainDirection

作为比较单独且核心的一个算法,这里单独拿出来方便后续查看

复制代码
  1. double RoomRotator::computeRoomMainDirection(const cv::Mat& room_map, const double map_resolution)
  2. {
  3. const double map_resolution_inverse = 1./map_resolution;
  4.  
  5. // compute Hough transform on edge image of the map
  6. cv::Mat edge_map;
  7. cv::Canny(room_map, edge_map, 50, 150, 3);
  8. std::vector<cv::Vec4i> lines;
  9. double min_line_length = 1.0; // in [m]
  10. for (; min_line_length > 0.1; min_line_length -= 0.2)
  11. {
  12. cv::HoughLinesP(edge_map, lines, 1, CV_PI/180, min_line_length*map_resolution_inverse, min_line_length*map_resolution_inverse, 1.5*min_line_length*map_resolution_inverse);
  13. cv::Mat room_hough = edge_map.clone();
  14. for (size_t i=0; i<lines.size(); ++i)
  15. {
  16. cv::Point p1(lines[i][0], lines[i][1]), p2(lines[i][2], lines[i][3]);
  17. cv::line(room_hough, p1, p2, cv::Scalar(128), 2);
  18. }
  19. //cv::imshow("room_hough", room_hough);
  20. if (lines.size() >= 4)
  21. break;
  22. }
  23. // setup a histogram on the line directions weighted by their length to determine the major direction
  24. Histogram<double> direction_histogram(0, CV_PI, 36);
  25. for (size_t i=0; i<lines.size(); ++i)
  26. {
  27. double dx = lines[i][2] - lines[i][0];
  28. double dy = lines[i][3] - lines[i][1];
  29. if(dy*dy+dx*dx > 0.0)
  30. {
  31. double current_direction = std::atan2(dy, dx);
  32. while (current_direction < 0.)
  33. current_direction += CV_PI;
  34. while (current_direction > CV_PI)
  35. current_direction -= CV_PI;
  36. direction_histogram.addData(current_direction, sqrt(dy*dy+dx*dx));
  37. //std::cout << " dx=" << dx << " dy=" << dy << " dir=" << current_direction << " len=" << sqrt(dy*dy+dx*dx) << std::endl;
  38. }
  39. }
  40. return direction_histogram.getMaxBinPreciseVal();
  41. }

详细解释:
计算分辨率的倒数,用于长度单位转换
const double map_resolution_inverse = 1./map_resolution;

使用 cv::Canny 函数对房间地图进行边缘检测,得到边缘图 edge_map
cv::Mat edge_map;
cv::Canny(room_map, edge_map, 50, 150, 3);

使用霍夫变化检测直线

复制代码
  1. std::vector<cv::Vec4i> lines;
  2. double min_line_length = 1.0; // in [m]
  3. for (; min_line_length > 0.1; min_line_length -= 0.2)
  4. {
  5. cv::HoughLinesP(edge_map, lines, 1, CV_PI/180, min_line_length*map_resolution_inverse, min_line_length*map_resolution_inverse, 1.5*min_line_length*map_resolution_inverse);
  6. cv::Mat room_hough = edge_map.clone();
  7. for (size_t i=0; i<lines.size(); ++i)
  8. {
  9. cv::Point p1(lines[i][0], lines[i][1]), p2(lines[i][2], lines[i][3]);
  10. cv::line(room_hough, p1, p2, cv::Scalar(128), 2);
  11. }
  12. //cv::imshow("room_hough", room_hough);
  13. if (lines.size() >= 4)
  14. break;
  15. }

使用 Histogram 类构建一个直方图,记录所有检测到的直线的方向和长度。
Histogram direction_histogram(0, CV_PI, 36);

遍历所有直线,计算它们的方向,并更新方向直方图。最后,返回方向直方图中最大值对应的方向,即为房间地图的主要方向。

复制代码
  1. for (size_t i=0; i<lines.size(); ++i)
  2. {
  3. double dx = lines[i][2] - lines[i][0];
  4. double dy = lines[i][3] - lines[i][1];
  5. if(dy*dy+dx*dx > 0.0)
  6. {
  7. double current_direction = std::atan2(dy, dx);
  8. while (current_direction < 0.)
  9. current_direction += CV_PI;
  10. while (current_direction > CV_PI)
  11. current_direction -= CV_PI;
  12. direction_histogram.addData(current_direction, sqrt(dy*dy+dx*dx));
  13. //std::cout << " dx=" << dx << " dy=" << dy << " dir=" << current_direction << " len=" << sqrt(dy*dy+dx*dx) << std::endl;
  14. }
  15. }
  16. return direction_histogram.getMaxBinPreciseVal();

相关阅读

注意!!!

站点域名更新!!!部分文章图片等由于域名问题无法显示!!!

通知!!!

站点域名更新!!!部分文章图片等由于域名问题无法显示!!!