Commit 5e69f8fca9d5597af539904e4b67bae1f9c2bfc8
1 parent
81e8a405
补充字段;
优化逆行处理
Showing
5 changed files
with
449 additions
and
674 deletions
jni/VehicleNativeInterface.cpp
@@ -452,7 +452,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_vehicle_VehicleNativeI | @@ -452,7 +452,7 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_vehicle_VehicleNativeI | ||
452 | jobject vehicle_pendant_det_res_vpd_res_syRect_rect = env->NewObject(cls_SyRect, mid_SyRect, one_pendant_res.rect.left_, | 452 | jobject vehicle_pendant_det_res_vpd_res_syRect_rect = env->NewObject(cls_SyRect, mid_SyRect, one_pendant_res.rect.left_, |
453 | one_pendant_res.rect.top_, one_pendant_res.rect.width_, one_pendant_res.rect.height_); | 453 | one_pendant_res.rect.top_, one_pendant_res.rect.width_, one_pendant_res.rect.height_); |
454 | 454 | ||
455 | - jobject vehiclePendantDetInfo = env->NewObject(cls_VehiclePendantDetInfo, mid_VehiclePendantDetInfo, vehicle_pendant_det_res_vpd_res_syRect_rect, one_pendant_res.index, one_pendant_res.confidence, one_pendant_res.driver_copilot_info); | 455 | + jobject vehiclePendantDetInfo = env->NewObject(cls_VehiclePendantDetInfo, mid_VehiclePendantDetInfo, vehicle_pendant_det_res_vpd_res_syRect_rect, one_pendant_res.index, one_pendant_res.confidence, one_pendant_res.driver_copilot_info, one_pendant_res.iColor); |
456 | 456 | ||
457 | env->SetObjectArrayElement(vehiclePendantDetInfoArray, m, vehiclePendantDetInfo); | 457 | env->SetObjectArrayElement(vehiclePendantDetInfoArray, m, vehiclePendantDetInfo); |
458 | } | 458 | } |
@@ -530,7 +530,18 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_vehicle_VehicleNativeI | @@ -530,7 +530,18 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_vehicle_VehicleNativeI | ||
530 | } | 530 | } |
531 | 531 | ||
532 | jint type = vehicle_info.type; | 532 | jint type = vehicle_info.type; |
533 | - jobject vehicleInfo = env->NewObject(cls_VehicleInfo, mid_VehicleInfo, vehicleDetectResult, vehicleWinDetectResult, vehicleBodyDetectResult, vehicleColorResult, vehicleRecgResult, vplateResult, vehiclePendantDetResult, vehicleIllegalDetResult, vehicleFeaResult,mtaResult, MannedResult, type ); | 533 | + jint vpt_type = vehicle_info.vpt_type; |
534 | + jint rainshed = vehicle_info.rainshed; //是否安装雨棚, 0 有雨棚 1 无雨棚 | ||
535 | + jint truck_manned = vehicle_info.truck_manned; | ||
536 | + jint motor_manned = vehicle_info.motor_manned; | ||
537 | + jint human_upper_color = vehicle_info.human_upper_color; | ||
538 | + jint human_lower_color = vehicle_info.human_lower_color; | ||
539 | + jint reverse_driving = vehicle_info.reverse_driving; // 0 正常行驶 1 逆行 -1 未知 | ||
540 | + jint phoning = vehicle_info.phoning; // 骑车打电话 | ||
541 | + jint cross_line = vehicle_info.cross_line; // 压实线, 1 黄实线 2 白实线 -1 其他 | ||
542 | + jint cross_diversion_line = vehicle_info.cross_diversion_line; // 压导流线 1 压了 -1 未压 | ||
543 | + | ||
544 | + jobject vehicleInfo = env->NewObject(cls_VehicleInfo, mid_VehicleInfo, vehicleDetectResult, vehicleWinDetectResult, vehicleBodyDetectResult, vehicleColorResult, vehicleRecgResult, vplateResult, vehiclePendantDetResult, vehicleIllegalDetResult, vehicleFeaResult,mtaResult, MannedResult, type, vpt_type, rainshed, truck_manned, motor_manned, human_upper_color, reverse_driving, phoning, cross_line, cross_diversion_line); | ||
534 | 545 | ||
535 | env->SetObjectArrayElement(vehicleInfoArray, j, vehicleInfo); | 546 | env->SetObjectArrayElement(vehicleInfoArray, j, vehicleInfo); |
536 | } | 547 | } |
@@ -566,12 +577,12 @@ JNIEXPORT void JNICALL Java_com_objecteye_nativeinterface_vehicle_VehicleNativeI | @@ -566,12 +577,12 @@ JNIEXPORT void JNICALL Java_com_objecteye_nativeinterface_vehicle_VehicleNativeI | ||
566 | 577 | ||
567 | /* | 578 | /* |
568 | * Class: com_objecteye_nativeinterface_vehicle_VehicleNativeInterface | 579 | * Class: com_objecteye_nativeinterface_vehicle_VehicleNativeInterface |
569 | - * Method: va_get_version | 580 | + * Method: get_village_pic_version |
570 | * Signature: ()Ljava/lang/String; | 581 | * Signature: ()Ljava/lang/String; |
571 | */ | 582 | */ |
572 | JNIEXPORT jstring JNICALL Java_com_objecteye_nativeinterface_vehicle_VehicleNativeInterface_getVersion(JNIEnv *env, jobject obj) | 583 | JNIEXPORT jstring JNICALL Java_com_objecteye_nativeinterface_vehicle_VehicleNativeInterface_getVersion(JNIEnv *env, jobject obj) |
573 | { | 584 | { |
574 | - const char *version = va_get_version(); | 585 | + const char *version = get_village_pic_version(); |
575 | return env->NewStringUTF(version); | 586 | return env->NewStringUTF(version); |
576 | } | 587 | } |
577 | 588 |
src/PicAnalysis.cpp
@@ -222,8 +222,8 @@ vector<AnalysisResult> PicAnalysis::analysis_img(vector<sy_img> vec_img){ | @@ -222,8 +222,8 @@ vector<AnalysisResult> PicAnalysis::analysis_img(vector<sy_img> vec_img){ | ||
222 | 222 | ||
223 | sy_rect vehicle_rect = result_info.vehicle_body_detect_res.rect; | 223 | sy_rect vehicle_rect = result_info.vehicle_body_detect_res.rect; |
224 | 224 | ||
225 | - if (road_info.direct_mask.cols > 0 && (1 == shot_type || 0 == shot_type)) { | ||
226 | - result_info.reverse_driving = m_road_seg_algorithm.check_reverse_driving(road_info.direct_mask, vehicle_rect, src.width, src.height, shot_type); | 225 | + if (road_info.vec_direct.size() > 0 && (1 == shot_type || 0 == shot_type)) { |
226 | + result_info.reverse_driving = m_road_seg_algorithm.check_reverse_driving(road_info.vec_direct, vehicle_rect, src.width, src.height, shot_type); | ||
227 | } | 227 | } |
228 | 228 | ||
229 | // 行人 | 229 | // 行人 |
@@ -250,14 +250,14 @@ vector<AnalysisResult> PicAnalysis::analysis_img(vector<sy_img> vec_img){ | @@ -250,14 +250,14 @@ vector<AnalysisResult> PicAnalysis::analysis_img(vector<sy_img> vec_img){ | ||
250 | // 车尾,判断是否 货车尾部货厢载人 | 250 | // 车尾,判断是否 货车尾部货厢载人 |
251 | if(result_info.vpt_type == 6 || result_info.vpt_type == 7){ | 251 | if(result_info.vpt_type == 6 || result_info.vpt_type == 7){ |
252 | if(result_info.manned_res.hs_count > 0){ | 252 | if(result_info.manned_res.hs_count > 0){ |
253 | - result_info.manned = 1; | 253 | + result_info.truck_manned = 1; |
254 | } | 254 | } |
255 | } | 255 | } |
256 | } else { | 256 | } else { |
257 | if(result_info.vpt_type == 1 || result_info.vpt_type == 2 || result_info.vpt_type == 3){ | 257 | if(result_info.vpt_type == 1 || result_info.vpt_type == 2 || result_info.vpt_type == 3){ |
258 | if(result_info.manned_res.hs_count >= 3){ | 258 | if(result_info.manned_res.hs_count >= 3){ |
259 | // 摩托车、三轮车载人 | 259 | // 摩托车、三轮车载人 |
260 | - result_info.manned = 1; | 260 | + result_info.motor_manned = 1; |
261 | } | 261 | } |
262 | } | 262 | } |
263 | } | 263 | } |
@@ -329,9 +329,10 @@ vector<AnalysisResult> PicAnalysis::analysis_img(vector<sy_img> vec_img){ | @@ -329,9 +329,10 @@ vector<AnalysisResult> PicAnalysis::analysis_img(vector<sy_img> vec_img){ | ||
329 | } | 329 | } |
330 | 330 | ||
331 | std::vector<HumanCarResult> vec_hcp_result = m_human_car_algorithm.detect(vec_motor_img); | 331 | std::vector<HumanCarResult> vec_hcp_result = m_human_car_algorithm.detect(vec_motor_img); |
332 | - if (vec_hcp_result.size() > 0) { | ||
333 | - if (vec_hcp_result[11] == 0 || vec_hcp_result[11] == 1) { | ||
334 | - result_info.reverse_driving = m_road_seg_algorithm.check_reverse_driving(road_info.direct_mask, vehicle_rect, src.width, src.height, vec_hcp_result[11]); | 332 | + if (vec_hcp_result.size() > 0 && road_info.vec_direct.size() > 0) { |
333 | + int head_or_tail = vec_hcp_result[11].type; | ||
334 | + if (head_or_tail == 0 || head_or_tail == 1) { | ||
335 | + result_info.reverse_driving = m_road_seg_algorithm.check_reverse_driving(road_info.vec_direct, vehicle_rect, src.width, src.height, head_or_tail); | ||
335 | } | 336 | } |
336 | } | 337 | } |
337 | 338 |
src/ai_engine_module/RoadSegAnalysis.cpp
@@ -3,518 +3,6 @@ | @@ -3,518 +3,6 @@ | ||
3 | uint8_t seg_colors[][3] = { {0, 0, 0}, {0, 255, 255}, {128, 255, 0}, {255, 128, 0}, {128, 0, 255}, {255, 0, 128}, {0, 128, 255}, {0, 255, 128}, {128, 255, 255}}; | 3 | uint8_t seg_colors[][3] = { {0, 0, 0}, {0, 255, 255}, {128, 255, 0}, {255, 128, 0}, {128, 0, 255}, {255, 0, 128}, {0, 128, 255}, {0, 255, 128}, {128, 255, 255}}; |
4 | uint8_t lane_colors[][3] = { {0, 0, 0}, {255, 0, 0}, {0, 255, 0}, {0, 0, 255}, {255, 255, 0}, {255, 0, 255}, {0, 255, 255}, {128, 255, 0}, {255, 128, 0}}; | 4 | uint8_t lane_colors[][3] = { {0, 0, 0}, {255, 0, 0}, {0, 255, 0}, {0, 0, 255}, {255, 255, 0}, {255, 0, 255}, {0, 255, 255}, {128, 255, 0}, {255, 128, 0}}; |
5 | 5 | ||
6 | -void lanes_process(const rs_lane* lanes, int lane_count, std::vector<std::pair<std::vector<cv::Point>, int>>& combined, float scale_w = 1.0, float scale_h = 1.0) { | ||
7 | - std::vector<std::vector<cv::Point> > lanes_xys; | ||
8 | - std::vector<int> lanes_cls; | ||
9 | - for (int i = 0; i < lane_count; i++) { | ||
10 | - std::vector<cv::Point> xys; | ||
11 | - for (int j = 0; j < lanes[i].num_points; j++) { | ||
12 | - int x = static_cast<int>(lanes[i].points[j].x_ * scale_w); | ||
13 | - int y = static_cast<int>(lanes[i].points[j].y_ * scale_h); | ||
14 | - if (x > 0 && y > 0) { | ||
15 | - xys.emplace_back(x, y); | ||
16 | - } | ||
17 | - } | ||
18 | - if (!xys.empty()) { | ||
19 | - lanes_xys.push_back(xys); | ||
20 | - lanes_cls.push_back(lanes[i].cls); | ||
21 | - } | ||
22 | - } | ||
23 | - | ||
24 | - for (size_t i = 0; i < lanes_xys.size(); ++i) { | ||
25 | - combined.push_back(std::make_pair(lanes_xys[i], lanes_cls[i])); | ||
26 | - } | ||
27 | - if (!combined.empty()) { | ||
28 | - //按车道线起点坐标排序,相应的类别顺序也会变化以保证标签对齐 | ||
29 | - std::sort(combined.begin(), combined.end(), [](const std::pair<std::vector<cv::Point>, int>& a, const std::pair<std::vector<cv::Point>, int>& b) { | ||
30 | - return a.first[0].x < b.first[0].x; | ||
31 | - }); | ||
32 | - } | ||
33 | -} | ||
34 | - | ||
35 | -cv::Mat mask_to_rgb(cv::Mat img, cv::Mat mask) { | ||
36 | - cv::Mat rgb = img.clone(); | ||
37 | - int reg_cls = 9; | ||
38 | - for (int i = 0; i < rgb.rows; i++) { | ||
39 | - for (int j = 0; j < rgb.cols; j++) { | ||
40 | - for (int k = 1; k < reg_cls; k++) { | ||
41 | - if (mask.at<int>(i,j) == k) { | ||
42 | - rgb.at<cv::Vec3b>(i,j)[0] = seg_colors[k][0]; | ||
43 | - rgb.at<cv::Vec3b>(i,j)[1] = seg_colors[k][1]; | ||
44 | - rgb.at<cv::Vec3b>(i,j)[2] = seg_colors[k][2]; | ||
45 | - } | ||
46 | - } | ||
47 | - } | ||
48 | - } | ||
49 | - return rgb; | ||
50 | -} | ||
51 | - | ||
52 | -float contourArea(std::vector<cv::Point> contour, cv::Point2f& center) { | ||
53 | - cv::RotatedRect rect = cv::minAreaRect(contour); // 最小外接矩形 rect[0]中心点 rect[1]宽 高 rect[2]旋转角度 | ||
54 | - center = rect.center; | ||
55 | - return cv::contourArea(contour); | ||
56 | -} | ||
57 | - | ||
58 | -int Mask2LanePoints(const cv::Mat& pred, std::vector<std::vector<cv::Point>>&lanes, std::vector<int>& cats) { | ||
59 | - std::vector<int> labels = {9, 10, 11, 12, 13}; | ||
60 | - for(auto cat: labels) { | ||
61 | - cv::Mat b_masks, measure_labels, stats, centroids; | ||
62 | - cv::compare(pred, cat, b_masks, cv::CMP_EQ); //将pred元素逐个和cat比较,相同255,不同0 | ||
63 | - // cv::threshold(pred, b_masks, 126, 255, cv::THRESH_OTSU); //生成二值图 | ||
64 | - // 连通域计算 b_masks:闭操作后的二值图像 measure_labels:和原图一样大的标记图 centroids:nccomps×2的矩阵,表示每个连通域的质心(x, y) | ||
65 | - // stats:nccomps×5的矩阵 表示每个连通区域的外接矩形和面积(x, y, w, h, area),索引0是背景信息 | ||
66 | - int nccomps = cv::connectedComponentsWithStats (b_masks, measure_labels, stats, centroids, 4); //8 | ||
67 | - for(int cv_measure_id = 1; cv_measure_id < nccomps; cv_measure_id++ ) { //跳过背景信息0 | ||
68 | - cv::Mat cv_measure_mask; | ||
69 | - cv::compare(measure_labels, cv_measure_id, cv_measure_mask, cv::CMP_EQ); | ||
70 | - std::vector< std::vector< cv::Point> > contours; | ||
71 | - cv::findContours(cv_measure_mask,contours,cv::noArray(),cv::RETR_TREE,cv::CHAIN_APPROX_SIMPLE); | ||
72 | - std::vector<cv::Point> contours_poly; | ||
73 | - for (int j = 0; j < contours.size();j++) { | ||
74 | - // float area = cv::contourArea(contours[j]); if (area < 60) continue; //30 | ||
75 | - float area = cv::contourArea(contours[j]); if (area < 30) continue; //30 | ||
76 | - cv::approxPolyDP(cv::Mat(contours[j]), contours_poly, 6, true); //减小epsilon提高拟合精度(需要调试,epsilon过小会使多边形不够简化,单条线变多条) | ||
77 | - if (contours_poly.size() == 1) continue; | ||
78 | - lanes.push_back(contours_poly); | ||
79 | - cats.push_back(cat); | ||
80 | - } | ||
81 | - } | ||
82 | - } | ||
83 | - return 0; | ||
84 | -} | ||
85 | - | ||
86 | -int findMainMaskV2(bool large_resolution, const cv::Mat& solve_masks, const std::vector<int>& labels, std::vector<std::vector<cv::Point>> &poly_masks, std::vector<int> ®ion_classes, std::vector<std::vector<cv::Point>> &main_masks, cv::Mat& new_mask, cv::Mat& new_mask_forlane) { | ||
87 | - int h = 360, w = 640; | ||
88 | - int seg_num_cls = 8; | ||
89 | - int seg_num_seg = 4; | ||
90 | - int seg_min_region_area = 512; //10 | ||
91 | - // mask部分区域 | ||
92 | - if (large_resolution) solve_masks(cv::Rect(0, 0, w, int(h * 0.14))) = 0; | ||
93 | - else solve_masks(cv::Rect(0, 0, w, int(h * 0.22))) = 0; | ||
94 | - solve_masks(cv::Rect(0, int(h * 0.95), w, int(h * 0.05))) = 0; | ||
95 | - solve_masks(cv::Rect(0, 0, int(w * 0.02), h)) = 0; | ||
96 | - solve_masks(cv::Rect(int(w * 0.95), 0, int(w * 0.05), h)) = 0; | ||
97 | - | ||
98 | - float hf_w = w*0.5; | ||
99 | - std::vector<std::vector<cv::Point>> all_emerg_contours, all_com_contours, mid_com_contours, mid_zd_contours; | ||
100 | - std::vector<cv::Point> emerg_contours, mid_contours, com_contours, zd_contours; | ||
101 | - float emerg_max_area = 0, max_area = 0, zd_max_area = 0; | ||
102 | - | ||
103 | - for(auto cat: labels) { | ||
104 | - if (cat == 0 || cat > seg_num_seg) | ||
105 | - continue; | ||
106 | - | ||
107 | - // std::cout << cat << std::endl; | ||
108 | - cv::Mat b_masks, measure_labels, stats, centroids; | ||
109 | - cv::Mat n_masks = cv::Mat_<int>(h,w); | ||
110 | - n_masks = cv::Scalar(255); | ||
111 | - cv::compare(solve_masks, cat, b_masks, cv::CMP_EQ); //将solve_masks元素逐个和cat比较,相同255,不同0 | ||
112 | - //连通域计算 | ||
113 | - int nccomps = cv::connectedComponentsWithStats (b_masks, measure_labels, stats, centroids, 8); | ||
114 | - for(int i = 1; i < nccomps; i++ ) { //跳过背景信息0 | ||
115 | - //移除过小的区域,并将对应位置置为0 | ||
116 | - if (stats.at<int>(i, cv::CC_STAT_AREA) < seg_min_region_area) { | ||
117 | - cv::Mat comparison_result; | ||
118 | - cv::compare(measure_labels, cv::Scalar(i), comparison_result, cv::CMP_EQ); //相等为255不等为0 | ||
119 | - n_masks.setTo(0, comparison_result); // 将comparison_result中非零区域置为0 | ||
120 | - cv::bitwise_and(solve_masks,n_masks,solve_masks); | ||
121 | - continue; | ||
122 | - } | ||
123 | - | ||
124 | - double centr_x = centroids.at<double>(i, 0); | ||
125 | - double centr_y = centroids.at<double>(i, 1); | ||
126 | - | ||
127 | - int region_class = cat; | ||
128 | - cv::Mat region_mask; | ||
129 | - cv::bitwise_and(measure_labels,n_masks,measure_labels);///// | ||
130 | - cv::compare(measure_labels, i, region_mask, cv::CMP_EQ); | ||
131 | - | ||
132 | - // 闭运算,先膨胀再腐蚀,去除较暗部分 | ||
133 | - cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(17, 5)); | ||
134 | - cv::morphologyEx(region_mask, region_mask, cv::MORPH_CLOSE, kernel); | ||
135 | - | ||
136 | - std::vector< std::vector< cv::Point> > contours; | ||
137 | - cv::findContours(region_mask,contours,cv::noArray(),cv::RETR_TREE,cv::CHAIN_APPROX_SIMPLE); | ||
138 | - std::vector<cv::Point> contours_poly; | ||
139 | - | ||
140 | - // 应急车道 | ||
141 | - if(region_class == 2) { | ||
142 | - for (auto contour : contours) { | ||
143 | - cv::Point2f center; | ||
144 | - float area_ = contourArea(contour, center); | ||
145 | - if (area_ > emerg_max_area) { | ||
146 | - emerg_max_area = area_; | ||
147 | - emerg_contours = contour; | ||
148 | - } | ||
149 | - all_emerg_contours.push_back(contour); | ||
150 | - } | ||
151 | - } | ||
152 | - | ||
153 | - // 普通行车道 | ||
154 | - if(region_class == 1) { | ||
155 | - for (auto contour : contours) { | ||
156 | - cv::Point2f center; | ||
157 | - float area_ = contourArea(contour, center); | ||
158 | - if (area_ > max_area) { | ||
159 | - max_area = area_; | ||
160 | - com_contours = contour; | ||
161 | - } | ||
162 | - // 取中点所在的连通域 | ||
163 | - cv::Point2f point(int(w*0.5),int(h*0.95)-1); | ||
164 | - double distance = cv::pointPolygonTest(contour, point, false); | ||
165 | - if (distance >= 0) { | ||
166 | - mid_contours = contour; | ||
167 | - hf_w = center.x; | ||
168 | - continue; | ||
169 | - } | ||
170 | - if (abs(center.x - hf_w) < 90) // 取中点所在区域左右90像素内的连通域 230307 | ||
171 | - mid_com_contours.push_back(contour); | ||
172 | - } | ||
173 | - } | ||
174 | - | ||
175 | - // 导流线 | ||
176 | - if(region_class == 3) { | ||
177 | - for (auto contour : contours) { | ||
178 | - cv::Point2f center; | ||
179 | - float area_ = contourArea(contour, center); | ||
180 | - if (area_ > zd_max_area) { | ||
181 | - zd_max_area = area_; | ||
182 | - zd_contours = contour; | ||
183 | - } | ||
184 | - // if (abs(center.x - w*0.5) < 200) // 取中点左右200像素内的连通域 | ||
185 | - if (abs(center.x - w*0.5) < 250) // 取中点左右250像素内的连通域 | ||
186 | - mid_zd_contours.push_back(contour); | ||
187 | - } | ||
188 | - } | ||
189 | - | ||
190 | - // 拟合各行驶区域 | ||
191 | - for (int j = 0; j < contours.size();j++) { | ||
192 | - cv::approxPolyDP(cv::Mat(contours[j]), contours_poly, 10, true); | ||
193 | - if (contours_poly.size() <= 2) continue; | ||
194 | - poly_masks.push_back(contours_poly); | ||
195 | - region_classes.push_back(cat); | ||
196 | - } | ||
197 | - } | ||
198 | - } | ||
199 | - | ||
200 | - // cv::Mat new_mask(h, w, CV_8UC3, cv::Scalar(0,0,0)); | ||
201 | - if (!mid_contours.empty()) { | ||
202 | - // cv::fillConvexPoly(new_mask, mid_contours, cv::Scalar(255,255,255)); //填充255 | ||
203 | - cv::fillConvexPoly(new_mask, mid_contours, cv::Scalar(255)); //填充255 | ||
204 | - cv::fillConvexPoly(new_mask_forlane, mid_contours, cv::Scalar(255)); //填充255 | ||
205 | - std::vector<cv::Point> contours_poly; | ||
206 | - cv::approxPolyDP(cv::Mat(mid_contours), contours_poly, 10, true); | ||
207 | - if (contours_poly.size() > 2) main_masks.push_back(contours_poly); | ||
208 | - all_com_contours.push_back(mid_contours); | ||
209 | - } | ||
210 | - else { | ||
211 | - // cv::fillConvexPoly(new_mask, com_contours, cv::Scalar(255,255,255)); //填充255 | ||
212 | - cv::fillConvexPoly(new_mask, com_contours, cv::Scalar(255)); //填充255 | ||
213 | - cv::fillConvexPoly(new_mask_forlane, com_contours, cv::Scalar(255)); //填充255 | ||
214 | - std::vector<cv::Point> contours_poly; | ||
215 | - cv::approxPolyDP(cv::Mat(com_contours), contours_poly, 10, true); | ||
216 | - if (contours_poly.size() > 2) main_masks.push_back(contours_poly); | ||
217 | - all_com_contours.push_back(com_contours); | ||
218 | - } | ||
219 | - | ||
220 | - for (auto contour_ : mid_com_contours) { | ||
221 | - // cv::fillConvexPoly(new_mask, contour_, cv::Scalar(255,255,255)); //填充255 | ||
222 | - cv::fillConvexPoly(new_mask, contour_, cv::Scalar(255)); //填充255 | ||
223 | - cv::fillConvexPoly(new_mask_forlane, contour_, cv::Scalar(255)); //填充255 | ||
224 | - std::vector<cv::Point> contours_poly; | ||
225 | - cv::approxPolyDP(cv::Mat(contour_), contours_poly, 10, true); | ||
226 | - if (contours_poly.size() > 2) main_masks.push_back(contours_poly); | ||
227 | - all_com_contours.push_back(contour_); | ||
228 | - } | ||
229 | - | ||
230 | - if (!emerg_contours.empty() && !all_emerg_contours.empty()) { | ||
231 | - if (all_emerg_contours.size() == 1) | ||
232 | - // cv::fillConvexPoly(new_mask, emerg_contours, cv::Scalar(255,255,255)); | ||
233 | - cv::fillConvexPoly(new_mask, emerg_contours, cv::Scalar(255)); //填充255 | ||
234 | - else { | ||
235 | - float sum_centerx = 0, sum_centery = 0; | ||
236 | - float length_emerg_com = 9999999; | ||
237 | - // 计算选中行车道的平均中心点 | ||
238 | - for (auto contour_ : all_com_contours) { | ||
239 | - cv::Point2f center; | ||
240 | - float area_ = contourArea(contour_, center); | ||
241 | - sum_centerx += center.x; | ||
242 | - sum_centery += center.y; | ||
243 | - } | ||
244 | - float ave_centerx = sum_centerx / all_com_contours.size(); | ||
245 | - float ave_centery = sum_centery / all_com_contours.size(); | ||
246 | - // 选择距离最近的应急车道且面积不小于最大应急车道的一半 | ||
247 | - for (auto econtour_ : all_emerg_contours) { | ||
248 | - cv::Point2f center; | ||
249 | - float area_ = contourArea(econtour_, center); | ||
250 | - float tmp_length = sqrt(pow((ave_centerx-center.x),2.0) + pow((ave_centery-center.y),2.0)); | ||
251 | - if (tmp_length < length_emerg_com and area_ > 0.7*emerg_max_area) { | ||
252 | - length_emerg_com = tmp_length; | ||
253 | - emerg_contours = econtour_; | ||
254 | - } | ||
255 | - } | ||
256 | - // cv::fillConvexPoly(new_mask, emerg_contours, cv::Scalar(255,255,255)); | ||
257 | - cv::fillConvexPoly(new_mask, emerg_contours, cv::Scalar(255)); //填充255 | ||
258 | - } | ||
259 | - } | ||
260 | - | ||
261 | - if (!mid_zd_contours.empty()) { | ||
262 | - for (auto contour_ : mid_zd_contours) | ||
263 | - // cv::fillConvexPoly(new_mask, contour_, cv::Scalar(255,255,255)); //填充255 | ||
264 | - cv::fillConvexPoly(new_mask, contour_, cv::Scalar(255)); //填充255 | ||
265 | - } | ||
266 | - | ||
267 | - // 膨胀腐蚀,去除行车道和应急车道间的空洞 | ||
268 | - cv::Mat kernel_ = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(17, 5)); | ||
269 | - cv::morphologyEx(new_mask, new_mask, cv::MORPH_CLOSE, kernel_); | ||
270 | - cv::morphologyEx(new_mask_forlane, new_mask_forlane, cv::MORPH_CLOSE, kernel_); | ||
271 | - | ||
272 | - return 0; | ||
273 | -} | ||
274 | - | ||
275 | - | ||
276 | -cv::Mat seg_post_process(bool large_resolution, unsigned char *seg_array, std::vector<std::pair<std::vector<cv::Point>, int>> combined, std::vector<std::vector<cv::Point>> &poly_masks, std::vector<int> ®ion_classes, std::vector<std::vector<cv::Point>> &lanes, std::vector<int> &cats, std::map<double, int> &x_sort, cv::Mat &background_mask) { | ||
277 | - std::vector<int> pred_cls; | ||
278 | - int h = 360, w = 640; | ||
279 | - cv::Mat lanes_masks = cv::Mat_<int>(h,w); //正常分割结果 | ||
280 | - cv::Mat mask_rmlane = cv::Mat_<int>(h,w); //车道线区域置为背景 | ||
281 | - cv::Mat solve_masks = cv::Mat_<int>(h,w); //计算主行驶区域用(虚线及减速标线归入行车道) | ||
282 | - int step_size = h*w; | ||
283 | - int seg_min_region_area = 512; //1024 | ||
284 | - | ||
285 | - for (int i = 0; i < h; ++i) { | ||
286 | - for (int j = 0; j < w; ++j) { | ||
287 | - int max_cls = seg_array[(i * w + j)]; | ||
288 | - lanes_masks.ptr<int>(i)[j] = max_cls; | ||
289 | - pred_cls.push_back(max_cls); | ||
290 | - mask_rmlane.ptr<int>(i)[j] = max_cls; | ||
291 | - solve_masks.ptr<int>(i)[j] = max_cls; | ||
292 | - } | ||
293 | - } | ||
294 | - | ||
295 | - for (const auto& lane_info : combined) { | ||
296 | - const auto& xys = lane_info.first; | ||
297 | - int cls = lane_info.second; | ||
298 | - if (cls == 1) cls = 9; /*黄实线*/ if (cls == 2) cls = 10; /*白实线*/ | ||
299 | - if (cls == 3) cls = 11; /*虚线*/ if (cls == 4) cls = 12; /*黄虚线*/ | ||
300 | - if (cls == 5) cls = 13; /*车道中线*/ | ||
301 | - for (size_t i = 1; i < xys.size(); ++i) { | ||
302 | - cv::line(lanes_masks, xys[i - 1], xys[i], cls, 4); //绘制车道线用于求连通域 | ||
303 | - if (cls == 11 || cls == 12) cls = 1; //求主行驶区域时将虚线归入行车道 | ||
304 | - cv::line(solve_masks, xys[i - 1], xys[i], cls, 4); | ||
305 | - | ||
306 | - } | ||
307 | - } | ||
308 | - | ||
309 | - // 求背景区域--mask车道区域,场景变化用 | ||
310 | - cv::compare(lanes_masks, 0, background_mask, cv::CMP_EQ); //将lanes_masks元素逐个和0比较,相同255,不同0 | ||
311 | -#if 0 | ||
312 | - //--mask远处区域------------------------------------------------ | ||
313 | - cv::Mat mask_black = mask_rmlane.clone(); | ||
314 | - if (large_resolution) mask_black(cv::Rect(0, 0, w, int(h * 0.14))) = 0; | ||
315 | - else mask_black(cv::Rect(0, 0, w, int(h * 0.22))) = 0; | ||
316 | - mask_black(cv::Rect(0, int(h * 0.95), w, int(h * 0.05))) = 0; | ||
317 | - mask_black(cv::Rect(0, 0, int(w * 0.02), h)) = 0; | ||
318 | - mask_black(cv::Rect(int(w * 0.95), 0, int(w * 0.05), h)) = 0; | ||
319 | - mask_rmlane = mask_black; | ||
320 | - //------------------------------------------------------------------------- | ||
321 | -#endif | ||
322 | - //2.去重获取预测到的类别 | ||
323 | - std::vector<int> labels(pred_cls); | ||
324 | - std::sort(labels.begin(),labels.end()); | ||
325 | - labels.erase(std::unique(labels.begin(),labels.end()),labels.end()); | ||
326 | - | ||
327 | - //4.求车道线区域 | ||
328 | - int flag = Mask2LanePoints(lanes_masks, lanes, cats); ///////////////////////// 车道线如何与mask结合 | ||
329 | - | ||
330 | - //5.求道路区域 | ||
331 | - int count = 0; | ||
332 | - for(auto cat: labels) { | ||
333 | - // std::cout << cat << std::endl; | ||
334 | - cv::Mat b_masks, measure_labels, stats, centroids; | ||
335 | - cv::Mat n_masks = cv::Mat_<int>(h,w); | ||
336 | - n_masks = cv::Scalar(255); | ||
337 | - cv::compare(mask_rmlane, cat, b_masks, cv::CMP_EQ); //将mask_rmlane元素逐个和cat比较,相同255,不同0 | ||
338 | - //连通域计算 | ||
339 | - int nccomps = cv::connectedComponentsWithStats (b_masks, measure_labels, stats, centroids, 8); | ||
340 | - for(int i = 1; i < nccomps; i++ ) { //跳过背景信息0 | ||
341 | - //移除过小的区域,并将对应位置置为0 | ||
342 | - if (stats.at<int>(i, cv::CC_STAT_AREA) < seg_min_region_area) { | ||
343 | - cv::Mat comparison_result; | ||
344 | - cv::compare(measure_labels, cv::Scalar(i), comparison_result, cv::CMP_EQ); //相等为255不等为0 | ||
345 | - n_masks.setTo(0, comparison_result); // 将comparison_result中非零区域置为0 | ||
346 | - | ||
347 | - cv::bitwise_and(mask_rmlane,n_masks,mask_rmlane); | ||
348 | - continue; | ||
349 | - } | ||
350 | - | ||
351 | - double centr_x = centroids.at<double>(i, 0); | ||
352 | - double centr_y = centroids.at<double>(i, 1); | ||
353 | - | ||
354 | - int region_class = cat; | ||
355 | - // printf("region_class: %d\n", region_class); | ||
356 | - cv::Mat region_mask; | ||
357 | - cv::bitwise_and(measure_labels,n_masks,measure_labels);///// | ||
358 | - cv::compare(measure_labels, i, region_mask, cv::CMP_EQ); | ||
359 | - | ||
360 | - std::vector< std::vector< cv::Point> > contours; | ||
361 | - cv::findContours(region_mask,contours,cv::noArray(),cv::RETR_TREE,cv::CHAIN_APPROX_SIMPLE); | ||
362 | - std::vector<cv::Point> contours_poly; | ||
363 | - for (int j = 0; j < contours.size();j++) { | ||
364 | - cv::approxPolyDP(cv::Mat(contours[j]), contours_poly, 10, true); | ||
365 | - if (contours_poly.size() <= 2) continue; | ||
366 | - poly_masks.push_back(contours_poly); | ||
367 | - region_classes.push_back(cat); | ||
368 | - if (x_sort.count(centr_x)) centr_x += 0.0001; | ||
369 | - x_sort.insert(std::make_pair(centr_x, count)); | ||
370 | - ++ count; | ||
371 | - // for (auto iter: contours_poly) { | ||
372 | - // std::cout << "contour " << iter << " " << cat << std::endl; | ||
373 | - // } | ||
374 | - | ||
375 | - } | ||
376 | - } | ||
377 | - } | ||
378 | - | ||
379 | -#if 0 | ||
380 | - //6.draw lanes | ||
381 | - for (int i = 0; i < lanes.size(); ++i) { | ||
382 | - int thickness = 4; | ||
383 | - for (int j = 0; j < lanes[i].size()-1; ++j) { | ||
384 | - cv::line(mask_rmlane, lanes[i][j], lanes[i][j+1], cats[i], thickness); | ||
385 | - // std::cout << lanes[i][j] << " " << lanes[i][j+1] << " " << cats[i] << std::endl; | ||
386 | - } | ||
387 | - } | ||
388 | -#endif | ||
389 | - return mask_rmlane; | ||
390 | -} | ||
391 | - | ||
392 | - | ||
393 | - | ||
394 | -cv::Mat direct_post_process(bool large_resolution, unsigned char *direct_array, std::vector<std::vector<cv::Point>> &poly_masks, std::vector<int> ®ion_classes) { | ||
395 | - std::vector<int> pred_cls; | ||
396 | - int h = 360, w = 640, step_size = h*w, seg_min_region_area = 512; | ||
397 | - cv::Mat mask_rmlane = cv::Mat_<int>(h,w); //车道线区域置为背景 | ||
398 | - for (int i = 0; i < h; ++i) { | ||
399 | - for (int j = 0; j < w; ++j) { | ||
400 | - int max_cls = direct_array[(i * w + j)]; | ||
401 | - pred_cls.push_back(max_cls); | ||
402 | - mask_rmlane.ptr<int>(i)[j] = max_cls; | ||
403 | - } | ||
404 | - } | ||
405 | - | ||
406 | -#if 1 /*mask远处区域*/ | ||
407 | - cv::Mat mask_black = mask_rmlane.clone(); | ||
408 | - if (large_resolution) mask_black(cv::Rect(0, 0, w, int(h * 0.14))) = 0; | ||
409 | - else mask_black(cv::Rect(0, 0, w, int(h * 0.22))) = 0; | ||
410 | - mask_black(cv::Rect(0, int(h * 0.95), w, int(h * 0.05))) = 0; | ||
411 | - mask_black(cv::Rect(0, 0, int(w * 0.02), h)) = 0; | ||
412 | - mask_black(cv::Rect(int(w * 0.95), 0, int(w * 0.05), h)) = 0; | ||
413 | - mask_rmlane = mask_black; | ||
414 | -#endif | ||
415 | - //去重获取预测到的类别 | ||
416 | - std::vector<int> labels(pred_cls); | ||
417 | - std::sort(labels.begin(),labels.end()); | ||
418 | - labels.erase(std::unique(labels.begin(),labels.end()),labels.end()); | ||
419 | - | ||
420 | - //求道路区域 | ||
421 | - for(auto cat: labels) { | ||
422 | - cv::Mat b_masks, measure_labels, stats, centroids; | ||
423 | - cv::Mat n_masks = cv::Mat_<int>(h,w); n_masks = cv::Scalar(255); | ||
424 | - cv::compare(mask_rmlane, cat, b_masks, cv::CMP_EQ); //将mask_rmlane元素逐个和cat比较,相同255,不同0 | ||
425 | - //连通域计算 | ||
426 | - int nccomps = cv::connectedComponentsWithStats (b_masks, measure_labels, stats, centroids, 8); | ||
427 | - for(int i = 1; i < nccomps; i++ ) { //跳过背景信息0 | ||
428 | - if (stats.at<int>(i, cv::CC_STAT_AREA) < seg_min_region_area) { //移除过小的区域,并将对应位置置为0 | ||
429 | - cv::Mat comparison_result; | ||
430 | - cv::compare(measure_labels, cv::Scalar(i), comparison_result, cv::CMP_EQ); //相等为255不等为0 | ||
431 | - n_masks.setTo(0, comparison_result); // 将comparison_result中非零区域置为0 | ||
432 | - cv::bitwise_and(mask_rmlane,n_masks,mask_rmlane); | ||
433 | - continue; | ||
434 | - } | ||
435 | - | ||
436 | - cv::Mat region_mask; | ||
437 | - cv::bitwise_and(measure_labels,n_masks,measure_labels);///// | ||
438 | - cv::compare(measure_labels, i, region_mask, cv::CMP_EQ); | ||
439 | - | ||
440 | - std::vector<std::vector<cv::Point>> contours; | ||
441 | - cv::findContours(region_mask,contours,cv::noArray(),cv::RETR_TREE,cv::CHAIN_APPROX_SIMPLE); | ||
442 | - std::vector<cv::Point> contours_poly; | ||
443 | - for (int j = 0; j < contours.size();j++) { | ||
444 | - cv::approxPolyDP(cv::Mat(contours[j]), contours_poly, 10, true); | ||
445 | - if (contours_poly.size() <= 2) continue; | ||
446 | - poly_masks.push_back(contours_poly); | ||
447 | - region_classes.push_back(cat); | ||
448 | - } | ||
449 | - } | ||
450 | - } | ||
451 | - return mask_rmlane; | ||
452 | -} | ||
453 | - | ||
454 | - | ||
455 | -// 合并来去区域 | ||
456 | -cv::Mat merge_direct_process(bool large_resolution, unsigned char *direct_array, std::vector<std::vector<cv::Point>> &poly_masks, std::vector<int> ®ion_classes) { | ||
457 | - std::vector<int> pred_cls; | ||
458 | - int h = 360, w = 640, step_size = h*w, seg_min_region_area = 512; | ||
459 | - cv::Mat mask_rmlane = cv::Mat_<int>(h,w); //车道线区域置为背景 | ||
460 | - for (int i = 0; i < h; ++i) { | ||
461 | - for (int j = 0; j < w; ++j) { | ||
462 | - int max_cls = direct_array[(i * w + j)]; | ||
463 | - if (max_cls == 1 || max_cls == 2) max_cls = 5; // 来去区域合并的类别为5 | ||
464 | - if (max_cls == 3 || max_cls == 4) max_cls = 6; // 近远区域合并的类别为6 | ||
465 | - pred_cls.push_back(max_cls); | ||
466 | - mask_rmlane.ptr<int>(i)[j] = max_cls; | ||
467 | - } | ||
468 | - } | ||
469 | - | ||
470 | -#if 0 /*mask远处区域*/ | ||
471 | - cv::Mat mask_black = mask_rmlane.clone(); | ||
472 | - if (large_resolution) mask_black(cv::Rect(0, 0, w, int(h * 0.14))) = 0; | ||
473 | - else mask_black(cv::Rect(0, 0, w, int(h * 0.22))) = 0; | ||
474 | - mask_black(cv::Rect(0, int(h * 0.95), w, int(h * 0.05))) = 0; | ||
475 | - mask_black(cv::Rect(0, 0, int(w * 0.02), h)) = 0; | ||
476 | - mask_black(cv::Rect(int(w * 0.95), 0, int(w * 0.05), h)) = 0; | ||
477 | - mask_rmlane = mask_black; | ||
478 | -#endif | ||
479 | - //去重获取预测到的类别 | ||
480 | - std::vector<int> labels(pred_cls); | ||
481 | - std::sort(labels.begin(),labels.end()); | ||
482 | - labels.erase(std::unique(labels.begin(),labels.end()),labels.end()); | ||
483 | - | ||
484 | - //求道路区域 | ||
485 | - for(auto cat: labels) { | ||
486 | - cv::Mat b_masks, measure_labels, stats, centroids; | ||
487 | - cv::Mat n_masks = cv::Mat_<int>(h,w); n_masks = cv::Scalar(255); | ||
488 | - cv::compare(mask_rmlane, cat, b_masks, cv::CMP_EQ); //将mask_rmlane元素逐个和cat比较,相同255,不同0 | ||
489 | - //连通域计算 | ||
490 | - int nccomps = cv::connectedComponentsWithStats (b_masks, measure_labels, stats, centroids, 8); | ||
491 | - for(int i = 1; i < nccomps; i++ ) { //跳过背景信息0 | ||
492 | - if (stats.at<int>(i, cv::CC_STAT_AREA) < seg_min_region_area) { //移除过小的区域,并将对应位置置为0 | ||
493 | - cv::Mat comparison_result; | ||
494 | - cv::compare(measure_labels, cv::Scalar(i), comparison_result, cv::CMP_EQ); //相等为255不等为0 | ||
495 | - n_masks.setTo(0, comparison_result); // 将comparison_result中非零区域置为0 | ||
496 | - cv::bitwise_and(mask_rmlane,n_masks,mask_rmlane); | ||
497 | - continue; | ||
498 | - } | ||
499 | - | ||
500 | - cv::Mat region_mask; | ||
501 | - cv::bitwise_and(measure_labels,n_masks,measure_labels);///// | ||
502 | - cv::compare(measure_labels, i, region_mask, cv::CMP_EQ); | ||
503 | - | ||
504 | - std::vector<std::vector<cv::Point>> contours; | ||
505 | - cv::findContours(region_mask,contours,cv::noArray(),cv::RETR_TREE,cv::CHAIN_APPROX_SIMPLE); | ||
506 | - std::vector<cv::Point> contours_poly; | ||
507 | - for (int j = 0; j < contours.size();j++) { | ||
508 | - cv::approxPolyDP(cv::Mat(contours[j]), contours_poly, 10, true); | ||
509 | - if (contours_poly.size() <= 2) continue; | ||
510 | - poly_masks.push_back(contours_poly); | ||
511 | - region_classes.push_back(cat); | ||
512 | - } | ||
513 | - } | ||
514 | - } | ||
515 | - return mask_rmlane; | ||
516 | -} | ||
517 | - | ||
518 | RoadSegAnalysis::RoadSegAnalysis(/* args */) | 6 | RoadSegAnalysis::RoadSegAnalysis(/* args */) |
519 | { | 7 | { |
520 | } | 8 | } |
@@ -573,34 +61,91 @@ std::vector<RoadInfo> RoadSegAnalysis::detect(vector<sy_img> vec_img){ | @@ -573,34 +61,91 @@ std::vector<RoadInfo> RoadSegAnalysis::detect(vector<sy_img> vec_img){ | ||
573 | 61 | ||
574 | for (int b = 0; b < batchsize; b++) { | 62 | for (int b = 0; b < batchsize; b++) { |
575 | auto one_result = results[b]; | 63 | auto one_result = results[b]; |
576 | - RoadInfo one_road; | ||
577 | - for (size_t i = 0; i < one_result.lane_count; i++) | ||
578 | - { | ||
579 | - auto one_lane = one_result.reg_array[i]; | ||
580 | - LineInfo info; | ||
581 | - for (size_t j = 0; j < one_lane.num_points; j++) | ||
582 | - { | ||
583 | - info.vec_pt.push_back(one_lane.points[j]); | ||
584 | - } | ||
585 | - info.line_type = one_lane.cls; | ||
586 | - one_road.vec_line.push_back(info); | ||
587 | - } | 64 | + RoadInfo one_road = parse_road(one_result, vec_img[b]); |
65 | + one_road.vec_direct = parse_direct(one_result, vec_img[b]); | ||
66 | + vec_road.push_back(one_road); | ||
67 | + } | ||
68 | + | ||
69 | + } while (0); | ||
70 | + | ||
71 | + for (int b = 0; b < batchsize; b++) { | ||
72 | + delete[] results[b].seg_array; | ||
73 | + results[b].seg_array = NULL; | ||
74 | + delete[] results[b].direct_seg; | ||
75 | + results[b].direct_seg = NULL; | ||
76 | + } | ||
77 | + | ||
78 | + return vec_road; | ||
79 | +} | ||
80 | + | ||
81 | +RoadInfo RoadSegAnalysis::parse_road(rs_result one_result, sy_img src) | ||
82 | +{ | ||
83 | + RoadInfo one_road; | ||
84 | + | ||
85 | + std::vector<std::pair<std::vector<cv::Point>, int>> combined; | ||
86 | + lanes_process(one_result.reg_array, one_result.lane_count, combined); | ||
87 | + std::vector<std::vector<cv::Point>> poly_masks, lanes; | ||
88 | + std::vector<int> region_classes, cats; | ||
89 | + std::map<double, int> x_sort; | ||
90 | + bool large_resolution = false; | ||
91 | + if (src.w_ > 1920) large_resolution = true; | ||
92 | + | ||
93 | + cv::Mat seg_output = seg_post_process(large_resolution, one_result.seg_array, combined, poly_masks, region_classes, lanes, cats, x_sort); //m_masks:mask前的结果 poly_masks后的结果 | ||
588 | 94 | ||
589 | - one_road.vec_road = parse_seg(one_result, vec_img[b]); | ||
590 | - one_road.direct_mask = parse_direct(one_result, vec_img[b]); | 95 | + for (int i = 0; i < lanes.size(); ++i) { |
96 | + std::vector<cv::Point> points = lanes[i]; | ||
97 | + LineInfo info; | ||
98 | + for (size_t j = 0; j < points.size(); j++) | ||
99 | + { | ||
100 | + sy_point pt; | ||
101 | + pt.x_ = points[j].x; | ||
102 | + pt.y_ = points[j].y; | ||
591 | 103 | ||
592 | - post_direct(one_result, vec_img[b]); | ||
593 | - | ||
594 | - vec_road.push_back(one_road); | 104 | + info.vec_pt.push_back(pt); |
595 | } | 105 | } |
106 | + info.line_type = cats[i]; | ||
107 | + one_road.vec_line.push_back(info); | ||
108 | + } | ||
109 | + | ||
110 | + for (int i = 0; i < poly_masks.size(); ++i) { | ||
111 | + std::vector<cv::Point> points = poly_masks[i]; | ||
112 | + SegInfo seg_info; | ||
113 | + for (int j = 0; j < points.size(); ++j) { | ||
114 | + sy_point pt; | ||
115 | + pt.x_ = points[j].x; | ||
116 | + pt.y_ = points[j].y; | ||
596 | 117 | ||
597 | - } while (0); | 118 | + seg_info.vec_pt.push_back(pt); |
119 | + } | ||
120 | + seg_info.seg_type = region_classes[i]; | ||
121 | + one_road.vec_road.push_back(seg_info); | ||
122 | + } | ||
123 | +} | ||
598 | 124 | ||
599 | - for (int b = 0; b < batchsize; b++) { | ||
600 | - delete[] results[b].seg_array; | ||
601 | - results[b].seg_array = NULL; | ||
602 | - delete[] results[b].direct_seg; | ||
603 | - results[b].direct_seg = NULL; | 125 | +std::vector<SegInfo> RoadSegAnalysis::parse_direct(rs_result one_result, sy_img src) { |
126 | + std::vector<std::pair<std::vector<cv::Point>, int>> combined; | ||
127 | + lanes_process(one_result.reg_array, one_result.lane_count, combined); | ||
128 | + std::vector<std::vector<cv::Point>> poly_masks, lanes; | ||
129 | + std::vector<int> region_classes, cats; | ||
130 | + std::map<double, int> x_sort; | ||
131 | + bool large_resolution = false; | ||
132 | + if (src.w_ > 1920) large_resolution = true; | ||
133 | + | ||
134 | + cv::Mat seg_output = seg_post_process(large_resolution, one_result.direct_seg, combined, poly_masks, region_classes, lanes, cats, x_sort); //m_masks:mask前的结果 poly_masks后的结果 | ||
135 | + | ||
136 | + std::vector<SegInfo> vec_road; | ||
137 | + for (int i = 0; i < poly_masks.size(); ++i) { | ||
138 | + std::vector<cv::Point> points = poly_masks[i]; | ||
139 | + SegInfo seg_info; | ||
140 | + for (int j = 0; j < points.size(); ++j) { | ||
141 | + sy_point pt; | ||
142 | + pt.x_ = points[j].x; | ||
143 | + pt.y_ = points[j].y; | ||
144 | + | ||
145 | + seg_info.vec_pt.push_back(pt); | ||
146 | + } | ||
147 | + seg_info.seg_type = region_classes[i]; | ||
148 | + vec_road.push_back(seg_info); | ||
604 | } | 149 | } |
605 | 150 | ||
606 | return vec_road; | 151 | return vec_road; |
@@ -622,95 +167,81 @@ int RoadSegAnalysis::release() { | @@ -622,95 +167,81 @@ int RoadSegAnalysis::release() { | ||
622 | return SY_SUCCESS; | 167 | return SY_SUCCESS; |
623 | } | 168 | } |
624 | 169 | ||
625 | -std::vector<SegInfo> RoadSegAnalysis::parse_seg(rs_result one_result, sy_img src) { | ||
626 | - int w = 640; | ||
627 | - int h = 360; | ||
628 | - float alpha = 0.75; | ||
629 | - cv::Mat overlayed_img(cv::Size(w,h), CV_8UC3, cv::Scalar(0, 0, 0)); | ||
630 | - // 将车道线标签转换为彩色图像 | ||
631 | - for (int i = 0; i < h; ++i) { | ||
632 | - for (int j = 0; j < w; ++j) { | ||
633 | - int idx = one_result.seg_array[(i * w + j)]; | ||
634 | - overlayed_img.at<cv::Vec3b>(i, j)[0] = seg_colors[idx][0]; // R通道; | ||
635 | - overlayed_img.at<cv::Vec3b>(i, j)[1] = seg_colors[idx][1]; // G通道 | ||
636 | - overlayed_img.at<cv::Vec3b>(i, j)[2] = seg_colors[idx][2]; // B通道 | ||
637 | - } | ||
638 | - } | 170 | +// head_or_tail 0:车头 1:车尾 |
171 | +int RoadSegAnalysis::check_reverse_driving(std::vector<SegInfo>& vec_direct, sy_rect src_rc, int src_width, int src_height, int head_or_tail) { | ||
639 | 172 | ||
640 | - cv::resize(overlayed_img, overlayed_img, cv::Size(src.w_,src.h_), 0, 0, cv::INTER_LINEAR); | ||
641 | - // 将原始图像和彩色车道线图进行混合 | ||
642 | - // cv::addWeighted(cvImg, alpha, overlayed_img, 1 - alpha, 0, overlayed_img); | 173 | + float scale_w = 640.0 / src_width; |
174 | + float scale_h = 360.0 / src_height; | ||
643 | 175 | ||
644 | - float scale_w = src.w_ / 640.0; | ||
645 | - float scale_h = src.h_ / 360.0; | ||
646 | - std::vector<std::pair<std::vector<cv::Point>, int>> combined; | ||
647 | - lanes_process(one_result.reg_array, one_result.lane_count, combined, scale_w, scale_h); | 176 | + sy_rect rc; |
177 | + rc.left_ = src_rc.left_ * scale_w; | ||
178 | + rc.width_ = src_rc.width_ * scale_w; | ||
179 | + rc.top_ = src_rc.top_ * scale_h; | ||
180 | + rc.height_ = src_rc.height_ * scale_h; | ||
648 | 181 | ||
649 | - std::vector<SegInfo> vec_seg; | ||
650 | - for (const auto& lane_info : combined) { | ||
651 | - const auto& xys = lane_info.first; | ||
652 | - int cls = lane_info.second; | ||
653 | - SegInfo info; | ||
654 | - info.seg_type = cls; | ||
655 | - // cv::Scalar color(lane_colors[cls][0],lane_colors[cls][1],lane_colors[cls][2]); | ||
656 | - for (size_t i = 0; i < xys.size(); ++i) { | ||
657 | - // cv::line(overlayed_img, xys[i - 1], xys[i], color, 4); | ||
658 | - sy_point pt; | ||
659 | - pt.x_ = xys[i].x; | ||
660 | - pt.y_ = xys[i].y; | ||
661 | - info.vec_pt.push_back(pt); | 182 | + std::vector<cv::Point> polygon_pts; |
183 | + cv::Point pt_lt; | ||
184 | + pt_lt.x = rc.left_; | ||
185 | + pt_lt.y = rc.top_; | ||
186 | + polygon_pts.push_back(pt_lt); | ||
187 | + cv::Point pt_rt; | ||
188 | + pt_rt.x = rc.left_ + rc.width_; | ||
189 | + pt_rt.y = rc.top_; | ||
190 | + polygon_pts.push_back(pt_rt); | ||
191 | + cv::Point pt_rb; | ||
192 | + pt_rb.x = rc.left_ + rc.width_; | ||
193 | + pt_rb.y = rc.top_ + rc.height_; | ||
194 | + polygon_pts.push_back(pt_rb); | ||
195 | + cv::Point pt_lb; | ||
196 | + pt_lb.x = rc.left_; | ||
197 | + pt_lb.y = rc.top_ + rc.height_; | ||
198 | + polygon_pts.push_back(pt_lb); | ||
199 | + | ||
200 | + int coming_count = 0; | ||
201 | + int leaving_count = 0; | ||
202 | + for (size_t i = 0; i < vec_direct.size(); i++) { | ||
203 | + SegInfo& region = vec_direct[i]; | ||
204 | + if (region.seg_type == 1) { | ||
205 | + std::vector<cv::Point> vec_pt; | ||
206 | + for (size_t j = 0; j < region.vec_pt.size(); j++) { | ||
207 | + double dist = pointPolygonTest(polygon_pts, cv::Point2f(region.vec_pt[j].x_, region.vec_pt[j].y_), false); | ||
208 | + if (dist > 0) { | ||
209 | + coming_count ++; | ||
210 | + } | ||
211 | + } | ||
212 | + } else if (region.seg_type == 2) { | ||
213 | + std::vector<cv::Point> vec_pt; | ||
214 | + for (size_t j = 0; j < region.vec_pt.size(); j++) { | ||
215 | + double dist = pointPolygonTest(polygon_pts, cv::Point2f(region.vec_pt[j].x_, region.vec_pt[j].y_), false); | ||
216 | + if (dist > 0) { | ||
217 | + leaving_count ++; | ||
218 | + } | ||
219 | + } | ||
662 | } | 220 | } |
663 | - vec_seg.push_back(info); | ||
664 | } | 221 | } |
665 | 222 | ||
666 | - return vec_seg; | ||
667 | -} | ||
668 | - | ||
669 | -cv::Mat RoadSegAnalysis::parse_direct(rs_result one_result, sy_img src){ | ||
670 | - int src_width = src.w_; | ||
671 | - | ||
672 | - std::vector<std::pair<std::vector<cv::Point>, int>> combined; | ||
673 | - lanes_process(one_result.reg_array, one_result.lane_count, combined); | ||
674 | - std::vector<std::vector<cv::Point>> poly_masks, lanes, direct_masks, merge_masks; | ||
675 | - std::vector<int> region_classes, cats, direct_classes, merge_classes; | ||
676 | - cv::Mat background_mask; | ||
677 | - std::map<double, int> x_sort; | ||
678 | - bool large_resolution = false; | ||
679 | - if (src_width > 1920) large_resolution = true; | ||
680 | - cv::Mat seg_output = seg_post_process(large_resolution, one_result.seg_array, combined, poly_masks, region_classes, lanes, cats, x_sort, background_mask); //m_masks:mask前的结果 poly_masks后的结果 | ||
681 | - cv::Mat direct_output = direct_post_process(large_resolution, one_result.direct_seg, direct_masks, direct_classes); | ||
682 | - | ||
683 | - | ||
684 | - // std::vector<std::vector<cv::Point>> direct_masks; | ||
685 | - // std::vector<int> direct_classes; | ||
686 | - // bool large_resolution = false; | ||
687 | - // if (src_width > 1920) large_resolution = true; | ||
688 | - // cv::Mat direct_output = direct_post_process(large_resolution, one_result.direct_seg, direct_masks, direct_classes); | ||
689 | - | ||
690 | - // cv::Mat image(cv::Size(640, 360), CV_8UC3, cv::Scalar(0, 0, 0)); | ||
691 | - // cv::Mat merge_image = mask_to_rgb(image, direct_output); | ||
692 | - // cv::imwrite("direct.jpg", merge_image); | ||
693 | - | ||
694 | - int direct = direct_output.at<int>(455, 146); | 223 | + int direct = 0; |
224 | + if(coming_count > 0 && leaving_count > 0) { | ||
225 | + if (coming_count > leaving_count) { | ||
226 | + direct = 1; | ||
227 | + } else { | ||
228 | + direct = 2; | ||
229 | + } | ||
230 | + } else if(coming_count > 0 && leaving_count <= 0) { | ||
231 | + direct = 1; | ||
232 | + } else if(coming_count <= 0 && leaving_count > 0) { | ||
233 | + direct = 2; | ||
234 | + } | ||
695 | 235 | ||
696 | - return direct_output; | ||
697 | -} | ||
698 | 236 | ||
699 | -// head_or_tail 0:车头 1:车尾 | ||
700 | -int RoadSegAnalysis::check_reverse_driving(cv::Mat direct_mask, sy_rect rc, int src_width, int src_height, int head_or_tail) { | ||
701 | - // cv::Mat image(cv::Size(640, 360), CV_8UC3, cv::Scalar(0, 0, 0)); | ||
702 | - // cv::Mat merge_image = mask_to_rgb(image, direct_mask); | ||
703 | - // cv::imwrite("direct_mask.jpg", merge_image); | 237 | + // int center_x = (rc.left_ + rc.width_ / 2) * scale_w; |
238 | + // int center_y = (rc.top_ + rc.height_ / 2) * scale_h; | ||
239 | + // if(center_x < 0 ||center_x >= direct_mask.cols || center_y < 0 || center_y >= direct_mask.rows){ | ||
240 | + // return -1; | ||
241 | + // } | ||
704 | 242 | ||
705 | - float scale_w = 640.0 / src_width; | ||
706 | - float scale_h = 360.0 / src_height; | ||
707 | - int center_x = (rc.left_ + rc.width_ / 2) * scale_w; | ||
708 | - int center_y = (rc.top_ + rc.height_ / 2) * scale_h; | ||
709 | - if(center_x < 0 ||center_x >= direct_mask.cols || center_y < 0 || center_y >= direct_mask.rows){ | ||
710 | - return -1; | ||
711 | - } | ||
712 | // '来': 1, '去': 2, '近': 3, '远': 4 | 243 | // '来': 1, '去': 2, '近': 3, '远': 4 |
713 | - int direct = direct_mask.at<int>(center_x, center_y); | 244 | + // int direct = direct_mask.at<int>(center_x, center_y); |
714 | if (direct == 1 && head_or_tail == 0) { | 245 | if (direct == 1 && head_or_tail == 0) { |
715 | // 来车道,车头,正常行驶 | 246 | // 来车道,车头,正常行驶 |
716 | return 0; | 247 | return 0; |
@@ -728,7 +259,16 @@ int RoadSegAnalysis::check_reverse_driving(cv::Mat direct_mask, sy_rect rc, int | @@ -728,7 +259,16 @@ int RoadSegAnalysis::check_reverse_driving(cv::Mat direct_mask, sy_rect rc, int | ||
728 | return -1; | 259 | return -1; |
729 | } | 260 | } |
730 | 261 | ||
731 | -int RoadSegAnalysis::check_cross_line(std::vector<LineInfo>& vec_line, sy_rect rc) { | 262 | +int RoadSegAnalysis::check_cross_line(std::vector<LineInfo>& vec_line, sy_rect src_rc) { |
263 | + | ||
264 | + float scale_w = 640.0 / src_rc.width_; | ||
265 | + float scale_h = 360.0 / src_rc.height_; | ||
266 | + | ||
267 | + sy_rect rc; | ||
268 | + rc.left_ = src_rc.left_ * scale_w; | ||
269 | + rc.width_ = src_rc.width_ * scale_w; | ||
270 | + rc.top_ = src_rc.top_ * scale_h; | ||
271 | + rc.height_ = src_rc.height_ * scale_h; | ||
732 | 272 | ||
733 | std::vector<cv::Point> polygon_pts; | 273 | std::vector<cv::Point> polygon_pts; |
734 | cv::Point pt_lt; | 274 | cv::Point pt_lt; |
@@ -816,7 +356,123 @@ int RoadSegAnalysis::check_cross_region(std::vector<SegInfo>& vec_reg, sy_rect r | @@ -816,7 +356,123 @@ int RoadSegAnalysis::check_cross_region(std::vector<SegInfo>& vec_reg, sy_rect r | ||
816 | return -1; | 356 | return -1; |
817 | } | 357 | } |
818 | 358 | ||
819 | -cv::Mat imshow_lanes(cv::Mat img, const rs_lane* lanes, int lane_count) { | 359 | +// cv::Mat imshow_lanes(cv::Mat img, const rs_lane* lanes, int lane_count) { |
360 | +// float scale_w = img.cols / 640.0; | ||
361 | +// float scale_h = img.rows / 360.0; | ||
362 | +// std::vector<std::pair<std::vector<cv::Point>, int>> combined; | ||
363 | +// lanes_process(lanes, lane_count, combined, scale_w, scale_h); | ||
364 | + | ||
365 | +// for (const auto& lane_info : combined) { | ||
366 | +// const auto& xys = lane_info.first; | ||
367 | +// int cls = lane_info.second; | ||
368 | +// cv::Scalar color(lane_colors[cls][0],lane_colors[cls][1],lane_colors[cls][2]); | ||
369 | +// for (size_t i = 1; i < xys.size(); ++i) { | ||
370 | +// cv::line(img, xys[i - 1], xys[i], color, 4); | ||
371 | +// } | ||
372 | +// } | ||
373 | + | ||
374 | +// return img; | ||
375 | +// } | ||
376 | + | ||
377 | +// void RoadSegAnalysis::post_direct(rs_result one_result, sy_img src){ | ||
378 | +// int src_width = src.w_; | ||
379 | +// int src_height = src.h_; | ||
380 | +// int w = 640; | ||
381 | +// int h = 360; | ||
382 | +// float alpha = 0.75; | ||
383 | +// cv::Mat overlayed_direct_img(cv::Size(w,h), CV_8UC3, cv::Scalar(0, 0, 0)); | ||
384 | +// // 将车道线标签转换为彩色图像 | ||
385 | +// for (int i = 0; i < h; ++i) { | ||
386 | +// for (int j = 0; j < w; ++j) { | ||
387 | +// int idx = one_result.direct_seg[(i * w + j)]; | ||
388 | +// overlayed_direct_img.at<cv::Vec3b>(i, j)[0] = seg_colors[idx][0]; // R通道; | ||
389 | +// overlayed_direct_img.at<cv::Vec3b>(i, j)[1] = seg_colors[idx][1]; // G通道 | ||
390 | +// overlayed_direct_img.at<cv::Vec3b>(i, j)[2] = seg_colors[idx][2]; // B通道 | ||
391 | +// } | ||
392 | +// } | ||
393 | +// cv::resize(overlayed_direct_img, overlayed_direct_img, cv::Size(src_width,src_height), 0, 0, cv::INTER_LINEAR); | ||
394 | +// // 将原始图像和彩色车道线图进行混合 | ||
395 | +// // cv::addWeighted(cvImg, alpha, overlayed_direct_img, 1 - alpha, 0, overlayed_direct_img); | ||
396 | +// cv::Mat img_direct_lane = imshow_lanes(overlayed_direct_img, one_result.reg_array, one_result.lane_count); | ||
397 | +// cv::imwrite("img_direct_lane.jpg", img_direct_lane); | ||
398 | + | ||
399 | + | ||
400 | +// std::vector<std::pair<std::vector<cv::Point>, int>> combined; | ||
401 | +// lanes_process(one_result.reg_array, one_result.lane_count, combined); | ||
402 | +// std::vector<std::vector<cv::Point>> poly_masks, lanes, direct_masks, merge_masks; | ||
403 | +// std::vector<int> region_classes, cats, direct_classes, merge_classes; | ||
404 | +// cv::Mat background_mask; | ||
405 | +// std::map<double, int> x_sort; | ||
406 | +// bool large_resolution = false; | ||
407 | +// if (src_height > 1920) large_resolution = true; | ||
408 | +// cv::Mat seg_output = seg_post_process(large_resolution, one_result.seg_array, combined, poly_masks, region_classes, lanes, cats, x_sort, background_mask); //m_masks:mask前的结果 poly_masks后的结果 | ||
409 | +// cv::Mat direct_output = direct_post_process(large_resolution, one_result.direct_seg, direct_masks, direct_classes); | ||
410 | +// cv::Mat merge_output = merge_direct_process(large_resolution, one_result.direct_seg, merge_masks, merge_classes); | ||
411 | + | ||
412 | +// cv::Mat image(cv::Size(w,h), CV_8UC3, cv::Scalar(0, 0, 0)); | ||
413 | +// cv::Mat vis_image = mask_to_rgb(image, seg_output); | ||
414 | +// cv::Mat direct_image = mask_to_rgb(image, direct_output); | ||
415 | +// cv::Mat merge_image = mask_to_rgb(image, merge_output); | ||
416 | +// cv::imwrite("vis_image.jpg", vis_image); | ||
417 | +// cv::imwrite("direct_image.jpg", direct_image); | ||
418 | +// cv::imwrite("merge_image.jpg", merge_image); | ||
419 | +// cv::imwrite("background_mask.jpg", background_mask); | ||
420 | +// } | ||
421 | + | ||
422 | + | ||
423 | +cv::Mat RoadSegAnalysis::mask_to_rgb(cv::Mat img, cv::Mat mask) { | ||
424 | + cv::Mat masks = img.clone(); | ||
425 | + int reg_cls = 8; | ||
426 | + for (int i = 0; i < masks.rows; i++) { | ||
427 | + for (int j = 0; j < masks.cols; j++) { | ||
428 | + for (int k = 1; k < reg_cls; k++) { | ||
429 | + if (mask.at<int>(i,j) == k) { | ||
430 | + masks.at<cv::Vec3b>(i,j)[0] = seg_colors[k][0]; | ||
431 | + masks.at<cv::Vec3b>(i,j)[1] = seg_colors[k][1]; | ||
432 | + masks.at<cv::Vec3b>(i,j)[2] = seg_colors[k][2]; | ||
433 | + } | ||
434 | + } | ||
435 | + } | ||
436 | + } | ||
437 | + return masks; | ||
438 | +} | ||
439 | + | ||
440 | +float RoadSegAnalysis::contourArea(std::vector<cv::Point> contour, cv::Point2f& center) { | ||
441 | + cv::RotatedRect rect = cv::minAreaRect(contour); // 最小外接矩形 rect[0]中心点 rect[1]宽 高 rect[2]旋转角度 | ||
442 | + center = rect.center; | ||
443 | + return cv::contourArea(contour); | ||
444 | +} | ||
445 | + | ||
446 | +void RoadSegAnalysis::lanes_process(const rs_lane* lanes, int lane_count, std::vector<std::pair<std::vector<cv::Point>, int>>& combined, float scale_w, float scale_h) { | ||
447 | + std::vector<std::vector<cv::Point> > lanes_xys; | ||
448 | + std::vector<int> lanes_cls; | ||
449 | + for (int i = 0; i < lane_count; i++) { | ||
450 | + std::vector<cv::Point> xys; | ||
451 | + for (int j = 0; j < lanes[i].num_points; j++) { | ||
452 | + int x = static_cast<int>(lanes[i].points[j].x_ * scale_w); | ||
453 | + int y = static_cast<int>(lanes[i].points[j].y_ * scale_h); | ||
454 | + if (x > 0 && y > 0) { | ||
455 | + xys.emplace_back(x, y); | ||
456 | + } | ||
457 | + } | ||
458 | + if (!xys.empty()) { | ||
459 | + lanes_xys.push_back(xys); | ||
460 | + lanes_cls.push_back(lanes[i].cls); | ||
461 | + } | ||
462 | + } | ||
463 | + | ||
464 | + for (size_t i = 0; i < lanes_xys.size(); ++i) { | ||
465 | + combined.push_back(std::make_pair(lanes_xys[i], lanes_cls[i])); | ||
466 | + } | ||
467 | + if (!combined.empty()) { | ||
468 | + //按车道线起点坐标排序,相应的类别顺序也会变化以保证标签对齐 | ||
469 | + std::sort(combined.begin(), combined.end(), [](const std::pair<std::vector<cv::Point>, int>& a, const std::pair<std::vector<cv::Point>, int>& b) { | ||
470 | + return a.first[0].x < b.first[0].x; | ||
471 | + }); | ||
472 | + } | ||
473 | +} | ||
474 | + | ||
475 | +cv::Mat RoadSegAnalysis::imshow_lanes(cv::Mat img, const rs_lane* lanes, int lane_count) { | ||
820 | float scale_w = img.cols / 640.0; | 476 | float scale_w = img.cols / 640.0; |
821 | float scale_h = img.rows / 360.0; | 477 | float scale_h = img.rows / 360.0; |
822 | std::vector<std::pair<std::vector<cv::Point>, int>> combined; | 478 | std::vector<std::pair<std::vector<cv::Point>, int>> combined; |
@@ -834,47 +490,145 @@ cv::Mat imshow_lanes(cv::Mat img, const rs_lane* lanes, int lane_count) { | @@ -834,47 +490,145 @@ cv::Mat imshow_lanes(cv::Mat img, const rs_lane* lanes, int lane_count) { | ||
834 | return img; | 490 | return img; |
835 | } | 491 | } |
836 | 492 | ||
837 | -void RoadSegAnalysis::post_direct(rs_result one_result, sy_img src){ | ||
838 | - int src_width = src.w_; | ||
839 | - int src_height = src.h_; | ||
840 | - int w = 640; | ||
841 | - int h = 360; | ||
842 | - float alpha = 0.75; | ||
843 | - cv::Mat overlayed_direct_img(cv::Size(w,h), CV_8UC3, cv::Scalar(0, 0, 0)); | ||
844 | - // 将车道线标签转换为彩色图像 | ||
845 | - for (int i = 0; i < h; ++i) { | ||
846 | - for (int j = 0; j < w; ++j) { | ||
847 | - int idx = one_result.direct_seg[(i * w + j)]; | ||
848 | - overlayed_direct_img.at<cv::Vec3b>(i, j)[0] = seg_colors[idx][0]; // R通道; | ||
849 | - overlayed_direct_img.at<cv::Vec3b>(i, j)[1] = seg_colors[idx][1]; // G通道 | ||
850 | - overlayed_direct_img.at<cv::Vec3b>(i, j)[2] = seg_colors[idx][2]; // B通道 | 493 | +int RoadSegAnalysis::Mask2LanePoints(const cv::Mat& pred, std::vector<std::vector<cv::Point>>&lanes, std::vector<int>& cats) { |
494 | + std::vector<int> labels = {8, 9, 10, 11}; | ||
495 | + for(auto cat: labels) { | ||
496 | + cv::Mat b_masks, measure_labels, stats, centroids; | ||
497 | + cv::compare(pred, cat, b_masks, cv::CMP_EQ); //将pred元素逐个和cat比较,相同255,不同0 | ||
498 | + // cv::threshold(pred, b_masks, 126, 255, cv::THRESH_OTSU); //生成二值图 | ||
499 | + // 连通域计算 b_masks:闭操作后的二值图像 measure_labels:和原图一样大的标记图 centroids:nccomps×2的矩阵,表示每个连通域的质心(x, y) | ||
500 | + // stats:nccomps×5的矩阵 表示每个连通区域的外接矩形和面积(x, y, w, h, area),索引0是背景信息 | ||
501 | + int nccomps = cv::connectedComponentsWithStats (b_masks, measure_labels, stats, centroids, 4); //8 | ||
502 | + for(int cv_measure_id = 1; cv_measure_id < nccomps; cv_measure_id++ ) { //跳过背景信息0 | ||
503 | + cv::Mat cv_measure_mask; | ||
504 | + cv::compare(measure_labels, cv_measure_id, cv_measure_mask, cv::CMP_EQ); | ||
505 | + std::vector< std::vector< cv::Point> > contours; | ||
506 | + cv::findContours(cv_measure_mask,contours,cv::noArray(),cv::RETR_TREE,cv::CHAIN_APPROX_SIMPLE); | ||
507 | + std::vector<cv::Point> contours_poly; | ||
508 | + for (int j = 0; j < contours.size();j++) { | ||
509 | + float area = cv::contourArea(contours[j]); if (area < 60) continue; //30 | ||
510 | + cv::approxPolyDP(cv::Mat(contours[j]), contours_poly, 6, true); //减小epsilon提高拟合精度(需要调试,epsilon过小会使多边形不够简化,单条线变多条) | ||
511 | + if (contours_poly.size() == 1) continue; | ||
512 | + lanes.push_back(contours_poly); | ||
513 | + cats.push_back(cat); | ||
514 | + } | ||
515 | + } | ||
516 | + } | ||
517 | + return 0; | ||
518 | +} | ||
519 | + | ||
520 | + | ||
521 | +cv::Mat RoadSegAnalysis::seg_post_process(bool large_resolution, unsigned char *seg_array, std::vector<std::pair<std::vector<cv::Point>, int>> combined, std::vector<std::vector<cv::Point>> &poly_masks, std::vector<int> ®ion_classes, std::vector<std::vector<cv::Point>> &lanes, std::vector<int> &cats, std::map<double, int> &x_sort) { | ||
522 | + std::vector<int> pred_cls; | ||
523 | + int h = 360, w = 640; | ||
524 | + cv::Mat lanes_masks = cv::Mat_<int>(h,w); //正常分割结果 | ||
525 | + cv::Mat mask_rmlane = cv::Mat_<int>(h,w); //车道线区域置为背景 | ||
526 | + cv::Mat solve_masks = cv::Mat_<int>(h,w); //计算主行驶区域用(虚线及减速标线归入行车道) | ||
527 | + int step_size = h*w; | ||
528 | + int seg_min_region_area = 512; //1024 | ||
529 | + | ||
530 | + for (int i = 0; i < h; ++i) { | ||
531 | + for (int j = 0; j < w; ++j) { | ||
532 | + int max_cls = seg_array[(i * w + j)]; | ||
533 | + lanes_masks.ptr<int>(i)[j] = max_cls; | ||
534 | + pred_cls.push_back(max_cls); | ||
535 | + mask_rmlane.ptr<int>(i)[j] = max_cls; | ||
536 | + solve_masks.ptr<int>(i)[j] = max_cls; | ||
537 | + } | ||
538 | + } | ||
539 | + | ||
540 | + for (const auto& lane_info : combined) { | ||
541 | + const auto& xys = lane_info.first; | ||
542 | + int cls = lane_info.second; | ||
543 | + if (cls == 1) cls = 8; /*黄实线*/ if (cls == 2) cls = 9; /*白实线*/ | ||
544 | + if (cls == 3) cls = 10; /*虚线*/ if (cls == 4) cls = 11; /*黄虚线*/ | ||
545 | + for (size_t i = 1; i < xys.size(); ++i) { | ||
546 | + cv::line(lanes_masks, xys[i - 1], xys[i], cls, 4); //绘制车道线用于求连通域 | ||
547 | + if (cls == 10 || cls == 11) cls = 1; //求主行驶区域时将虚线归入行车道 | ||
548 | + cv::line(solve_masks, xys[i - 1], xys[i], cls, 4); | ||
549 | + | ||
851 | } | 550 | } |
852 | } | 551 | } |
853 | - cv::resize(overlayed_direct_img, overlayed_direct_img, cv::Size(src_width,src_height), 0, 0, cv::INTER_LINEAR); | ||
854 | - // 将原始图像和彩色车道线图进行混合 | ||
855 | - // cv::addWeighted(cvImg, alpha, overlayed_direct_img, 1 - alpha, 0, overlayed_direct_img); | ||
856 | - cv::Mat img_direct_lane = imshow_lanes(overlayed_direct_img, one_result.reg_array, one_result.lane_count); | ||
857 | - cv::imwrite("img_direct_lane.jpg", img_direct_lane); | ||
858 | 552 | ||
553 | + /* 求背景区域--mask车道区域,场景变化用 | ||
554 | + cv::compare(lanes_masks, 0, background_mask, cv::CMP_EQ); //将lanes_masks元素逐个和0比较,相同255,不同0*/ | ||
555 | +#if 1 | ||
556 | + //--mask远处区域------------------------------------------------ | ||
557 | + cv::Mat mask_black = mask_rmlane.clone(); | ||
558 | + if (large_resolution) mask_black(cv::Rect(0, 0, w, int(h * 0.14))) = 0; | ||
559 | + else mask_black(cv::Rect(0, 0, w, int(h * 0.22))) = 0; | ||
560 | + mask_black(cv::Rect(0, int(h * 0.95), w, int(h * 0.05))) = 0; | ||
561 | + mask_black(cv::Rect(0, 0, int(w * 0.02), h)) = 0; | ||
562 | + mask_black(cv::Rect(int(w * 0.95), 0, int(w * 0.05), h)) = 0; | ||
563 | + mask_rmlane = mask_black; | ||
564 | + //------------------------------------------------------------------------- | ||
565 | +#endif | ||
566 | + //2.去重获取预测到的类别 | ||
567 | + std::vector<int> labels(pred_cls); | ||
568 | + std::sort(labels.begin(),labels.end()); | ||
569 | + labels.erase(std::unique(labels.begin(),labels.end()),labels.end()); | ||
570 | + | ||
571 | + //4.求车道线区域 | ||
572 | + int flag = Mask2LanePoints(lanes_masks, lanes, cats); ///////////////////////// 车道线如何与mask结合 | ||
573 | + | ||
574 | + //5.求道路区域 | ||
575 | + int count = 0; | ||
576 | + for(auto cat: labels) { | ||
577 | + // std::cout << cat << std::endl; | ||
578 | + cv::Mat b_masks, measure_labels, stats, centroids; | ||
579 | + cv::Mat n_masks = cv::Mat_<int>(h,w); | ||
580 | + n_masks = cv::Scalar(255); | ||
581 | + cv::compare(mask_rmlane, cat, b_masks, cv::CMP_EQ); //将mask_rmlane元素逐个和cat比较,相同255,不同0 | ||
582 | + //连通域计算 | ||
583 | + int nccomps = cv::connectedComponentsWithStats (b_masks, measure_labels, stats, centroids, 8); | ||
584 | + for(int i = 1; i < nccomps; i++ ) { //跳过背景信息0 | ||
585 | + //移除过小的区域,并将对应位置置为0 | ||
586 | + if (stats.at<int>(i, cv::CC_STAT_AREA) < seg_min_region_area) { | ||
587 | + cv::Mat comparison_result; | ||
588 | + cv::compare(measure_labels, cv::Scalar(i), comparison_result, cv::CMP_EQ); //相等为255不等为0 | ||
589 | + n_masks.setTo(0, comparison_result); // 将comparison_result中非零区域置为0 | ||
590 | + | ||
591 | + cv::bitwise_and(mask_rmlane,n_masks,mask_rmlane); | ||
592 | + continue; | ||
593 | + } | ||
859 | 594 | ||
860 | - std::vector<std::pair<std::vector<cv::Point>, int>> combined; | ||
861 | - lanes_process(one_result.reg_array, one_result.lane_count, combined); | ||
862 | - std::vector<std::vector<cv::Point>> poly_masks, lanes, direct_masks, merge_masks; | ||
863 | - std::vector<int> region_classes, cats, direct_classes, merge_classes; | ||
864 | - cv::Mat background_mask; | ||
865 | - std::map<double, int> x_sort; | ||
866 | - bool large_resolution = false; | ||
867 | - if (src_height > 1920) large_resolution = true; | ||
868 | - cv::Mat seg_output = seg_post_process(large_resolution, one_result.seg_array, combined, poly_masks, region_classes, lanes, cats, x_sort, background_mask); //m_masks:mask前的结果 poly_masks后的结果 | ||
869 | - cv::Mat direct_output = direct_post_process(large_resolution, one_result.direct_seg, direct_masks, direct_classes); | ||
870 | - cv::Mat merge_output = merge_direct_process(large_resolution, one_result.direct_seg, merge_masks, merge_classes); | ||
871 | - | ||
872 | - cv::Mat image(cv::Size(w,h), CV_8UC3, cv::Scalar(0, 0, 0)); | ||
873 | - cv::Mat vis_image = mask_to_rgb(image, seg_output); | ||
874 | - cv::Mat direct_image = mask_to_rgb(image, direct_output); | ||
875 | - cv::Mat merge_image = mask_to_rgb(image, merge_output); | ||
876 | - cv::imwrite("vis_image.jpg", vis_image); | ||
877 | - cv::imwrite("direct_image.jpg", direct_image); | ||
878 | - cv::imwrite("merge_image.jpg", merge_image); | ||
879 | - cv::imwrite("background_mask.jpg", background_mask); | 595 | + double centr_x = centroids.at<double>(i, 0); |
596 | + double centr_y = centroids.at<double>(i, 1); | ||
597 | + | ||
598 | + int region_class = cat; | ||
599 | + // printf("region_class: %d\n", region_class); | ||
600 | + cv::Mat region_mask; | ||
601 | + cv::bitwise_and(measure_labels,n_masks,measure_labels);///// | ||
602 | + cv::compare(measure_labels, i, region_mask, cv::CMP_EQ); | ||
603 | + | ||
604 | + std::vector< std::vector< cv::Point> > contours; | ||
605 | + cv::findContours(region_mask,contours,cv::noArray(),cv::RETR_TREE,cv::CHAIN_APPROX_SIMPLE); | ||
606 | + std::vector<cv::Point> contours_poly; | ||
607 | + for (int j = 0; j < contours.size();j++) { | ||
608 | + cv::approxPolyDP(cv::Mat(contours[j]), contours_poly, 10, true); | ||
609 | + if (contours_poly.size() <= 2) continue; | ||
610 | + poly_masks.push_back(contours_poly); | ||
611 | + region_classes.push_back(cat); | ||
612 | + if (x_sort.count(centr_x)) centr_x += 0.0001; | ||
613 | + x_sort.insert(std::make_pair(centr_x, count)); | ||
614 | + ++ count; | ||
615 | + // for (auto iter: contours_poly) { | ||
616 | + // std::cout << "contour " << iter << " " << cat << std::endl; | ||
617 | + // } | ||
618 | + | ||
619 | + } | ||
620 | + } | ||
621 | + } | ||
622 | + | ||
623 | +#if 0 | ||
624 | + //6.draw lanes | ||
625 | + for (int i = 0; i < lanes.size(); ++i) { | ||
626 | + int thickness = 4; | ||
627 | + for (int j = 0; j < lanes[i].size()-1; ++j) { | ||
628 | + cv::line(mask_rmlane, lanes[i][j], lanes[i][j+1], {seg_colors[cats[i]][0],seg_colors[cats[i]][1],seg_colors[cats[i]][2]}, thickness); | ||
629 | + // std::cout << lanes[i][j] << " " << lanes[i][j+1] << " " << cats[i] << std::endl; | ||
630 | + } | ||
631 | + } | ||
632 | +#endif | ||
633 | + return mask_rmlane; | ||
880 | } | 634 | } |
881 | \ No newline at end of file | 635 | \ No newline at end of file |
src/ai_engine_module/RoadSegAnalysis.h
@@ -9,8 +9,7 @@ using namespace std; | @@ -9,8 +9,7 @@ using namespace std; | ||
9 | struct RoadInfo{ | 9 | struct RoadInfo{ |
10 | std::vector<LineInfo> vec_line; | 10 | std::vector<LineInfo> vec_line; |
11 | std::vector<SegInfo> vec_road; | 11 | std::vector<SegInfo> vec_road; |
12 | - | ||
13 | - cv::Mat direct_mask; | 12 | + std::vector<SegInfo> vec_direct; |
14 | }; | 13 | }; |
15 | 14 | ||
16 | class RoadSegAnalysis | 15 | class RoadSegAnalysis |
@@ -23,7 +22,7 @@ public: | @@ -23,7 +22,7 @@ public: | ||
23 | 22 | ||
24 | std::vector<RoadInfo> detect(vector<sy_img> vec_img); | 23 | std::vector<RoadInfo> detect(vector<sy_img> vec_img); |
25 | 24 | ||
26 | - int check_reverse_driving(cv::Mat direct_mask, sy_rect rc, int src_width, int src_height, int head_or_tail); | 25 | + int check_reverse_driving(std::vector<SegInfo>& vec_direct, sy_rect rc, int src_width, int src_height, int head_or_tail); |
27 | 26 | ||
28 | int check_cross_line(std::vector<LineInfo>& vec_line, sy_rect rc); | 27 | int check_cross_line(std::vector<LineInfo>& vec_line, sy_rect rc); |
29 | 28 | ||
@@ -32,11 +31,20 @@ public: | @@ -32,11 +31,20 @@ public: | ||
32 | private: | 31 | private: |
33 | int release(); | 32 | int release(); |
34 | 33 | ||
35 | - std::vector<SegInfo> parse_seg(rs_result one_result, sy_img src); | 34 | + RoadInfo parse_road(rs_result one_result, sy_img src); |
35 | + | ||
36 | + std::vector<SegInfo> parse_direct(rs_result one_result, sy_img src); | ||
37 | + | ||
38 | + // void post_direct(rs_result one_result, sy_img src); | ||
39 | + | ||
36 | 40 | ||
37 | - cv::Mat parse_direct(rs_result one_result, sy_img src); | 41 | + cv::Mat mask_to_rgb(cv::Mat img, cv::Mat mask); |
42 | + float contourArea(std::vector<cv::Point> contour, cv::Point2f& center); | ||
43 | + void lanes_process(const rs_lane* lanes, int lane_count, std::vector<std::pair<std::vector<cv::Point>, int>>& combined, float scale_w = 1.0, float scale_h = 1.0); | ||
44 | + cv::Mat imshow_lanes(cv::Mat img, const rs_lane* lanes, int lane_count); | ||
45 | + int Mask2LanePoints(const cv::Mat& pred, std::vector<std::vector<cv::Point>>&lanes, std::vector<int>& cats); | ||
46 | + cv::Mat seg_post_process(bool large_resolution, unsigned char *seg_array, std::vector<std::pair<std::vector<cv::Point>, int>> combined, std::vector<std::vector<cv::Point>> &poly_masks, std::vector<int> ®ion_classes, std::vector<std::vector<cv::Point>> &lanes, std::vector<int> &cats, std::map<double, int> &x_sort); | ||
38 | 47 | ||
39 | - void post_direct(rs_result one_result, sy_img src); | ||
40 | private: | 48 | private: |
41 | void* m_handle{nullptr}; | 49 | void* m_handle{nullptr}; |
42 | aclrtContext ctx{nullptr}; | 50 | aclrtContext ctx{nullptr}; |
src/village_inc.h
@@ -36,10 +36,11 @@ typedef struct VehicleInfo { | @@ -36,10 +36,11 @@ typedef struct VehicleInfo { | ||
36 | manned_result manned_res; | 36 | manned_result manned_res; |
37 | 37 | ||
38 | int type; | 38 | int type; |
39 | - | 39 | + |
40 | int vpt_type; | 40 | int vpt_type; |
41 | int rainshed; //是否安装雨棚, 0 有雨棚 1 无雨棚 | 41 | int rainshed; //是否安装雨棚, 0 有雨棚 1 无雨棚 |
42 | - int manned; | 42 | + int truck_manned; |
43 | + int motor_manned; | ||
43 | 44 | ||
44 | int human_upper_color; | 45 | int human_upper_color; |
45 | int human_lower_color; | 46 | int human_lower_color; |