diff --git a/.gitignore b/.gitignore index 6447d85..0a74973 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ cmake-build-debug build .idea +.xmake +.vscode/.cache +.vscode/compile_commands.json Mark armor_box_photo tools/TrainCNN/.idea @@ -9,4 +12,4 @@ tools/TrainCNN/__pycache__ others/include/config/config.h others/MV-UB31-Group0.config .DS_Store -video \ No newline at end of file +video diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4ee1895 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "clangd.arguments": [ + "--compile-commands-dir=${workspaceFolder}/.vscode", + "--completion-style=detailed", + "--query-driver=/usr/bin/g++,/usr/bin/gcc,/usr/bin/c++", + "--header-insertion=never" + ], +} \ No newline at end of file diff --git a/armor/include/armor_finder/armor_finder.h b/armor/include/armor_finder/armor_finder.h index 9dc6a8a..f00eca0 100644 --- a/armor/include/armor_finder/armor_finder.h +++ b/armor/include/armor_finder/armor_finder.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/armor/src/armor_finder/armor_finder.cpp b/armor/src/armor_finder/armor_finder.cpp index de28f5c..96fd655 100644 --- a/armor/src/armor_finder/armor_finder.cpp +++ b/armor/src/armor_finder/armor_finder.cpp @@ -67,7 +67,7 @@ void ArmorFinder::run(cv::Mat &src) { if ((target_box.rect & cv::Rect2d(0, 0, 640, 480)) == target_box.rect) { // 判断装甲板区域是否脱离图像区域 if (!classifier) { /* 如果分类器不可用 */ cv::Mat roi = src(target_box.rect).clone(), roi_gray; /* 就使用装甲区域亮点数判断是否跟丢 */ - cv::cvtColor(roi, roi_gray, CV_RGB2GRAY); + cv::cvtColor(roi, roi_gray, cv::COLOR_RGB2GRAY); cv::threshold(roi_gray, roi_gray, 180, 255, cv::THRESH_BINARY); contour_area = cv::countNonZero(roi_gray); } diff --git a/armor/src/armor_finder/find/find_light_blobs.cpp b/armor/src/armor_finder/find/find_light_blobs.cpp index ad47222..1dad251 100644 --- a/armor/src/armor_finder/find/find_light_blobs.cpp +++ b/armor/src/armor_finder/find/find_light_blobs.cpp @@ -83,11 +83,11 @@ bool ArmorFinder::findLightBlobs(const cv::Mat &src, LightBlobs &light_blobs) { }else{ light_threshold = 200; } - cv::threshold(color_channel, src_bin_light, light_threshold, 255, CV_THRESH_BINARY); // 二值化对应通道 + cv::threshold(color_channel, src_bin_light, light_threshold, 255, cv::THRESH_BINARY); // 二值化对应通道 if (src_bin_light.empty()) return false; imagePreProcess(src_bin_light); // 开闭运算 - cv::threshold(color_channel, src_bin_dim, 140, 255, CV_THRESH_BINARY); // 二值化对应通道 + cv::threshold(color_channel, src_bin_dim, 140, 255, cv::THRESH_BINARY); // 二值化对应通道 if (src_bin_dim.empty()) return false; imagePreProcess(src_bin_dim); // 开闭运算 @@ -100,8 +100,8 @@ bool ArmorFinder::findLightBlobs(const cv::Mat &src, LightBlobs &light_blobs) { std::vector> light_contours_light, light_contours_dim; LightBlobs light_blobs_light, light_blobs_dim; std::vector hierarchy_light, hierarchy_dim; - cv::findContours(src_bin_light, light_contours_light, hierarchy_light, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE); - cv::findContours(src_bin_dim, light_contours_dim, hierarchy_dim, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE); + cv::findContours(src_bin_light, light_contours_light, hierarchy_light, cv::RETR_CCOMP, cv::CHAIN_APPROX_NONE); + cv::findContours(src_bin_dim, light_contours_dim, hierarchy_dim, cv::RETR_CCOMP, cv::CHAIN_APPROX_NONE); for (int i = 0; i < light_contours_light.size(); i++) { if (hierarchy_light[i][2] == -1) { cv::RotatedRect rect = cv::minAreaRect(light_contours_light[i]); diff --git a/armor/src/armor_finder/tracking_state/tracking_state.cpp b/armor/src/armor_finder/tracking_state/tracking_state.cpp index e736b99..213ab11 100644 --- a/armor/src/armor_finder/tracking_state/tracking_state.cpp +++ b/armor/src/armor_finder/tracking_state/tracking_state.cpp @@ -8,13 +8,13 @@ #include bool ArmorFinder::stateTrackingTarget(cv::Mat &src) { - auto pos = target_box.rect; + cv::Rect pos(target_box.rect); if(!tracker->update(src, pos)){ // 使用KCFTracker进行追踪 target_box = ArmorBox(); LOGW("Track fail!"); return false; } - if((pos & cv::Rect2d(0, 0, 640, 480)) != pos){ + if((cv::Rect2d(pos) & cv::Rect2d(0, 0, 640, 480)) != cv::Rect2d(pos)){ target_box = ArmorBox(); LOGW("Track out range!"); return false; @@ -52,7 +52,7 @@ bool ArmorFinder::stateTrackingTarget(cv::Mat &src) { } }else{ // 分类器不可用,使用常规方法判断 cv::Mat roi_gray; - cv::cvtColor(roi, roi_gray, CV_RGB2GRAY); + cv::cvtColor(roi, roi_gray, cv::COLOR_RGB2GRAY); cv::threshold(roi_gray, roi_gray, 180, 255, cv::THRESH_BINARY); contour_area = cv::countNonZero(roi_gray); if(abs(cv::countNonZero(roi_gray) - contour_area) > contour_area * 0.3){ diff --git a/energy/src/energy/find/energy_finder.cpp b/energy/src/energy/find/energy_finder.cpp index 3a8f963..b8387e3 100644 --- a/energy/src/energy/find/energy_finder.cpp +++ b/energy/src/energy/find/energy_finder.cpp @@ -21,12 +21,12 @@ int Energy::findFans(const cv::Mat &src) { static Mat src_bin; src_bin = src.clone(); if (src.type() == CV_8UC3) { - cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 + cvtColor(src_bin, src_bin, cv::COLOR_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 } std::vector > fan_contours; FanStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找 if (show_process)imshow("fan struct", src_bin); - findContours(src_bin, fan_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); + findContours(src_bin, fan_contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); for (auto &fan_contour : fan_contours) { if (!isValidFanContour(src_bin, fan_contour)) { @@ -54,16 +54,16 @@ int Energy::findArmors(const cv::Mat &src) { static Mat src_bin; src_bin = src.clone(); if (src.type() == CV_8UC3) { - cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 + cvtColor(src_bin, src_bin, cv::COLOR_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 } std::vector > armor_contours; std::vector > armor_contours_external;//用总轮廓减去外轮廓,只保留内轮廓,除去流动条的影响。 ArmorStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找 - findContours(src_bin, armor_contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); + findContours(src_bin, armor_contours, cv::RETR_LIST, cv::CHAIN_APPROX_NONE); if (show_process)imshow("armor struct", src_bin); - findContours(src_bin, armor_contours_external, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); + findContours(src_bin, armor_contours_external, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); for (int i = 0; i < armor_contours_external.size(); i++)//去除外轮廓 { unsigned long external_contour_size = armor_contours_external[i].size(); @@ -103,12 +103,12 @@ bool Energy::findCenterR(const cv::Mat &src) { static Mat src_bin; src_bin = src.clone(); if (src.type() == CV_8UC3) { - cvtColor(src_bin, src_bin, CV_BGR2GRAY); + cvtColor(src_bin, src_bin, cv::COLOR_BGR2GRAY); } std::vector > center_R_contours; CenterRStruct(src_bin); if (show_process)imshow("R struct", src_bin); - findContours(src_bin, center_R_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); + findContours(src_bin, center_R_contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); for (auto ¢er_R_contour : center_R_contours) { if (!isValidCenterRContour(center_R_contour)) { continue; @@ -139,13 +139,13 @@ bool Energy::findFlowStripFan(const cv::Mat &src) { src_bin = src.clone(); src_copy = src.clone(); if (src.type() == CV_8UC3) { - cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 + cvtColor(src_bin, src_bin, cv::COLOR_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 } std::vector > flow_strip_fan_contours; FlowStripFanStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找 if (show_process)imshow("flow strip fan struct", src_bin); - findContours(src_bin, flow_strip_fan_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); + findContours(src_bin, flow_strip_fan_contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); std::vector candidate_flow_strip_fans; for (auto &flow_strip_fan_contour : flow_strip_fan_contours) { @@ -175,7 +175,7 @@ bool Energy::findFlowStrip(const cv::Mat &src) { if (src_bin.type() == CV_8UC1) // 黑白图像 { - cvtColor(src_bin, src_bin, COLOR_GRAY2RGB); + cvtColor(src_bin, src_bin, cv::COLOR_GRAY2RGB); } std::vector candidate_target_armors = target_armors; @@ -189,13 +189,13 @@ bool Energy::findFlowStrip(const cv::Mat &src) { } } - cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 + cvtColor(src_bin, src_bin, cv::COLOR_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 FlowStripStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找 if (show_process)imshow("flow strip struct", src_bin); std::vector > flow_strip_contours; - findContours(src_bin, flow_strip_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); + findContours(src_bin, flow_strip_contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); for (auto candidate_flow_strip_fan: flow_strip_fans) { for (auto &flow_strip_contour : flow_strip_contours) { @@ -261,7 +261,7 @@ bool Energy::findFlowStripWeak(const cv::Mat &src) { if (src_bin.type() == CV_8UC1) // 黑白图像 { - cvtColor(src_bin, src_bin, COLOR_GRAY2RGB); + cvtColor(src_bin, src_bin, cv::COLOR_GRAY2RGB); } std::vector candidate_armors = armors; @@ -275,13 +275,13 @@ bool Energy::findFlowStripWeak(const cv::Mat &src) { } } - cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 + cvtColor(src_bin, src_bin, cv::COLOR_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 FlowStripStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找 if (show_process)imshow("weak struct", src_bin); std::vector > flow_strip_contours; - findContours(src_bin, flow_strip_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); + findContours(src_bin, flow_strip_contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); for (auto &flow_strip_contour : flow_strip_contours) { if (!isValidFlowStripContour(flow_strip_contour)) { @@ -335,6 +335,4 @@ bool Energy::findCenterROI(const cv::Mat &src) { Size2f(length * 1.7, length * 1.7), -90); return true; -} - - +} \ No newline at end of file diff --git a/others/include/camera/camera_wrapper.h b/others/include/camera/camera_wrapper.h index 2236d55..3fe58dc 100644 --- a/others/include/camera/camera_wrapper.h +++ b/others/include/camera/camera_wrapper.h @@ -6,7 +6,7 @@ #define _CAMERA_WRAPPER_H_ #include -#include +#include #include #ifdef Windows @@ -33,7 +33,7 @@ private: tSdkCameraCapbility tCapability; tSdkFrameHead frame_info; BYTE *pby_buffer; - IplImage* iplImage; + cv::Mat image_header; int channel; RoundQueue src_queue; @@ -52,4 +52,4 @@ public: }; -#endif /* _CAMERA_WRAPPER_H_ */ +#endif /* _CAMERA_WRAPPER_H_ */ \ No newline at end of file diff --git a/others/include/log.h b/others/include/log.h index 39b6ba4..8d32ae7 100644 --- a/others/include/log.h +++ b/others/include/log.h @@ -32,6 +32,7 @@ #include #include +#include /************** Define the control code *************/ #define START_CTR "\033[0" diff --git a/others/src/camera/camera_wrapper.cpp b/others/src/camera/camera_wrapper.cpp index 16ba19e..6c19fe5 100644 --- a/others/src/camera/camera_wrapper.cpp +++ b/others/src/camera/camera_wrapper.cpp @@ -17,7 +17,6 @@ CameraWrapper::CameraWrapper(int exposure, int gain, int camera_mode, const std: mode(camera_mode), camera_cnts(2), camera_status(-1), - iplImage(nullptr), rgb_buffer(nullptr), channel(3), gain(gain), @@ -27,9 +26,11 @@ CameraWrapper::CameraWrapper(int exposure, int gain, int camera_mode, const std: void cameraCallback(CameraHandle hCamera, BYTE *pFrameBuffer, tSdkFrameHead* pFrameHead,PVOID pContext){ CameraWrapper *c = (CameraWrapper*)pContext; CameraImageProcess(hCamera, pFrameBuffer, c->rgb_buffer, pFrameHead); - auto iplImage = cvCreateImageHeader(cvSize(pFrameHead->iWidth, pFrameHead->iHeight), IPL_DEPTH_8U, c->channel); - cvSetData(iplImage, c->rgb_buffer, pFrameHead->iWidth * c->channel); //此处只是设置指针,无图像块数据拷贝,不需担心转换效率 - c->src_queue.push(cv::cvarrToMat(iplImage).clone()); + // 使用 cv::Mat 替代 IplImage + cv::Mat img(pFrameHead->iHeight, pFrameHead->iWidth, + c->channel == 3 ? CV_8UC3 : CV_8UC1, + c->rgb_buffer, pFrameHead->iWidth * c->channel); + c->src_queue.push(img.clone()); } bool CameraWrapper::init() { @@ -134,15 +135,9 @@ bool CameraWrapper::read(cv::Mat &src) { bool CameraWrapper::readRaw(cv::Mat &src) { if (CameraGetImageBuffer(h_camera, &frame_info, &pby_buffer, 500) == CAMERA_STATUS_SUCCESS) { - if (iplImage) { - cvReleaseImageHeader(&iplImage); - } - - iplImage = cvCreateImageHeader(cvSize(frame_info.iWidth, frame_info.iHeight), IPL_DEPTH_8U, 1); - - cvSetData(iplImage, pby_buffer, frame_info.iWidth); //此处只是设置指针,无图像块数据拷贝,不需担心转换效率 - - src = cv::cvarrToMat(iplImage).clone(); + // 使用 cv::Mat 替代 IplImage + cv::Mat img(frame_info.iHeight, frame_info.iWidth, CV_8UC1, pby_buffer, frame_info.iWidth); + src = img.clone(); //在成功调用CameraGetImageBuffer后,必须调用CameraReleaseImageBuffer来释放获得的buffer。 //否则再次调用CameraGetImageBuffer时,程序将被挂起一直阻塞,直到其他线程中调用CameraReleaseImageBuffer来释放了buffer @@ -156,16 +151,13 @@ bool CameraWrapper::readRaw(cv::Mat &src) { } bool CameraWrapper::readProcessed(cv::Mat &src) { -// cerr << "Get-1" << endl; if (CameraGetImageBuffer(h_camera, &frame_info, &pby_buffer, 500) == CAMERA_STATUS_SUCCESS) { CameraImageProcess(h_camera, pby_buffer, rgb_buffer, &frame_info); // this function is super slow, better not to use it. - if (iplImage) { - cvReleaseImageHeader(&iplImage); - } - iplImage = cvCreateImageHeader(cvSize(frame_info.iWidth, frame_info.iHeight), IPL_DEPTH_8U, channel); - cvSetData(iplImage, rgb_buffer, frame_info.iWidth * channel); //此处只是设置指针,无图像块数据拷贝,不需担心转换效率 - src = cv::cvarrToMat(iplImage).clone(); + // 使用 cv::Mat 替代 IplImage + int mat_type = (channel == 3) ? CV_8UC3 : CV_8UC1; + cv::Mat img(frame_info.iHeight, frame_info.iWidth, mat_type, rgb_buffer, frame_info.iWidth * channel); + src = img.clone(); //在成功调用CameraGetImageBuffer后,必须调用CameraReleaseImageBuffer来释放获得的buffer。 //否则再次调用CameraGetImageBuffer时,程序将被挂起一直阻塞,直到其他线程中调用CameraReleaseImageBuffer来释放了buffer CameraReleaseImageBuffer(h_camera, pby_buffer); @@ -193,4 +185,4 @@ CameraWrapper::~CameraWrapper() { //注意,先反初始化后再free if (rgb_buffer != nullptr) free(rgb_buffer); -} +} \ No newline at end of file diff --git a/others/src/options.cpp b/others/src/options.cpp index be2652a..cde8ada 100644 --- a/others/src/options.cpp +++ b/others/src/options.cpp @@ -6,12 +6,13 @@ #include #include #include +#include -bool show_armor_box = false; +bool show_armor_box = true; bool show_armor_boxes = false; bool show_light_blobs = false; bool show_origin = false; -bool run_with_camera = false; +bool run_with_camera = true; bool save_video = false; bool wait_uart = false; bool save_labelled_boxes = false; diff --git a/tools/tty-permission.sh b/tools/tty-permission.sh new file mode 100644 index 0000000..82f3653 --- /dev/null +++ b/tools/tty-permission.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +sudo touch /etc/udev/rules.d/70-ttyusb.rules diff --git a/xmake.lua b/xmake.lua new file mode 100644 index 0000000..a636b13 --- /dev/null +++ b/xmake.lua @@ -0,0 +1,122 @@ +-- 设置项目信息 +set_project("SJTU-RM-CV") +set_version("1.0.0") +set_languages("c++17") + +-- 设置构建模式 +set_rules("mode.release") +set_optimize("fastest") + +--导出构建指令 +add_rules("plugin.compile_commands.autoupdate", {outputdir = ".vscode"}) + +-- 定义宏 +add_defines('PATH=\"$(projectdir)\"') +add_defines("Linux") + +-- 检查是否存在 config.h +if os.isfile("others/include/config/config.h") or os.isfile("others/include/config.h") then + add_defines("WITH_CONFIG") + print("Found config.h") +end + +-- 添加依赖 +add_requires("eigen", {system = false}) +add_requires("pthread") + +--- OpenCV 4.6.0 配置(启用 ffmpeg 和 contrib) +add_requires("opencv", { + system = false, + configs = { + ffmpeg = false, + eigen = true, + png = true, + jpeg = true, + webp = false, + tiff = false, + quirc = false, + opengl = false, + protobuf = false, + bundled = true, + gtk = true + } +}) + +-- 目标配置 +target("run") + set_kind("binary") + + -- 添加源文件 + add_files("main.cpp") + add_files("others/src/*.cpp") + add_files("others/src/camera/*.cpp") + add_files("energy/src/energy/*.cpp") + add_files("energy/src/energy/*/*.cpp") + add_files("armor/src/armor_finder/*.cpp") + add_files("armor/src/armor_finder/*/*.cpp") + add_files("armor/src/show_images/*.cpp") + + -- 添加头文件搜索路径 + add_includedirs("others/include") + add_includedirs("others/include/camera") + add_includedirs("others/include/config") + add_includedirs("energy/include") + add_includedirs("energy/include/energy") + add_includedirs("armor/include") + add_includedirs("armor/include/armor_finder") + add_includedirs("armor/include/armor_finder/classifier") + add_includedirs("armor/include/show_images") + + -- 添加依赖包 + add_packages("pthread", "eigen", "opencv") + + -- 添加链接目录 + add_linkdirs("others") + + -- 根据平台链接相机 SDK + if is_plat("linux") then + add_links("MVSDK") + print("current platform: Linux") + elseif is_plat("windows") then + add_links("MVCAMSDK_X64") + print("current platform: Windows") + elseif is_plat("macosx") then + add_links("mvsdk") + print("current platform: Mac") + else + print("Unsupported platform") + end + + -- 设置目标目录 + set_targetdir("$(builddir)") + + -- 添加编译选项 + add_cxxflags("-O3") + +-- 自定义任务:create-startup +task("create-startup") + set_category("action") + on_run(function () + os.exec("$(projectdir)/tools/create-startup.sh $(projectdir) $(builddir)") + end) + set_menu { + usage = "xmake create-startup", + description = "Create startup script", + options = {} + } + +-- 自定义任务:train-cnn +task("train-cnn") + set_category("action") + on_run(function () + if os.host() == "linux" then + os.exec("gnome-terminal -- bash -c \"$(projectdir)/tools/TrainCNN/backward.py\"") + else + print("train-cnn only supported on Linux with gnome-terminal") + end + end) + set_menu { + usage = "xmake train-cnn", + description = "Train CNN model", + options = {} + } \ No newline at end of file