7 #include <sensor_msgs/image_encodings.hpp>
8 #include <std_msgs/msg/header.hpp>
10 #include <opencv2/imgproc/imgproc.hpp>
21 #include <opencv2/opencv.hpp>
22 #include <opencv2/imgproc.hpp>
23 #include <opencv2/core/types.hpp>
25 using namespace ::std::literals;
32 using std::placeholders::_1;
35 log(
"StopLineDetectorNode: Initializing...");
37 std::string configPath =
"settings/onstartup_startstopline.json";
39 json& settingsJson = (*settingsJsonSPtr)[
"settings"];
59 rclcpp::QoS qos_params = get_qos_profile(QOS_BEST_EFFORT);
65 rclcpp::QoS qos_params = get_qos_profile(QOS_BEST_EFFORT);
93 std::shared_ptr<cv_bridge::CvImage const> cvImgSPtr = cv_bridge::toCvShare(msg, sensor_msgs::image_encodings::BGR8);
95 assert(cvImgSPtr->image.cols == 512 && cvImgSPtr->image.rows == 256);
97 cv::Mat undistortedImage;
98 undistortedImage.create(256, 512, cvImgSPtr->image.type());
101 cv::Mat undistortedTopViewImage;
102 undistortedImage.create(256, 512, cvImgSPtr->image.type());
106 bool stopLineDetected =
false;
110 height = undistortedTopViewImage.rows * 0.3f;
111 yOffset = undistortedTopViewImage.rows * 0.55f;
112 cv::Rect roiForCropStopLine = Rect(undistortedTopViewImage.cols * 0.4f, yOffset, undistortedTopViewImage.cols * 0.25f, height);
113 cv::Mat croppedImageForStartStopLineDetection = undistortedTopViewImage(roiForCropStopLine);
114 cv::Mat copiedImageForStopLineDetec = croppedImageForStartStopLineDetection.clone();
115 stopLineDetected = this->
detect_stopline(copiedImageForStopLineDetec, msg->header);
119 bool startLineDetected =
false;
121 height = undistortedTopViewImage.rows * 0.2f;
122 yOffset = undistortedTopViewImage.rows * 0.6f;
123 cv::Rect roiForCrop = Rect(undistortedTopViewImage.cols * 0.2f, yOffset, undistortedTopViewImage.cols * 0.4f, height);
124 cv::Mat croppedImageForStartLineDetection = undistortedTopViewImage(roiForCrop);
125 startLineDetected = this->
detect_startline(croppedImageForStartLineDetection, msg->header);
128 if(startLineDetected || stopLineDetected) {
129 log(
"Start or Stopline detected: Sending message...");
130 std::unique_ptr<StopLineType> lineMessageUPtr = std::make_unique<StopLineType>();
132 if(stopLineDetected && startLineDetected) {
133 stopLineDetected =
false;
136 lineMessageUPtr->header.stamp = msg->header.stamp;
137 lineMessageUPtr->stopline_flag = stopLineDetected;
138 lineMessageUPtr->stopline_distance = stopLineDetected ? 0.5f : -1.f;
140 lineMessageUPtr->startline_flag = startLineDetected;
141 lineMessageUPtr->startline_distance = startLineDetected ? 0.5f : -1.f;
150 bool stopLineDetected =
false;
154 assert(image.channels() > 1);
155 cv::cvtColor(image, temp, cv::COLOR_BGR2GRAY);
156 threshold(temp, greyImage, 200, 255, CV_THRESH_BINARY);
160 Canny(greyImage, inputImage, 60, 200, 3);
163 cv::cvtColor(inputImage, debugImage, CV_GRAY2BGR);
166 std::vector<cv::Vec4i> p_lines;
168 cv::HoughLinesP( inputImage, p_lines,
174 std::vector<cv::Vec4i> p_linesPostprocessed;
175 p_linesPostprocessed.reserve(p_lines.size());
179 for(
auto const& line : p_lines) {
180 if(std::fabs(line[1] - line[3]) < yTolerance && std::fabs(line[0] - line[2]) > xMinLength) {
181 p_linesPostprocessed.push_back(line);
185 if(p_linesPostprocessed.size() > 0) {
186 stopLineDetected =
true;
190 if(p_linesPostprocessed.size() > 0)
log_debug(
"Detected StopLines: ", p_linesPostprocessed.size());
194 for (
const cv::Vec4i& l : p_linesPostprocessed) {
195 #ifndef CV_VERSION_EPOCH
196 cv::line(debugImage, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255, 0, 0), 3, cv::LINE_AA);
198 cv::line(debugImage, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255, 0, 0), 3, CV_AA);
203 std::shared_ptr<sensor_msgs::msg::Image> msgImgSPtr = std::make_shared<sensor_msgs::msg::Image>();
204 cv_bridge::CvImage m_bridgeImg = cv_bridge::CvImage(header, sensor_msgs::image_encodings::BGR8, debugImage);
205 m_bridgeImg.toImageMsg(*msgImgSPtr);
209 return stopLineDetected;
215 cv::Mat& frame = image;
216 bool startLineDetected =
false;
221 cv::cvtColor(frame, temp, cv::COLOR_BGR2GRAY);
225 std::vector<cv::Point2f> corners;
226 bool use_harris_detector =
false;
236 double yAverage = 0.0;
237 for(
auto const& corner : corners) {
238 yAverage += corner.y;
240 yAverage /= corners.size();
243 int pointsInAverage = 0;
244 std::vector<cv::Point2f> cornersPostprocessed;
245 cornersPostprocessed.reserve(corners.size());
246 for(
auto const& corner : corners) {
249 cornersPostprocessed.push_back(corner);
255 log_debug(
"StartLine with Detected Corners: ", cornersPostprocessed.size());
257 startLineDetected =
true;
262 for (
const cv::Point2f& corner : cornersPostprocessed)
264 cv::circle(frame, corner, r, cv::Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), -1, 8,
269 std::shared_ptr<sensor_msgs::msg::Image> msgImgSPtr = std::make_shared<sensor_msgs::msg::Image>();
270 cv_bridge::CvImage m_bridgeImg = cv_bridge::CvImage(header, sensor_msgs::image_encodings::BGR8, frame);
271 m_bridgeImg.toImageMsg(*msgImgSPtr);
275 return startLineDetected;
279 log(
"[StopLineDetection] NEW PARAMETERS");
281 rcl_interfaces::msg::SetParametersResult result;
282 result.successful =
true;
285 for (
const auto ¶m: parameters) {
286 if (param.get_name() ==
"stopline.hough_lines_minLineLength") {
287 if(check_parameter<int>(param, result, 1, 1000)) {
291 else if (param.get_name() ==
"stopline.hough_lines_maxLineGap") {
292 if(check_parameter<int>(param, result, 1, 1000)) {
296 else if (param.get_name() ==
"startline.whiteness_lower_threshold") {
297 if(check_parameter<int>(param, result, 1, 1000)) {
301 else if (param.get_name() ==
"startline.feature_quality_level") {
302 if(check_parameter<double>(param, result, 0, 1)) {
306 else if (param.get_name() ==
"startline.feature_min_distance") {
307 if(check_parameter<int>(param, result, 0, 1000)) {
311 else if (param.get_name() ==
"startline.feature_block_size") {
312 if(check_parameter<int>(param, result, 0, 1000)) {
316 else if (param.get_name() ==
"startline.feature_k") {
317 if(check_parameter<double>(param, result, 0, 5)) {
321 else if (param.get_name() ==
"startline.cluster_eps") {
322 if(check_parameter<int>(param, result, 0, 50)) {
326 else if (param.get_name() ==
"startline.points_count_threshold") {
327 if(check_parameter<int>(param, result, 0, 500)) {
331 else if (param.get_name() ==
"stopline.hough_lines_threshold") {
332 if(check_parameter<int>(param, result, 1, 1000)) {
336 result.successful =
false;
337 result.reason +=
"[" + param.get_name() +
"] UNKNOWN param or NOT IMPLEMENTED; ";
341 if(result.successful ==
false) {
342 log_warning(
"[AutopilotNode] Failed to set some parameters. Reasons: ", result.reason);