Commit 81e8a40597cb70ae5126f68891f3bddd9f864355
1 parent
d26b9f64
初步完成SDK
Showing
11 changed files
with
857 additions
and
52 deletions
algorithm/proj_tz_road_seg_231018/linux/Makefile
100755 → 100644
1 | 1 | CC = gcc |
2 | 2 | XX = c++ |
3 | 3 | |
4 | -TARGET = libroad_seg_vdec.so | |
5 | 4 | |
6 | -PROJ_ALL_PATH = $(PWD)/../.. | |
7 | -CUR_PROJ_PATH = $(PWD)/.. | |
5 | + | |
6 | +PROJ_ALL_PATH = /home/cmhu/village_ascend_arm/village_ascend_arm | |
7 | +CUR_PROJ_PATH = $(PROJ_ALL_PATH)/src | |
8 | +BIN_PATH = $(PROJ_ALL_PATH)/bin | |
9 | + | |
10 | +DEFS=-DOS_LINUX -DENABLE_DVPP_INTERFACE | |
11 | + | |
12 | +TARGET = $(BIN_PATH)/test_road_seg | |
13 | + | |
8 | 14 | ACL_PATH = $(ASCEND_AICPU_PATH)/acllib |
15 | +OPENCV_PATH = $(PROJ_ALL_PATH)/3rdparty/opencv_4_1 | |
16 | +SPDLOG_ROOT = $(PROJ_ALL_PATH)/3rdparty/spdlog-1.9.2/release | |
17 | +ALGORITHM_PATH = $(PROJ_ALL_PATH)/algorithm | |
9 | 18 | |
10 | -INCLUDES = -I$(PROJ_ALL_PATH)/common \ | |
11 | - -I$(PROJ_ALL_PATH)/common/dvppx \ | |
12 | - -I$(PROJ_ALL_PATH)/common/road_cnn \ | |
13 | - -I$(CUR_PROJ_PATH)/src \ | |
19 | +INCLUDES = -I$(PROJ_ALL_PATH)/src/common \ | |
20 | + -I$(PROJ_ALL_PATH)/src/common/dvpp \ | |
21 | + -I$(PROJ_ALL_PATH)/src/common/cnn \ | |
22 | + -I$(PROJ_ALL_PATH)/src/common/cnn_cls \ | |
23 | + -I$(PROJ_ALL_PATH)/src/common/road_cnn \ | |
24 | + -I$(PROJ_ALL_PATH)/src/common/dvppx \ | |
25 | + -I$(PROJ_ALL_PATH)/src/common/model_process \ | |
26 | + -I$(CUR_PROJ_PATH)/../va \ | |
27 | + -I$(OPENCV_PATH)/include \ | |
28 | + -I$(OPENCV_PATH)/include/opencv2 \ | |
14 | 29 | -I$(ACL_PATH)/include \ |
30 | + -I$(SPDLOG_ROOT)/include \ | |
31 | + -I$(CUR_PROJ_PATH)/ai_engine_module \ | |
32 | + -I$(ALGORITHM_PATH)/vehicle_analysis \ | |
33 | + -I$(ALGORITHM_PATH)/vid_clothes2/vid_clothes \ | |
34 | + -I$(ALGORITHM_PATH)/hp2/hp \ | |
35 | + -I$(ALGORITHM_PATH)/hcp2/hcp \ | |
36 | + | |
15 | 37 | |
16 | -CFLAGS = -O2 -std=c++11 -fPIC -shared $(INCLUDES) -DENABLE_DVPP_INTERFACE -D_GLIBCXX_USE_CXX11_ABI=0 | |
38 | +# CXXFLAGS = -O0 -std=c++11 $(INCLUDES) -DENABLE_DVPP_INTERFACE -D_GLIBCXX_USE_CXX11_ABI=0 | |
39 | +# CXXFLAGS= -g -O0 -fPIC $(INCLUDES) -lpthread -lrt -lz -fexceptions -std=c++11 -DENABLE_DVPP_INTERFACE -D_GLIBCXX_USE_CXX11_ABI=0 -fvisibility=hidden -Wall -Wno-deprecated -Wdeprecated-declarations -Wl,-Bsymbolic -ldl | |
17 | 40 | |
18 | 41 | local_shared_libs_dirs := \ |
42 | + $(OPENCV_PATH)/lib \ | |
43 | + $(SPDLOG_ROOT)/lib/aarch64-linux-gnu \ | |
19 | 44 | $(ACL_PATH)/lib64 \ |
20 | - $(PROJ_ALL_PATH)/common \ | |
45 | + $(BIN_PATH)/ | |
21 | 46 | |
22 | 47 | local_shared_libs := \ |
48 | + opencv_world \ | |
23 | 49 | ascendcl \ |
24 | 50 | acl_dvpp \ |
25 | - sycheck \ | |
51 | + vehicle_analysis \ | |
52 | + vid_clothes \ | |
53 | + hp \ | |
54 | + hcp \ | |
26 | 55 | |
56 | + | |
27 | 57 | SHARED_LIBRARIES := $(foreach shared_lib, $(local_shared_libs), -l$(shared_lib)) |
28 | -SHARED_LIBRARIES_DIRS := $(foreach shared_lib_dir, $(local_shared_libs_dirs), -L$(shared_lib_dir) -Wl,-z,relro,-z,now,-z,noexecstack,-rpath-link,$(shared_lib_dir)) | |
58 | +#SHARED_LIBRARIES_DIRS := $(foreach shared_lib_dir, $(local_shared_libs_dirs), -L$(shared_lib_dir) -Wl,-z,relro,-z,now,-z,noexecstack,-rpath-link,$(shared_lib_dir)) | |
59 | +SHARED_LIBRARIES_DIRS := $(foreach shared_lib_dir, $(local_shared_libs_dirs), -L$(shared_lib_dir) -Wl,-z,relro,-z,now,-z,noexecstack,-rpath,$(shared_lib_dir)) | |
60 | + | |
61 | +CXXFLAGS= -g -O0 -fPIC $(INCLUDES) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -DENABLE_DVPP_INTERFACE -D_GLIBCXX_USE_CXX11_ABI=0 -fvisibility=hidden -Wall -Wno-deprecated -Wdeprecated-declarations -Wl,-Bsymbolic -ldl | |
62 | +CFLAGS = -O2 -std=c++11 $(INCLUDES) -DENABLE_DVPP_INTERFACE -D_GLIBCXX_USE_CXX11_ABI=0 | |
29 | 63 | |
30 | -SRCS := $(wildcard $(CUR_PROJ_PATH)/src/*.cpp) | |
31 | -SRCS += $(wildcard $(PROJ_ALL_PATH)/common/*.cpp) | |
32 | -SRCS += $(wildcard $(PROJ_ALL_PATH)/common/road_cnn/*.cpp) | |
33 | -SRCS += $(wildcard $(PROJ_ALL_PATH)/common/dvppx/*.cpp) | |
64 | +SRCS := $(wildcard /home/cmhu/village_ascend_arm/village_ascend_arm/algorithm/proj_tz_road_seg_231018/src/test/*.cpp) \ | |
65 | + $(wildcard $(CUR_PROJ_PATH)/common/*.cpp) \ | |
66 | + $(wildcard $(CUR_PROJ_PATH)/common/road_cnn/*.cpp) \ | |
67 | + $(wildcard $(CUR_PROJ_PATH)/common/dvppx/*.cpp) \ | |
68 | + $(wildcard /home/cmhu/village_ascend_arm/village_ascend_arm/algorithm/proj_tz_road_seg_231018/src/*.cpp) \ | |
34 | 69 | |
35 | 70 | DIRS := $(notdir $(SRCS)) |
36 | 71 | OBJS := $(patsubst %cpp, %o, $(DIRS)) |
... | ... | @@ -38,16 +73,26 @@ OBJS := $(patsubst %cpp, %o, $(DIRS)) |
38 | 73 | all: $(TARGET) |
39 | 74 | |
40 | 75 | $(TARGET):$(OBJS) |
41 | - $(XX) $(CFLAGS) -o $@ $^ $(SHARED_LIBRARIES_DIRS) $(SHARED_LIBRARIES) | |
42 | -%.o:$(CUR_PROJ_PATH)/src/%.cpp | |
43 | - $(XX) $(CFLAGS) -c $< | |
44 | -%.o:$(PROJ_ALL_PATH)/common/%.cpp | |
45 | - $(XX) $(CFLAGS) -c $< | |
46 | -%.o:$(PROJ_ALL_PATH)/common/road_cnn/%.cpp | |
47 | - $(XX) $(CFLAGS) -c $< | |
48 | -%.o:$(PROJ_ALL_PATH)/common/dvppx/%.cpp | |
49 | - $(XX) $(CFLAGS) -c $< | |
76 | + $(XX) -o $@ $^ $(CXXFLAGS) $(SHARED_LIBRARIES_DIRS) $(SHARED_LIBRARIES) | |
77 | + | |
78 | +%.o:/home/cmhu/village_ascend_arm/village_ascend_arm/algorithm/proj_tz_road_seg_231018/src/test/%.cpp | |
79 | + $(XX) $(CXXFLAGS) -c $< | |
80 | + | |
81 | +%.o:$(CUR_PROJ_PATH)/common/%.cpp | |
82 | + $(XX) $(CXXFLAGS) -c $< | |
83 | + | |
84 | +%.o:$(CUR_PROJ_PATH)/common/road_cnn/%.cpp | |
85 | + $(XX) $(CXXFLAGS) -c $< | |
86 | + | |
87 | +%.o:$(CUR_PROJ_PATH)/common/dvppx/%.cpp | |
88 | + $(XX) $(CXXFLAGS) -c $< | |
89 | + | |
90 | +%.o:/home/cmhu/village_ascend_arm/village_ascend_arm/algorithm/proj_tz_road_seg_231018/src/%.cpp | |
91 | + $(XX) $(CXXFLAGS) -c $< | |
50 | 92 | |
51 | 93 | clean: |
52 | 94 | @rm -f $(TARGET) |
53 | 95 | @rm -f $(OBJS) |
96 | + | |
97 | +cleano: | |
98 | + @rm -f $(OBJS) | |
54 | 99 | \ No newline at end of file | ... | ... |
algorithm/proj_tz_road_seg_231018/src/road_seg.cpp
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | #include <time.h> |
6 | 6 | #include <sys/time.h> |
7 | 7 | #include "stream_data.h" |
8 | -#include "sycheck.h" | |
8 | +// #include "sycheck.h" | |
9 | 9 | #include <algorithm> |
10 | 10 | #include <map> |
11 | 11 | #include <cstring> |
... | ... | @@ -38,9 +38,9 @@ typedef struct Tools { |
38 | 38 | |
39 | 39 | int rs_init(void **handle, rs_param param){ |
40 | 40 | |
41 | - if (!sycheck()) { | |
42 | - return SY_VERSION_EXPIRED; | |
43 | - } | |
41 | + // if (!sycheck()) { | |
42 | + // return SY_VERSION_EXPIRED; | |
43 | + // } | |
44 | 44 | int ret = SY_SUCCESS; |
45 | 45 | Tools* tools = new Tools; |
46 | 46 | // init resource | ... | ... |
algorithm/proj_tz_road_seg_231018/src/test/test.cpp
... | ... | @@ -606,7 +606,7 @@ int main() { |
606 | 606 | rs_param param; |
607 | 607 | // param.modelNames = "tzroad_seg_310p.om"; |
608 | 608 | // param.modelNames = "tzroad_seg1027_310p.om"; |
609 | - param.modelNames = "tzroad_seg240108_310p.om"; | |
609 | + param.modelNames = "./models/road_seg/tzroad_seg240108_310p.om"; | |
610 | 610 | param.thresld = 0.25; |
611 | 611 | param.devId = 0; |
612 | 612 | |
... | ... | @@ -625,7 +625,7 @@ int main() { |
625 | 625 | cout << "init success " << endl; |
626 | 626 | |
627 | 627 | // const char* img_file_path="imgs/"; |
628 | - const char* img_file_path="test_img/"; | |
628 | + const char* img_file_path="img/"; | |
629 | 629 | std::vector<std::string> fileList; |
630 | 630 | |
631 | 631 | getAllNm(img_file_path,fileList); |
... | ... | @@ -697,9 +697,12 @@ int main() { |
697 | 697 | cv::addWeighted(cvImg, alpha, overlayed_img, 1 - alpha, 0, overlayed_img); |
698 | 698 | cv::Mat img_lane = imshow_lanes(overlayed_img, results[b].reg_array, results[b].lane_count); |
699 | 699 | |
700 | - string strpath = "results/" + file; | |
700 | + string strpath = "res/results/" + file; | |
701 | 701 | cv::imwrite(strpath, img_lane); |
702 | 702 | |
703 | + | |
704 | + | |
705 | + | |
703 | 706 | cv::Mat overlayed_direct_img(cv::Size(w,h), CV_8UC3, cv::Scalar(0, 0, 0)); |
704 | 707 | // 将车道线标签转换为彩色图像 |
705 | 708 | for (int i = 0; i < h; ++i) { |
... | ... | @@ -714,7 +717,7 @@ int main() { |
714 | 717 | // 将原始图像和彩色车道线图进行混合 |
715 | 718 | cv::addWeighted(cvImg, alpha, overlayed_direct_img, 1 - alpha, 0, overlayed_direct_img); |
716 | 719 | cv::Mat img_direct_lane = imshow_lanes(overlayed_direct_img, results[b].reg_array, results[b].lane_count); |
717 | - strpath = "results_direct/" + file; | |
720 | + strpath = "res/results_direct/" + file; | |
718 | 721 | cv::imwrite(strpath, img_direct_lane); |
719 | 722 | #endif |
720 | 723 | |
... | ... | @@ -736,13 +739,13 @@ int main() { |
736 | 739 | cv::Mat vis_image = mask_to_rgb(image, seg_output); |
737 | 740 | cv::Mat direct_image = mask_to_rgb(image, direct_output); |
738 | 741 | cv::Mat merge_image = mask_to_rgb(image, merge_output); |
739 | - strpath = "lane_cpp/" + file; | |
742 | + strpath = "res/lane_cpp/" + file; | |
740 | 743 | cv::imwrite(strpath, vis_image); |
741 | - strpath = "direct_img/" + file; | |
744 | + strpath = "res/direct_img/" + file; | |
742 | 745 | cv::imwrite(strpath, direct_image); |
743 | - strpath = "merge_img/" + file; | |
746 | + strpath = "res/merge_img/" + file; | |
744 | 747 | cv::imwrite(strpath, merge_image); |
745 | - strpath = "background_mask/" + file; | |
748 | + strpath = "res/background_mask/" + file; | |
746 | 749 | cv::imwrite(strpath, background_mask); |
747 | 750 | #endif |
748 | 751 | //debug===================================== |
... | ... | @@ -820,7 +823,7 @@ int main() { |
820 | 823 | } |
821 | 824 | } |
822 | 825 | } |
823 | - strpath = "reg_cpp/" + file; | |
826 | + strpath = "res/reg_cpp/" + file; | |
824 | 827 | cv::imwrite(strpath, vis_image); |
825 | 828 | //debug end================================= |
826 | 829 | ... | ... |
build/demo/Makefile
src/PicAnalysis.cpp
... | ... | @@ -187,8 +187,10 @@ vector<AnalysisResult> PicAnalysis::analysis_img(vector<sy_img> vec_img){ |
187 | 187 | m_vehicle_analysis.release_result(result, vec_img.size()); |
188 | 188 | } |
189 | 189 | |
190 | + bool bConsistent = false; | |
190 | 191 | std::vector<RoadInfo> vec_road = m_road_seg_algorithm.detect(vec_img); |
191 | 192 | if (vec_road.size() == batch_size && vec_result.size() == batch_size) { |
193 | + bConsistent = true; | |
192 | 194 | for (size_t i = 0; i < batch_size; i++) { |
193 | 195 | vec_result[i].vec_line = vec_road[i].vec_line; |
194 | 196 | vec_result[i].vec_road = vec_road[i].vec_road; |
... | ... | @@ -199,6 +201,11 @@ vector<AnalysisResult> PicAnalysis::analysis_img(vector<sy_img> vec_img){ |
199 | 201 | { |
200 | 202 | vector<VehicleInfo>& vec_info = vec_result[b].info; |
201 | 203 | |
204 | + RoadInfo road_info; | |
205 | + if (bConsistent) { | |
206 | + road_info = vec_road[b]; | |
207 | + } | |
208 | + | |
202 | 209 | sy_img img = vec_img[b]; |
203 | 210 | |
204 | 211 | ImageData src; |
... | ... | @@ -213,11 +220,16 @@ vector<AnalysisResult> PicAnalysis::analysis_img(vector<sy_img> vec_img){ |
213 | 220 | VehicleInfo& result_info = vec_info[c]; |
214 | 221 | int shot_type=result_info.type; |
215 | 222 | |
223 | + sy_rect vehicle_rect = result_info.vehicle_body_detect_res.rect; | |
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); | |
227 | + } | |
228 | + | |
216 | 229 | // 行人 |
217 | 230 | if (6 == shot_type) |
218 | 231 | { |
219 | - sy_rect human_rect = result_info.vehicle_body_detect_res.rect; | |
220 | - ImageData* human_data = m_crop_util.crop(src, human_rect.left_, human_rect.top_, human_rect.left_ + human_rect.width_, human_rect.top_ + human_rect.height_); | |
232 | + ImageData* human_data = m_crop_util.crop(src, vehicle_rect.left_, vehicle_rect.top_, vehicle_rect.left_ + vehicle_rect.width_, vehicle_rect.top_ + vehicle_rect.height_); | |
221 | 233 | |
222 | 234 | sy_img img; |
223 | 235 | img.w_ = human_data->alignWidth; |
... | ... | @@ -294,8 +306,7 @@ vector<AnalysisResult> PicAnalysis::analysis_img(vector<sy_img> vec_img){ |
294 | 306 | // analysis_result.motor_helmeted = result_info.mta_res.motor_driver_helmeted.status; |
295 | 307 | // float score=result_info.mta_res.motor_driver_helmeted.confidence; |
296 | 308 | |
297 | - sy_rect motor_rect = result_info.vehicle_body_detect_res.rect; | |
298 | - ImageData* motor_data = m_crop_util.crop(src, motor_rect.left_, motor_rect.top_, motor_rect.left_ + motor_rect.width_, motor_rect.top_ + motor_rect.height_); | |
309 | + ImageData* motor_data = m_crop_util.crop(src, vehicle_rect.left_, vehicle_rect.top_, vehicle_rect.left_ + vehicle_rect.width_, vehicle_rect.top_ + vehicle_rect.height_); | |
299 | 310 | |
300 | 311 | sy_img img; |
301 | 312 | img.w_ = motor_data->alignWidth; |
... | ... | @@ -314,12 +325,24 @@ vector<AnalysisResult> PicAnalysis::analysis_img(vector<sy_img> vec_img){ |
314 | 325 | vector<int> vec_phone_result = m_motor_phone_algorithm.detect(vec_motor_img); |
315 | 326 | if (vec_phone_result.size() > 0) |
316 | 327 | { |
317 | - int phoning = vec_phone_result[0]; | |
328 | + result_info.phoning = vec_phone_result[0]; | |
329 | + } | |
330 | + | |
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]); | |
335 | + } | |
318 | 336 | } |
319 | 337 | |
320 | 338 | delete motor_data; |
321 | 339 | motor_data = nullptr; |
322 | 340 | } |
341 | + | |
342 | + //压黄实线 | |
343 | + result_info.cross_line = m_road_seg_algorithm.check_cross_line(road_info.vec_line, vehicle_rect); | |
344 | + // 压导流线 | |
345 | + result_info.cross_diversion_line = m_road_seg_algorithm.check_cross_region(road_info.vec_road, vehicle_rect, 3); //3是导流线区域 | |
323 | 346 | } |
324 | 347 | } |
325 | 348 | ... | ... |
src/ai_engine_module/HumanCarAnalysis.cpp
... | ... | @@ -28,9 +28,9 @@ int HumanCarAnalysis::init(int devId){ |
28 | 28 | return SY_SUCCESS; |
29 | 29 | } |
30 | 30 | |
31 | -int HumanCarAnalysis::detect(vector<sy_img> vec_img){ | |
31 | +std::vector<HumanCarResult> HumanCarAnalysis::detect(vector<sy_img> vec_img){ | |
32 | 32 | |
33 | - ACL_CALL(aclrtSetCurrentContext(ctx), SY_SUCCESS, SY_FAILED); | |
33 | + std::vector<HumanCarResult> vec_result; | |
34 | 34 | |
35 | 35 | const int batchsize = vec_img.size(); |
36 | 36 | hcp_analysis_result * results = new hcp_analysis_result[batchsize]; |
... | ... | @@ -39,6 +39,12 @@ int HumanCarAnalysis::detect(vector<sy_img> vec_img){ |
39 | 39 | |
40 | 40 | do |
41 | 41 | { |
42 | + ret = aclrtSetCurrentContext(ctx); | |
43 | + if (SY_SUCCESS != ret) { | |
44 | + printf("aclrtSetCurrentContext failed!"); | |
45 | + break; | |
46 | + } | |
47 | + | |
42 | 48 | ret = hcp_batch(m_handle, vec_img.data(), batchsize, results); |
43 | 49 | if (SY_SUCCESS != ret) { |
44 | 50 | printf("hcp_batch failed!"); |
... | ... | @@ -47,7 +53,10 @@ int HumanCarAnalysis::detect(vector<sy_img> vec_img){ |
47 | 53 | |
48 | 54 | for(int batchIdx = 0;batchIdx<batchsize;batchIdx++){ |
49 | 55 | for (int i = 0; i < HCP_ATTRI_INDEX_SIZE; i++) { |
50 | - printf("hcp index:%d,confidence:%f\n",results[batchIdx].res_objs[i].res_index,results[batchIdx].res_objs[i].res_prob); | |
56 | + HumanCarResult one_result; | |
57 | + one_result.type = results[batchIdx].res_objs[i].res_index; | |
58 | + one_result.prob = results[batchIdx].res_objs[i].res_prob; | |
59 | + vec_result.push_back(one_result); | |
51 | 60 | } |
52 | 61 | } |
53 | 62 | } while (0); |
... | ... | @@ -56,7 +65,7 @@ int HumanCarAnalysis::detect(vector<sy_img> vec_img){ |
56 | 65 | delete [] results; |
57 | 66 | } |
58 | 67 | |
59 | - return ret; | |
68 | + return vec_result; | |
60 | 69 | } |
61 | 70 | |
62 | 71 | int HumanCarAnalysis::release() { | ... | ... |
src/ai_engine_module/HumanCarAnalysis.h
1 | 1 | #include "include.h" |
2 | 2 | #include "human_car_parsing.h" |
3 | 3 | |
4 | +struct HumanCarResult { | |
5 | + int type; | |
6 | + float prob; | |
7 | +}; | |
8 | + | |
4 | 9 | class HumanCarAnalysis |
5 | 10 | { |
6 | 11 | public: |
... | ... | @@ -9,7 +14,7 @@ public: |
9 | 14 | |
10 | 15 | int init(int devId); |
11 | 16 | |
12 | - int detect(vector<sy_img> vec_img); | |
17 | + std::vector<HumanCarResult> detect(vector<sy_img> vec_img); | |
13 | 18 | |
14 | 19 | private: |
15 | 20 | int release(); | ... | ... |
src/ai_engine_module/RoadSegAnalysis.cpp
... | ... | @@ -32,6 +32,489 @@ void lanes_process(const rs_lane* lanes, int lane_count, std::vector<std::pair<s |
32 | 32 | } |
33 | 33 | } |
34 | 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 | + | |
35 | 518 | RoadSegAnalysis::RoadSegAnalysis(/* args */) |
36 | 519 | { |
37 | 520 | } |
... | ... | @@ -104,6 +587,9 @@ std::vector<RoadInfo> RoadSegAnalysis::detect(vector<sy_img> vec_img){ |
104 | 587 | } |
105 | 588 | |
106 | 589 | one_road.vec_road = parse_seg(one_result, vec_img[b]); |
590 | + one_road.direct_mask = parse_direct(one_result, vec_img[b]); | |
591 | + | |
592 | + post_direct(one_result, vec_img[b]); | |
107 | 593 | |
108 | 594 | vec_road.push_back(one_road); |
109 | 595 | } |
... | ... | @@ -167,7 +653,7 @@ std::vector<SegInfo> RoadSegAnalysis::parse_seg(rs_result one_result, sy_img src |
167 | 653 | SegInfo info; |
168 | 654 | info.seg_type = cls; |
169 | 655 | // cv::Scalar color(lane_colors[cls][0],lane_colors[cls][1],lane_colors[cls][2]); |
170 | - for (size_t i = 1; i < xys.size(); ++i) { | |
656 | + for (size_t i = 0; i < xys.size(); ++i) { | |
171 | 657 | // cv::line(overlayed_img, xys[i - 1], xys[i], color, 4); |
172 | 658 | sy_point pt; |
173 | 659 | pt.x_ = xys[i].x; |
... | ... | @@ -178,4 +664,217 @@ std::vector<SegInfo> RoadSegAnalysis::parse_seg(rs_result one_result, sy_img src |
178 | 664 | } |
179 | 665 | |
180 | 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); | |
695 | + | |
696 | + return direct_output; | |
697 | +} | |
698 | + | |
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); | |
704 | + | |
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 | |
713 | + int direct = direct_mask.at<int>(center_x, center_y); | |
714 | + if (direct == 1 && head_or_tail == 0) { | |
715 | + // 来车道,车头,正常行驶 | |
716 | + return 0; | |
717 | + } else if (direct == 1 && head_or_tail == 1){ | |
718 | + // 来车道,车尾,逆行 | |
719 | + return 1; | |
720 | + } else if (direct == 2 && head_or_tail == 0){ | |
721 | + // 去车道,车头,逆行 | |
722 | + return 1; | |
723 | + } else if (direct == 2 && head_or_tail == 1){ | |
724 | + // 去车道,车尾,正常行驶 | |
725 | + return 0; | |
726 | + } | |
727 | + | |
728 | + return -1; | |
729 | +} | |
730 | + | |
731 | +int RoadSegAnalysis::check_cross_line(std::vector<LineInfo>& vec_line, sy_rect rc) { | |
732 | + | |
733 | + std::vector<cv::Point> polygon_pts; | |
734 | + cv::Point pt_lt; | |
735 | + pt_lt.x = rc.left_; | |
736 | + pt_lt.y = rc.top_; | |
737 | + polygon_pts.push_back(pt_lt); | |
738 | + cv::Point pt_rt; | |
739 | + pt_rt.x = rc.left_ + rc.width_; | |
740 | + pt_rt.y = rc.top_; | |
741 | + polygon_pts.push_back(pt_rt); | |
742 | + cv::Point pt_rb; | |
743 | + pt_rb.x = rc.left_ + rc.width_; | |
744 | + pt_rb.y = rc.top_ + rc.height_; | |
745 | + polygon_pts.push_back(pt_rb); | |
746 | + cv::Point pt_lb; | |
747 | + pt_lb.x = rc.left_; | |
748 | + pt_lb.y = rc.top_ + rc.height_; | |
749 | + polygon_pts.push_back(pt_lb); | |
750 | + | |
751 | + | |
752 | + for (size_t i = 0; i < vec_line.size(); i++) { | |
753 | + LineInfo& line = vec_line[i]; | |
754 | + if (line.line_type == 1 || line.line_type == 2) { | |
755 | + // 黄实线 | |
756 | + int in_count = 0; | |
757 | + std::vector<cv::Point> vec_pt; | |
758 | + for (size_t j = 0; j < line.vec_pt.size(); j++) { | |
759 | + double dist = pointPolygonTest(polygon_pts, cv::Point2f(line.vec_pt[j].x_, line.vec_pt[j].y_), false); | |
760 | + if (dist > 0) { | |
761 | + in_count ++; | |
762 | + } | |
763 | + } | |
764 | + | |
765 | + if (in_count > 5) | |
766 | + {//有5个点就认为是压线了 | |
767 | + return line.line_type; | |
768 | + } | |
769 | + } | |
770 | + } | |
771 | + | |
772 | + return -1; | |
773 | +} | |
774 | + | |
775 | +int RoadSegAnalysis::check_cross_region(std::vector<SegInfo>& vec_reg, sy_rect rc, int region_type) { | |
776 | + | |
777 | + std::vector<cv::Point> polygon_pts; | |
778 | + cv::Point pt_lt; | |
779 | + pt_lt.x = rc.left_; | |
780 | + pt_lt.y = rc.top_; | |
781 | + polygon_pts.push_back(pt_lt); | |
782 | + cv::Point pt_rt; | |
783 | + pt_rt.x = rc.left_ + rc.width_; | |
784 | + pt_rt.y = rc.top_; | |
785 | + polygon_pts.push_back(pt_rt); | |
786 | + cv::Point pt_rb; | |
787 | + pt_rb.x = rc.left_ + rc.width_; | |
788 | + pt_rb.y = rc.top_ + rc.height_; | |
789 | + polygon_pts.push_back(pt_rb); | |
790 | + cv::Point pt_lb; | |
791 | + pt_lb.x = rc.left_; | |
792 | + pt_lb.y = rc.top_ + rc.height_; | |
793 | + polygon_pts.push_back(pt_lb); | |
794 | + | |
795 | + | |
796 | + for (size_t i = 0; i < vec_reg.size(); i++) { | |
797 | + SegInfo& seg = vec_reg[i]; | |
798 | + if (seg.seg_type == region_type) { | |
799 | + // 黄实线 | |
800 | + int in_count = 0; | |
801 | + std::vector<cv::Point> vec_pt; | |
802 | + for (size_t j = 0; j < seg.vec_pt.size(); j++) { | |
803 | + double dist = pointPolygonTest(polygon_pts, cv::Point2f(seg.vec_pt[j].x_, seg.vec_pt[j].y_), false); | |
804 | + if (dist > 0) { | |
805 | + in_count ++; | |
806 | + } | |
807 | + } | |
808 | + | |
809 | + if (in_count > 5) | |
810 | + {//有5个点就认为是压线了 | |
811 | + return 1; | |
812 | + } | |
813 | + } | |
814 | + } | |
815 | + | |
816 | + return -1; | |
817 | +} | |
818 | + | |
819 | +cv::Mat imshow_lanes(cv::Mat img, const rs_lane* lanes, int lane_count) { | |
820 | + float scale_w = img.cols / 640.0; | |
821 | + float scale_h = img.rows / 360.0; | |
822 | + std::vector<std::pair<std::vector<cv::Point>, int>> combined; | |
823 | + lanes_process(lanes, lane_count, combined, scale_w, scale_h); | |
824 | + | |
825 | + for (const auto& lane_info : combined) { | |
826 | + const auto& xys = lane_info.first; | |
827 | + int cls = lane_info.second; | |
828 | + cv::Scalar color(lane_colors[cls][0],lane_colors[cls][1],lane_colors[cls][2]); | |
829 | + for (size_t i = 1; i < xys.size(); ++i) { | |
830 | + cv::line(img, xys[i - 1], xys[i], color, 4); | |
831 | + } | |
832 | + } | |
833 | + | |
834 | + return img; | |
835 | +} | |
836 | + | |
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通道 | |
851 | + } | |
852 | + } | |
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 | + | |
859 | + | |
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); | |
181 | 880 | } |
182 | 881 | \ No newline at end of file | ... | ... |
src/ai_engine_module/RoadSegAnalysis.h
... | ... | @@ -9,6 +9,8 @@ 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 | 14 | }; |
13 | 15 | |
14 | 16 | class RoadSegAnalysis |
... | ... | @@ -21,11 +23,20 @@ public: |
21 | 23 | |
22 | 24 | std::vector<RoadInfo> detect(vector<sy_img> vec_img); |
23 | 25 | |
26 | + int check_reverse_driving(cv::Mat direct_mask, sy_rect rc, int src_width, int src_height, int head_or_tail); | |
27 | + | |
28 | + int check_cross_line(std::vector<LineInfo>& vec_line, sy_rect rc); | |
29 | + | |
30 | + int check_cross_region(std::vector<SegInfo>& vec_reg, sy_rect rc, int region_type); | |
31 | + | |
24 | 32 | private: |
25 | 33 | int release(); |
26 | 34 | |
27 | 35 | std::vector<SegInfo> parse_seg(rs_result one_result, sy_img src); |
28 | 36 | |
37 | + cv::Mat parse_direct(rs_result one_result, sy_img src); | |
38 | + | |
39 | + void post_direct(rs_result one_result, sy_img src); | |
29 | 40 | private: |
30 | 41 | void* m_handle{nullptr}; |
31 | 42 | aclrtContext ctx{nullptr}; | ... | ... |
src/demo/main.cpp
... | ... | @@ -11,9 +11,12 @@ int main() { |
11 | 11 | pic_analysis.init(param); |
12 | 12 | |
13 | 13 | vector<string> vec_path; |
14 | - for (size_t i = 0; i < 1; i++) | |
14 | + size_t i = 1; | |
15 | + // for (i = 1; i < 8; i++) | |
15 | 16 | { |
16 | - vec_path.push_back("./img/test_road1.jpg"); | |
17 | + string path = "./img/test_phone"; | |
18 | + path = path + to_string(i) + ".jpg"; | |
19 | + vec_path.push_back(path); | |
17 | 20 | } |
18 | 21 | |
19 | 22 | pic_analysis.analysis_file(vec_path); | ... | ... |
src/village_inc.h
... | ... | @@ -35,7 +35,8 @@ typedef struct VehicleInfo { |
35 | 35 | |
36 | 36 | manned_result manned_res; |
37 | 37 | |
38 | - int type; | |
38 | + int type; | |
39 | + | |
39 | 40 | int vpt_type; |
40 | 41 | int rainshed; //是否安装雨棚, 0 有雨棚 1 无雨棚 |
41 | 42 | int manned; |
... | ... | @@ -43,6 +44,12 @@ typedef struct VehicleInfo { |
43 | 44 | int human_upper_color; |
44 | 45 | int human_lower_color; |
45 | 46 | |
47 | + int reverse_driving; // 0 正常行驶 1 逆行 -1 未知 | |
48 | + int phoning; // 骑车打电话 | |
49 | + | |
50 | + int cross_line; // 压实线, 1 黄实线 2 白实线 -1 其他 | |
51 | + int cross_diversion_line; // 压导流线 1 压了 -1 未压 | |
52 | + | |
46 | 53 | } VehicleInfo; |
47 | 54 | |
48 | 55 | struct LineInfo{ | ... | ... |