停车场识别

// /*car*/
// #include <ros/ros.h>
// #include <image_transport/image_transport.h>
// #include <cv_bridge/cv_bridge.h>
// #include <sensor_msgs/image_encodings.h>
// #include <opencv2/opencv.hpp>
// #include <iostream>
// #include <ros/package.h>
// #include <string>
// #include <vector>
// #include <map>
// #include <set>

// using namespace cv;
// using namespace std;

// // 定义全局变量
// static int max_value = 255;
// static int min_value = 0;
// static int gray_2_canny_max = 230;
// static int gray_2_canny_min= 200;

// static Mat car_Image;

// struct Line {
//     int x1, y1, x2, y2;

//     // 定义 operator< 运算符
//     bool operator<(const Line& other) const {
//         if (x1 != other.x1) {
//             return x1 < other.x1;
//         }
//         if (y1 != other.y1) {
//             return y1 < other.y1;
//         }
//         if (x2 != other.x2) {
//             return x2 < other.x2;
//         }
//         return y2 < other.y2;
//     }
// };

// // 定义一个函数用于绘制停车位
// std::pair<cv::Mat, std::map<std::tuple<int, int, int, int>, int>> draw_parking
//       (
//     const cv::Mat& image, 
//     const std::map<int, std::vector<int>>& rects, 
//     bool make_copy = true
//       ) 
      
// {
//     cv::Mat new_image;
//     if (make_copy) {
//         new_image = image.clone();
//     } else {
//         new_image = image;
//     }

//     double gap = 15.5;
//     std::map<std::tuple<int, int, int, int>, int> spot_dict;
//     int tot_spots = 0;

//     // 微调参数
//     std::map<int, int> adj_x1 = {
//         {0, -8}, {1, -15}, {2, -15}, {3, -15}, {4, -15}, {5, -15}, {6, -15}, {7, -15}, {8, -10}, {9, -10}, {10, -10}, {11, 0}
//     };
//     std::map<int, int> adj_x2 = {
//         {0, 0}, {1, 15}, {2, 15}, {3, 15}, {4, 15}, {5, 15}, {6, 15}, {7, 15}, {8, 10}, {9, 10}, {10, 10}, {11, 0}
//     };
//     std::map<int, int> fine_tune_y = {
//         {0, 4}, {1, -2}, {2, 3}, {3, 1}, {4, -3}, {5, 1}, {6, 5}, {7, -3}, {8, 0}, {9, 5}, {10, 4}, {11, 0}
//     };

//     for (const auto& pair : rects) {
//         int key = pair.first;
//         const std::vector<int>& tup = pair.second;

//         int x1 = static_cast<int>(tup[0] + adj_x1[key]);
//         int x2 = static_cast<int>(tup[2] + adj_x2[key]);
//         int y1 = static_cast<int>(tup[1]);
//         int y2 = static_cast<int>(tup[3]);

//         // 绘制矩形
//         cv::rectangle(new_image, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(0, 255, 0), 2);

//         int num_splits = static_cast<int>(std::abs(y2 - y1) / gap);
//         for (int i = 0; i <= num_splits; ++i) {
//             int y = static_cast<int>(y1 + i * gap) + fine_tune_y[key];
//             // 绘制横线
//             cv::line(new_image, cv::Point(x1, y), cv::Point(x2, y), cv::Scalar(255, 0, 0), 2);
//         }

//         if (key > 0 && key < rects.size() - 1) {
//             int x = static_cast<int>((x1 + x2) / 2);
//             // 绘制竖线
//             cv::line(new_image, cv::Point(x, y1), cv::Point(x, y2), cv::Scalar(0, 0, 255), 2);
//         }

//         // 计算停车位数量
//         if (key == 0 || key == rects.size() - 1) {
//             tot_spots += num_splits + 1;
//         } else {
//             tot_spots += 2 * (num_splits + 1);
//         }

//         // 填充车位字典
//         if (key == 0 || key == rects.size() - 1) {
//             for (int i = 0; i <= num_splits; ++i) {
//                 int cur_len = static_cast<int>(spot_dict.size());
//                 int y = static_cast<int>(y1 + i * gap) + fine_tune_y[key];
//                 spot_dict[std::make_tuple(x1, y, x2, y + static_cast<int>(gap))] = cur_len + 1;
//             }
//         } else {
//             for (int i = 0; i <= num_splits; ++i) {
//                 int cur_len = static_cast<int>(spot_dict.size());
//                 int y = static_cast<int>(y1 + i * gap) + fine_tune_y[key];
//                 int x = static_cast<int>((x1 + x2) / 2);
//                 spot_dict[std::make_tuple(x1, y, x, y + static_cast<int>(gap))] = cur_len + 1;
//                 spot_dict[std::make_tuple(x, y, x2, y + static_cast<int>(gap))] = cur_len + 2;
//             }
//         }
//     }

   

//     return std::make_pair(new_image, spot_dict);
// }


// // rect_finetune 函数的 C++ 实现
// std::pair<cv::Mat, std::map<int, std::vector<int>>> rect_finetune(
//     const cv::Mat& image, 
//     std::map<int, std::vector<int>> rects, 
//     bool copy_img = true) 
    
//     {
//     cv::Mat image_copy;
//     if (copy_img) {
//         image_copy = image.clone();
//     }

//     // 对矩形框的坐标进行微调
//     for (auto& pair : rects) {
//         int k = pair.first;
//         std::vector<int>& rect = pair.second;

       
//         if (k == 0) {
//             rect[1] -= 10;
//         } 
//         else if (k == 1) {
//             rect[1] -= 10;
//             rect[3] += 10;
//         } 
//         else if (k == 3) {
//             rect[1] += 110;
//             rect[3] += 60;  
//         } 
//         else if (k == 4) {
//             rect[1] += 150;
//             rect[3] += 60;
//         } 
//         else if (k == 5) {
//             rect[1] += 80;
//             rect[3] += 13;
//         }
//         else if (k == 2) {
//             rect[1] -= 4;
//             rect[3] += 13;
//         } 
//         else if (k == 6 || k == 8) {
//             rect[1] -= 18;
//             rect[3] += 12;
//         } 
//         else if (k == 9) {
//             rect[1] += 10;
//             rect[3] += 10;
//         } 
//         else if (k == 10) {
//             rect[1] += 45;
//         } 
//         else if (k == 11) {
//             rect[3] += 45;
//         }
//     }

//     int buff = 8;
//     for (const auto& pair : rects) {
//         int key = pair.first;
//         const std::vector<int>& rect = pair.second;

//         cv::Point tup_topLeft(rect[0] - buff, rect[1]);
//         cv::Point tup_botRight(rect[2] + buff, rect[3]);
//         cv::rectangle(image_copy, tup_topLeft, tup_botRight, cv::Scalar(0, 255, 0), 3);
//     }

//     return std::make_pair(image_copy, rects);
// }


// // 定义比较函数,用于按 x1 和 y1 排序直线
// bool compareLines(const Line& a, const Line& b) {
//     if (a.x1 != b.x1) {
//         return a.x1 < b.x1;
//     }
//     return a.y1 < b.y1;
// }

// // 定义比较函数,用于按 y1 排序直线
// bool compareLinesByY(const Line& a, const Line& b) {
//     return a.y1 < b.y1;
// }

// // identity_blocks 函数,实现与 Python 代码相同的功能
// //pair实质上是一个结构体 pair.first/pair.second
// std::pair<cv::Mat, std::map<int, std::vector<int>>> identity_blocks(const cv::Mat& image, const std::vector<std::vector<int>>& lines, bool make_copy = true) {
//     cv::Mat new_image;
//     if (make_copy) {
//         new_image = image.clone();
//     }

//     // 过滤部分直线
//     std::vector<Line> stayed_lines;
//     for (const auto& line : lines) {
//         int x1 = line[0], y1 = line[1], x2 = line[2], y2 = line[3];
//         if (std::abs(y2 - y1) <= 1 && std::abs(x2 - x1) >= 25 && std::abs(x2 - x1) <= 55) {
//            Line line = {x1, y1, x2, y2};
//           stayed_lines.push_back(line);
//           /*or 
//         stayed_lines.emplace_back(x1, y1, x2, y2);
//           */
//         }
//     }

//     // 对直线按照 x1 排序
//     std::sort(stayed_lines.begin(), stayed_lines.end(), compareLines);

//     // 找到多个列,相当于每列是一排车
//     std::map<int, std::vector<Line>> clusters;//std::map 会根据键的大小自动对元素进行排序
//     int dIndex = 0;
//     int clus_dist = 10;  // 每一列之间的那个距离
//     for (size_t i = 0; i < stayed_lines.size() - 1; ++i) //for 循环的迭代部分并不依赖于自增运算符的返回值++i=i++
//     {
//         int distance = std::abs(stayed_lines[i + 1].x1 - stayed_lines[i].x1);
//         if (distance <= clus_dist) {

// /*map_use*/
//             clusters[dIndex].push_back(stayed_lines[i]);
//             clusters[dIndex].push_back(stayed_lines[i + 1]);

//         } else {
//             ++dIndex;
//         }
//     }
             

// //duanduanduanduanduanduanduanduanduanduan


//     // 得到每列停车位的矩形框
//     std::map<int, std::vector<int>> rects;
//     int i = 0;
//     for (const auto& cluster : clusters) {
//         std::vector<Line> all_list = cluster.second;
//         /*
//         通过这个范围(all_list.begin(), all_list.end())初始化,
//         std::set 会遍历该范围内的所有 Line 对象,将它们插入到 unique_lines 中。
//         在插入过程中,std::set 会自动去重(即如果有重复的 Line 对象,只会保留一个),并根据比较规则对元素进行排序
//         */
//         std::set<Line> unique_lines(all_list.begin(), all_list.end());//set:去重+排序
//         //std::set<Line> 容器 unique_lines 中的元素复制到一个 std::vector<Line> 容器 cleaned 中
//         std::vector<Line> cleaned(unique_lines.begin(), unique_lines.end());

//         // 有 5 个停车位至少
//         if (cleaned.size() > 5) {
//             std::sort(cleaned.begin(), cleaned.end(), compareLinesByY);
//             int avg_y1 = cleaned[0].y1;
//             int avg_y2 = cleaned.back().y1;
//             if (std::abs(avg_y2 - avg_y1) < 15) {
//                 continue;
//             }
//             double avg_x1 = 0, avg_x2 = 0;
//             for (const auto& tup : cleaned) {
//                 avg_x1 += tup.x1;
//                 avg_x2 += tup.x2;
//             }
//             avg_x1 /= cleaned.size();
//             avg_x2 /= cleaned.size();

//             rects[i] = {static_cast<int>(avg_x1), avg_y1, static_cast<int>(avg_x2), avg_y2};
//             ++i;
//         }
//     }
//     std::cout << "Num Parking Lanes: " << rects.size() << std::endl;

//     // 把列矩形画出来
//     int buff = 7;
//     for (const auto& rect : rects) {
//         cv::Point tup_topLeft(rect.second[0] - buff, rect.second[1]);
//         cv::Point tup_botRight(rect.second[2] + buff, rect.second[3]);
//         cv::rectangle(new_image, tup_topLeft, tup_botRight, cv::Scalar(0, 255, 0), 3);
//     }

//     return std::make_pair(new_image, rects);//之前没有创建pair对象,所以这里临时创建对象返回
// }

// // 在图像上绘制直线并筛选
// cv::Mat draw_lines(const cv::Mat& image,
//                    const std::vector<cv::Vec4i>& lines,
//                    cv::Scalar color = cv::Scalar(255, 0, 0),
//                    int thickness = 1,
//                    bool make_copy = true) {
//     cv::Mat result;
//     if (make_copy) {
//         image.copyTo(result);
//     } else {
//         result = const_cast<cv::Mat&>(image);
//     }
//     std::vector<cv::Vec4i> cleaned;
//     for (const cv::Vec4i& line : lines) {
//         int x1 = line[0];
//         int y1 = line[1];
//         int x2 = line[2];
//         int y2 = line[3];
//         if (abs(y2 - y1) <= 1 && abs(x2 - x1) >= 25 && abs(x2 - x1) <= 55) {
//             cleaned.push_back(line);
//             cv::line(result, cv::Point(x1, y1), cv::Point(x2, y2), color, thickness);
//         }
//     }

//     return result;
// }

// // 定义hough_lines函数
// std::vector<cv::Vec4i> hough_lines(const cv::Mat& image) {
//     std::vector<cv::Vec4i> lines;
//     // 调用HoughLinesP函数进行直线检测
//     cv::HoughLinesP(image, lines, 0.1, CV_PI / 10, 15, 9, 4);
//     return lines;
// }

// // 函数用于根据顶点区域过滤图像
// cv::Mat filter_region(const cv::Mat& image, const std::vector<cv::Point>& vertices) {
//     cv::Mat mask = cv::Mat::zeros(image.size(), image.type());

//     if (image.channels() == 1) {
//         std::vector<std::vector<cv::Point>> contours;
//         contours.push_back(vertices);
//         cv::fillPoly(mask, contours, cv::Scalar(255));
//         cv::imshow("mask", mask);
//     } else {
//         std::vector<std::vector<cv::Point>> contours;
//         contours.push_back(vertices);
//         cv::fillPoly(mask, contours, cv::Scalar(255, 255, 255));
//     }
//     cv::Mat result;
//     cv::bitwise_and(image, mask, result);
//     return result;
// }

// cv::Mat select_region(const cv::Mat& image) {
//     int rows = image.rows;
//     int cols = image.cols;

//     cv::Point pt_1 = cv::Point(cols * 0.05, rows * 0.90);
//     cv::Point pt_2 = cv::Point(cols * 0.05, rows * 0.70);
//     cv::Point pt_3 = cv::Point(cols * 0.30, rows * 0.55);
//     cv::Point pt_4 = cv::Point(cols * 0.30, rows * 0.15);
//     cv::Point pt_5 = cv::Point(cols * 0.90, rows * 0.15);
//     cv::Point pt_6 = cv::Point(cols * 0.90, rows * 0.90);

//     std::vector<cv::Point> vertices = {pt_1, pt_2, pt_3, pt_4, pt_5, pt_6};

//     cv::Mat point_img = image.clone();
//     if (point_img.channels() == 1) {
//         cv::cvtColor(point_img, point_img, cv::COLOR_GRAY2RGB);
//     }

//     for (const cv::Point& point : vertices) {
//         cv::circle(point_img, point, 10, cv::Scalar(0, 0, 255), 4);
//     }

//     cv::imshow("point_img", point_img);
//     return filter_region(image, vertices);
// }

// // 滑动条值改变的回调函数
// void onTrackbarChange(int, void*) {
//     // 第一种方法:灰度化和二值化
//     Mat gray;
//     cvtColor(car_Image, gray, COLOR_BGR2GRAY);
//     Mat binary;
//     threshold(gray, binary, min_value, max_value, THRESH_BINARY);
//     cv::imshow("binary", binary);

//     // 第二种方法:颜色范围过滤
//     cv::Scalar low(120, 120, 120); // BGR
//     cv::Scalar upper(255, 255, 255);
//     cv::Mat white_img;
//     cv::inRange(car_Image, low, upper, white_img);
//     cv::imshow("white_img", white_img);

//     // 与原图进行与运算,求出结果图像  有点没必要
//     cv::Mat and_img;
//     cv::bitwise_and(car_Image, car_Image, and_img, white_img);
//     cv::imshow("and_img", and_img);

//     Mat gray_2;
//     cvtColor(and_img, gray_2, COLOR_BGR2GRAY);
//     cv::imshow("gray_2", gray_2);

//     // 进行Canny边缘检测  直接在灰度图像gray_2上进行边缘检测
//     cv::Mat edges;
//     cv::Canny(gray_2, edges, gray_2_canny_min, gray_2_canny_max); //230-250 I CAN change
//     cv::imshow("edges", edges);

//     cv::Mat result = select_region(edges);
//     cv::imshow("result", result);

//     std::vector<cv::Vec4i> detectedLines = hough_lines(result);
//     cv::Mat outputImage = draw_lines(car_Image, detectedLines);

//     // 将检测到的直线转换为 identity_blocks 函数所需的格式
//     std::vector<std::vector<int>> linesForIdentityBlocks;
//     for (const auto& line : detectedLines) {
//         linesForIdentityBlocks.push_back({line[0], line[1], line[2], line[3]});//<cv::Vec4i>好
//     }

//     // 调用 identity_blocks 函数
//     auto [newImageWithRects, rects] = identity_blocks(outputImage, linesForIdentityBlocks);
//     cv::imshow("Image with drawn lines and rectangles", newImageWithRects);

    
//     auto [newImageWithRects_2, rects_2]=rect_finetune(car_Image,rects) ;
//     cv::imshow("Image with drawn lines and rectangles__2", newImageWithRects_2);

//     auto[newImageWithRects_3, spot_dict]=draw_parking(car_Image,rects_2);
//     cv::imshow("Image with drawn lines and rectangles__3", newImageWithRects_3);

//   }

// int main(int argc, char** argv) {
//     ros::init(argc, argv, "demo_cv_hsv");
//     ros::NodeHandle nh;

//     // 获取当前功能包的路径
//     string packagePath = ros::package::getPath("wpr_simulation");
//     // 构建包含数字的图像路径(数字模板图像)
//     string car_path = packagePath + "/data/car.png";

//     // 读取数字模板图像
//     car_Image = imread(car_path, IMREAD_COLOR);
//     if (car_Image.empty()) {
//         ROS_ERROR("无法读取数字模板图像,请检查图像路径。");
//         return -1;
//     }

//     // 生成图像显示和参数调节的窗口空间
//     cv::namedWindow("WINDOW", cv::WINDOW_AUTOSIZE);
//     cv::createTrackbar("max", "WINDOW", &max_value, 255, onTrackbarChange);
//     cv::createTrackbar("min", "WINDOW", &min_value, 255, onTrackbarChange);
//     cv::createTrackbar("gray_2_canny_min", "WINDOW", &gray_2_canny_min, 255, onTrackbarChange);
//     cv::createTrackbar("gray_2_canny_max", "WINDOW", &gray_2_canny_max, 255, onTrackbarChange);
//     // 初始调用回调函数以显示初始图像
//     onTrackbarChange(0, nullptr);

//     imshow("car_Image", car_Image);
//     waitKey(0);

//     ros::Rate loop_rate(50);
//     while (ros::ok()) {
//         ros::spinOnce();
//         loop_rate.sleep();
//     }

//     return 0;
// }
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值