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 | 452 | jobject vehicle_pendant_det_res_vpd_res_syRect_rect = env->NewObject(cls_SyRect, mid_SyRect, one_pendant_res.rect.left_, |
453 | 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 | 457 | env->SetObjectArrayElement(vehiclePendantDetInfoArray, m, vehiclePendantDetInfo); |
458 | 458 | } |
... | ... | @@ -530,7 +530,18 @@ JNIEXPORT jint JNICALL Java_com_objecteye_nativeinterface_vehicle_VehicleNativeI |
530 | 530 | } |
531 | 531 | |
532 | 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 | 546 | env->SetObjectArrayElement(vehicleInfoArray, j, vehicleInfo); |
536 | 547 | } |
... | ... | @@ -566,12 +577,12 @@ JNIEXPORT void JNICALL Java_com_objecteye_nativeinterface_vehicle_VehicleNativeI |
566 | 577 | |
567 | 578 | /* |
568 | 579 | * Class: com_objecteye_nativeinterface_vehicle_VehicleNativeInterface |
569 | - * Method: va_get_version | |
580 | + * Method: get_village_pic_version | |
570 | 581 | * Signature: ()Ljava/lang/String; |
571 | 582 | */ |
572 | 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 | 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 | 222 | |
223 | 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 | 250 | // 车尾,判断是否 货车尾部货厢载人 |
251 | 251 | if(result_info.vpt_type == 6 || result_info.vpt_type == 7){ |
252 | 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 | 256 | } else { |
257 | 257 | if(result_info.vpt_type == 1 || result_info.vpt_type == 2 || result_info.vpt_type == 3){ |
258 | 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 | 329 | } |
330 | 330 | |
331 | 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 | 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 | 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 | 6 | RoadSegAnalysis::RoadSegAnalysis(/* args */) |
519 | 7 | { |
520 | 8 | } |
... | ... | @@ -573,34 +61,91 @@ std::vector<RoadInfo> RoadSegAnalysis::detect(vector<sy_img> vec_img){ |
573 | 61 | |
574 | 62 | for (int b = 0; b < batchsize; b++) { |
575 | 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 | 151 | return vec_road; |
... | ... | @@ -622,95 +167,81 @@ int RoadSegAnalysis::release() { |
622 | 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 | 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 | 245 | if (direct == 1 && head_or_tail == 0) { |
715 | 246 | // 来车道,车头,正常行驶 |
716 | 247 | return 0; |
... | ... | @@ -728,7 +259,16 @@ int RoadSegAnalysis::check_reverse_driving(cv::Mat direct_mask, sy_rect rc, int |
728 | 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 | 273 | std::vector<cv::Point> polygon_pts; |
734 | 274 | cv::Point pt_lt; |
... | ... | @@ -816,7 +356,123 @@ int RoadSegAnalysis::check_cross_region(std::vector<SegInfo>& vec_reg, sy_rect r |
816 | 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 | 476 | float scale_w = img.cols / 640.0; |
821 | 477 | float scale_h = img.rows / 360.0; |
822 | 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 | 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 | 635 | \ No newline at end of file | ... | ... |
src/ai_engine_module/RoadSegAnalysis.h
... | ... | @@ -9,8 +9,7 @@ using namespace std; |
9 | 9 | struct RoadInfo{ |
10 | 10 | std::vector<LineInfo> vec_line; |
11 | 11 | std::vector<SegInfo> vec_road; |
12 | - | |
13 | - cv::Mat direct_mask; | |
12 | + std::vector<SegInfo> vec_direct; | |
14 | 13 | }; |
15 | 14 | |
16 | 15 | class RoadSegAnalysis |
... | ... | @@ -23,7 +22,7 @@ public: |
23 | 22 | |
24 | 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 | 27 | int check_cross_line(std::vector<LineInfo>& vec_line, sy_rect rc); |
29 | 28 | |
... | ... | @@ -32,11 +31,20 @@ public: |
32 | 31 | private: |
33 | 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 | 48 | private: |
41 | 49 | void* m_handle{nullptr}; |
42 | 50 | aclrtContext ctx{nullptr}; | ... | ... |
src/village_inc.h
... | ... | @@ -36,10 +36,11 @@ typedef struct VehicleInfo { |
36 | 36 | manned_result manned_res; |
37 | 37 | |
38 | 38 | int type; |
39 | - | |
39 | + | |
40 | 40 | int vpt_type; |
41 | 41 | int rainshed; //是否安装雨棚, 0 有雨棚 1 无雨棚 |
42 | - int manned; | |
42 | + int truck_manned; | |
43 | + int motor_manned; | |
43 | 44 | |
44 | 45 | int human_upper_color; |
45 | 46 | int human_lower_color; | ... | ... |