diff --git a/.vscode/launch.json b/.vscode/launch.json
index 1741c5e..79ce621 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -8,7 +8,7 @@
{
"name": "(gdb) Launch", /* 配置名称,将会在启动配置的下拉菜单中显⽰ */
- "preLaunchTask": "build", /* 调试前执⾏ 'build'选项 */
+ // "preLaunchTask": "build", /* 调试前执⾏ 'build'选项 */
"type": "cppdbg", /* 配置类型,这⾥只能为cppdbg */
"request": "launch",/**/
"program": "${workspaceFolder}/run.o", /*选择要调试的⽂件路径*/
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 93af57b..a2df583 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -7,11 +7,11 @@
"command": "/usr/bin/g++", /* 这⾥填写你的编译器地址 */
"args": [
/* 类似与qt的Pro⽂件⾥开始的那⼏句 */
- "-Ofast",
- "-march=native",
- "-flto",
- "-frename-registers",
- "-std=c++11",// 静态链接
+ // "-Ofast",
+ // "-march=native",
+ // "-flto",
+ // "-frename-registers",
+ "-std=c++14",// 静态链接
"-static-libgcc",
"-lpthread",
@@ -31,6 +31,7 @@
"-I","${workspaceFolder}/module/RM_Buff/Target",
"-I","${workspaceFolder}/module/RM_Buff",
"-I","${workspaceFolder}/module/top_detect",
+ "-I","${workspaceFolder}/module/orc",
"-I","${workspaceFolder}/base",
"-I","/usr/local/include",
"-I","/usr/local/include/opencv4",
@@ -52,6 +53,7 @@
"${workspaceFolder}/module/RM_Buff/Target/Target.cpp",
"${workspaceFolder}/module/RM_Buff/RM_Buff.cpp",
"${workspaceFolder}/module/top_detect/top.cpp",
+ "${workspaceFolder}/module/orc/orc.cpp",
"${workspaceFolder}/base/connector.cpp",
"${workspaceFolder}/user/main.cpp",/* ${workspaceFolder}表⽰路径从当前项⽬⽂件夹开始 */
"-o", /* 编译输出⽂件的存放路径 */
diff --git a/base/connector.cpp b/base/connector.cpp
index 18a3fd4..3184cbd 100644
--- a/base/connector.cpp
+++ b/base/connector.cpp
@@ -5,6 +5,7 @@ Connector::Connector() {}
Connector::~Connector() {}
void Connector::run() {
+ model module_("mnist-8.onnx");
while (true) {
if (mv_capture_.isindustryimgInput()) {
src_img_ = mv_capture_.image();
@@ -40,7 +41,7 @@ void Connector::run() {
mv_capture_.cameraReleasebuff();
armor_.free_Memory();
// usleep(1);
- if (cv::waitKey(1) == 'q') {
+ if (cv::waitKey(0) == 'q') {
return;
}
}
diff --git a/base/connector.hpp b/base/connector.hpp
index f30c55d..ee405e4 100644
--- a/base/connector.hpp
+++ b/base/connector.hpp
@@ -6,19 +6,28 @@
#include "module/RM_Buff/RM_Buff.hpp"
#include "module/angle_solve/rm_solve_pnp.hpp"
#include "module/armor/rm_armor.hpp"
+
+
class Connector {
private:
cv::Mat src_img_;
- mv_camera::RM_VideoCapture mv_capture_ =
+
+ mv_camera::RM_VideoCapture mv_capture_ =//初始相机的结构体
mv_camera::RM_VideoCapture(mv_camera::CameraParam(
- 1, mv_camera::RESOLUTION_1280_X_800, mv_camera::EXPOSURE_600));
+ 1, mv_camera::RESOLUTION_1280_X_800, mv_camera::EXPOSURE_600));
+
armor::RM_ArmorDetector armor_ =
armor::RM_ArmorDetector("module/armor/armor_config.xml");
+
serial_port::SerialPort serial_ =
serial_port::SerialPort("devices/serial/serial_config.xml");
+
buff::RM_Buff buff_ = buff::RM_Buff("module/RM_Buff/Config/buff_config.xml");
+
cv::VideoCapture cap_ =
- cv::VideoCapture("/home/xx/下载/视频/效果图/camera_MaxBuff18.avi");
+ cv::VideoCapture("/home/sms/VIDEO/camera_MaxBuff15.avi");
+
+
public:
void run();
diff --git a/mnist-8.onnx b/mnist-8.onnx
new file mode 100644
index 0000000..fc1a3f7
Binary files /dev/null and b/mnist-8.onnx differ
diff --git a/module/armor/armor_config.xml b/module/armor/armor_config.xml
index a1d4f8f..2375ebf 100644
--- a/module/armor/armor_config.xml
+++ b/module/armor/armor_config.xml
@@ -64,6 +64,10 @@
30
255
+
+
+
+
diff --git a/module/armor/rm_armor.cpp b/module/armor/rm_armor.cpp
index 43254ef..cc0e191 100644
--- a/module/armor/rm_armor.cpp
+++ b/module/armor/rm_armor.cpp
@@ -26,7 +26,10 @@ RM_ArmorDetector::RM_ArmorDetector(std::string _armor_config) {
fs_armor["S_BLUE_MAX"] >> image_config_.s_blue_max;
fs_armor["V_BLUE_MIN"] >> image_config_.v_blue_min;
fs_armor["V_BLUE_MAX"] >> image_config_.v_blue_max;
+
+
}
+
fs_armor["LIGHT_DRAW"] >> light_config_.light_draw;
fs_armor["LIGHT_EDTI"] >> light_config_.light_edit;
fs_armor["LIGHT_RATIO_W_H_MIN"] >> light_config_.ratio_w_h_min;
@@ -57,6 +60,8 @@ RM_ArmorDetector::RM_ArmorDetector(std::string _armor_config) {
std::cout << "装甲板参数初始化成功" << std::endl;
std::cout << "💚💚💚💚💚💚💚💚💚💚💚💚" << std::endl;
+
+
}
/**
@@ -162,8 +167,9 @@ bool RM_ArmorDetector::find_Light() {
* @return false 无法得到装甲板
*/
serial_port::Write_Data RM_ArmorDetector::run_Armor(
- cv::Mat &_src_img, serial_port::Receive_Data _receive_data) {
+ cv::Mat &_src_img, serial_port::Receive_Data _receive_data ) {
//图像处理
+ frame = _src_img.clone();
run_Image(_src_img, _receive_data.my_color);
draw_img_ = _src_img;
if (find_Light()) {
@@ -180,6 +186,9 @@ serial_port::Write_Data RM_ArmorDetector::run_Armor(
if (armor_config_.armor_draw == 1 || light_config_.light_draw == 1 ||
armor_config_.armor_edit == 1 || light_config_.light_edit == 1) {
+ cv::putText(draw_img_,to_string( pnp_.returnDepth()),
+ cv::Point(50,100),cv::FONT_HERSHEY_SIMPLEX,1,
+ cv::Scalar(0,255,255),1,cv::LINE_AA);
imshow("armor_draw_img", draw_img_);
draw_img_ = cv::Mat::zeros(_src_img.size(), CV_8UC3);
}
@@ -191,6 +200,7 @@ serial_port::Write_Data RM_ArmorDetector::run_Armor(
}
if (armor_config_.armor_draw == 1 || light_config_.light_draw == 1 ||
armor_config_.armor_edit == 1 || light_config_.light_edit == 1) {
+
imshow("armor_draw_img", draw_img_);
draw_img_ = cv::Mat::zeros(_src_img.size(), CV_8UC3);
}
@@ -199,6 +209,79 @@ serial_port::Write_Data RM_ArmorDetector::run_Armor(
pnp_.returnYawAngle(), cv::Point(0, 0)),
pnp_.returnPitchAngle(), pnp_.returnDepth(), armor_.size(), 0);
}
+
+
+
+/*********number*********************/
+
+cv::Mat RM_ArmorDetector::Save_ROI(cv::Rect input_rect , cv::Mat img_input)
+{
+ cv::Point Point_t;int width_ ,height_;
+ Point_t.x = input_rect.x + 10;
+ Point_t.y = input_rect.y - 30;
+ width_ = input_rect.width -20;
+ height_ = input_rect.height +50;
+if(Point_t.x < 0)
+{
+ Point_t.x = 0 ;
+}
+if(Point_t.y < 0)
+{
+ Point_t.y = 0;
+}
+if(Point_t.x+width_ > img_input.cols)
+{
+ width_ = img_input.cols - abs(Point_t.x);
+}
+if(Point_t.y+height_ > img_input.rows)
+{
+ height_ = img_input.rows - abs(Point_t.y);
+}
+
+return img_input(cv::Rect(Point_t,cv::Size(width_,height_)));
+
+}
+
+
+bool RM_ArmorDetector::NumberOrc()
+{
+
+ cv::namedWindow("数字number");
+ cv::createTrackbar("h_min_num", "数字number",&OrcCtrl_.num_cfg_.h_min_num,
+ 255, NULL);
+ cv::createTrackbar("s_min_num", "数字number",
+ &OrcCtrl_.num_cfg_.s_min_num, 255, NULL);
+ cv::createTrackbar("v_min_num", "数字number",
+ &OrcCtrl_.num_cfg_.v_min_num, 255, NULL);
+
+ cv::createTrackbar("CONFIDENT", "数字number",
+ &OrcCtrl_.num_cfg_.Confident, 5000, NULL);//置信度
+ cv::createTrackbar("kernel_size", "数字number",
+ &OrcCtrl_.num_cfg_.kennerl_size, 10, NULL);//置信度
+
+ cv::Mat Number_img = Save_ROI(armor_data_.armor_rect.boundingRect(),frame);
+ int k =module_.inferring(Number_img,
+ 2*OrcCtrl_.num_cfg_.kennerl_size-1,
+ cv::Scalar(OrcCtrl_.num_cfg_.h_min_num,OrcCtrl_.num_cfg_.s_min_num,OrcCtrl_.num_cfg_.v_min_num),
+ cv::Scalar(255,255,255),OrcCtrl_.num_cfg_.Confident);
+ if(OrcCtrl_.num_cfg_.switch_number == 1)
+ {
+ putText( frame, to_string(k), cv::Point(100, 100), 5, 5.0 ,cv::Scalar(0,360,360),
+ 2, cv::LINE_8, false );
+ cv::imshow("frame_number",frame);
+ cv::imshow("number",Number_img);
+ }
+
+
+ if(k == 2)
+ {
+ return false;
+ }else{
+ return true;
+ }
+}
+
+/*********number*********************/
/**
* @brief 求两点之间的距离
*
@@ -323,7 +406,7 @@ bool RM_ArmorDetector::fitting_Armor() {
* @return true 找到了符合装甲板条件的位置
* @return false 没找到了符合装甲板条件的位置
*/
-bool RM_ArmorDetector::light_Judge(int i, int j) {
+bool RM_ArmorDetector::light_Judge(int i, int j ) {
armor_data_.left_light_height =
MAX(light_[i].size.height, light_[i].size.width);
armor_data_.left_light_width =
@@ -344,7 +427,8 @@ bool RM_ArmorDetector::light_Judge(int i, int j) {
armor_data_.light_width_aspect <
(armor_config_.light_width_ratio_max * 0.1) &&
armor_data_.light_width_aspect >
- (armor_config_.light_height_ratio_min * 0.1)) {
+ (armor_config_.light_height_ratio_min * 0.1))
+ {
armor_data_.height = (armor_data_.left_light.size.height +
armor_data_.right_light.size.height) /
2;
@@ -377,12 +461,31 @@ bool RM_ArmorDetector::light_Judge(int i, int j) {
(armor_config_.small_armor_aspect_min * 0.1) &&
(armor_data_.aspect_ratio < armor_config_.armor_type_th * 0.1)) {
armor_data_.distinguish = 0; // 小装甲板
- return true;
+
+
+ if(NumberOrc())
+ {
+ if(OrcCtrl_.num_cfg_.switch_number == 1)
+ {
+ cv::putText(draw_img_,"SMALL",cv::Point(50,50),cv::FONT_HERSHEY_SIMPLEX,2,
+ cv::Scalar(255,255,255),2,cv::LINE_AA);
+ }
+ return true;
+ }else
+ {
+ return false;
+ }
} else if (armor_data_.aspect_ratio >
(armor_config_.armor_type_th * 0.1) &&
armor_data_.aspect_ratio <
- (armor_config_.big_armor_aspect_max * 0.1)) {
- armor_data_.distinguish = 1; //大装甲板
+ (armor_config_.big_armor_aspect_max * 0.1)){
+ armor_data_.distinguish = 1; //大装甲板
+ NumberOrc();
+ if(OrcCtrl_.num_cfg_.switch_number == 1)
+ {
+ cv::putText(draw_img_,"BIG",cv::Point(50,50),cv::FONT_HERSHEY_SIMPLEX,2,
+ cv::Scalar(255,255,255),2,cv::LINE_AA);
+ }
return true;
}
}
diff --git a/module/armor/rm_armor.hpp b/module/armor/rm_armor.hpp
index 16a894f..ebbcee3 100644
--- a/module/armor/rm_armor.hpp
+++ b/module/armor/rm_armor.hpp
@@ -8,6 +8,9 @@
#include "module/angle_solve/rm_solve_pnp.hpp"
#include "module/filter/filter.hpp"
#include "module/top_detect/top.hpp"
+#include "module/orc/orc.hpp"
+#include "opencv_onnx_inferring.hpp"
+
namespace armor {
struct Armor_Data {
@@ -48,6 +51,7 @@ struct Armor_Cfg {
int small_armor_aspect_min;
int armor_type_th;
int big_armor_aspect_max;
+
};
struct Light_Cfg {
@@ -88,7 +92,12 @@ struct Image_Cfg {
int gray_edit = 0;
int color_edit = 0;
int method = 0;
+
+
+
};
+
+
/**
* @brief 图像处理
*
@@ -97,14 +106,23 @@ class RM_ArmorDetector {
//装甲板
public:
serial_port::Write_Data run_Armor(cv::Mat &_src_img,
- serial_port::Receive_Data _receive_data);
- bool light_Judge(int i, int j); //判断左右灯条能否组成装甲板
+ serial_port::Receive_Data _receive_data );
+ bool light_Judge(int i, int j ); //判断左右灯条能否组成装甲板
int average_Color(); //计算图像颜色平均值
bool fitting_Armor(); //拟合装甲板
bool find_Light(); //寻找灯条
void final_Armor(); //最优装甲板
void free_Memory(); //释放内存
- int motion_Direction(); //判断装甲板运动方向
+ int motion_Direction(); //判断装甲板运动方向
+
+/****************数字*************************/
+
+ bool NumberOrc();
+ cv::Mat Save_ROI( cv::Rect input_rect , cv::Mat img_input);
+
+/****************数字*************************/
+
+
inline Armor_Data returnFinalArmor(int _num) { return armor_[_num]; }
inline cv::Point returnFinalArmorCenter(int _num) {
return armor_[num].armor_rect.center;
@@ -136,6 +154,10 @@ class RM_ArmorDetector {
Image_Cfg image_config_;
Light_Cfg light_config_;
+
+ Orc::OrcNumber OrcCtrl_ = Orc::OrcNumber("module/orc/orc_config.xml");
+ model module_ = model("mnist-8.onnx");
+
cv::Mat frame; //原图
cv::Mat draw_img_; //画板
cv::Mat gray_img_;
@@ -173,6 +195,7 @@ class RM_ArmorDetector {
int armor_direction = 0; // 1向右 -1 向左
int num = 0; //运行次数
+
//图像
private:
cv::Mat gray_trackbar_ = cv::Mat::zeros(1, 300, CV_8UC1);
diff --git a/module/orc/orc.cpp b/module/orc/orc.cpp
new file mode 100644
index 0000000..ff38a73
--- /dev/null
+++ b/module/orc/orc.cpp
@@ -0,0 +1,25 @@
+#include "orc.hpp"
+
+namespace Orc
+{
+ OrcNumber::OrcNumber(){}
+
+ OrcNumber::OrcNumber(std::string Orc_config_)
+ {
+ cv::FileStorage Orc_armor(Orc_config_, cv::FileStorage::READ);
+ Orc_armor["H_MIN_NUM"] >> num_cfg_.h_min_num;
+ Orc_armor["H_MAX_NUM"] >> num_cfg_.h_max_num;
+ Orc_armor["S_MIN_NUM"] >> num_cfg_.s_min_num;
+ Orc_armor["S_MAX_NUM"] >> num_cfg_.s_max_num;
+ Orc_armor["V_MIN_NUM"] >> num_cfg_.v_min_num;
+ Orc_armor["V_MAX_NUM"] >> num_cfg_.v_max_num;
+ Orc_armor["CONFIDENT"] >> num_cfg_.Confident;
+ Orc_armor["KERNEL_SIZE"] >> num_cfg_.kennerl_size;
+
+ Orc_armor["NUMBER_SWITCH"] >> num_cfg_.switch_number;
+ }
+ OrcNumber::~OrcNumber(){}
+
+
+} // namespace Orc
+
diff --git a/module/orc/orc.hpp b/module/orc/orc.hpp
new file mode 100644
index 0000000..70579bc
--- /dev/null
+++ b/module/orc/orc.hpp
@@ -0,0 +1,53 @@
+
+#ifndef _USE_ORCNUMBER_
+#define _USE_ORCNUMBER_
+
+
+#include
+#include
+#include"opencv_onnx_inferring.hpp"
+
+
+namespace Orc
+{
+struct Number_Cfg {
+
+ int h_min_num;
+ int h_max_num;
+
+ int s_min_num ;
+ int s_max_num;
+
+ int v_min_num;
+ int v_max_num;
+
+ int Confident;
+ int kennerl_size ;
+
+ int switch_number;
+
+
+};
+
+ class OrcNumber
+ {
+ private:
+ /* data */
+ public:
+ OrcNumber();
+ OrcNumber(std::string Orc_config_);
+
+ ~OrcNumber();
+ Number_Cfg num_cfg_;
+
+ bool NumberOrc(model model);
+ };
+} // namespace Orc
+
+
+
+
+
+
+
+#endif
\ No newline at end of file
diff --git a/module/orc/orc_config.xml b/module/orc/orc_config.xml
new file mode 100644
index 0000000..18e2006
--- /dev/null
+++ b/module/orc/orc_config.xml
@@ -0,0 +1,24 @@
+
+
+
+
+5
+255
+4
+255
+2
+255
+
+666
+2
+
+
+1
+
+
diff --git a/opencv_onnx_inferring.hpp b/opencv_onnx_inferring.hpp
new file mode 100644
index 0000000..89d5526
--- /dev/null
+++ b/opencv_onnx_inferring.hpp
@@ -0,0 +1,132 @@
+/*
+ * @name: opencv_onnx_inferring.hpp
+ * @namespace: ooi
+ * @class: model
+ * @brief: Load ONNX model and infer input image for classified int digit
+ * @author Unbinilium
+ * @version 1.0.1
+ * @date 2021-05-10
+ */
+
+#ifndef _USE_NUMBER_
+#define _USE_NUMBER_
+
+#pragma once_
+#include
+using namespace std;
+
+#include
+
+
+class model {
+ public:
+ /**
+ @brief: Init model from params
+ @param: onnx_model_path, the path of the modle on your machine, downloadable at https://github.com/onnx/models/blob/master/vision/classification/mnist/model/mnist-8.onnx
+ @param: input_size, define the input layer size, default to cv::Size(28, 28)
+ */
+ inline model(const char* onnx_model_path, const cv::Size& input_size = cv::Size(28, 28)) {
+ model::load(onnx_model_path);
+ model::layers();
+
+ this->input_size = input_size;
+ }
+ model(){};
+ ~model(){};
+ /**
+ @brief: Inferring input image from loaded model, return classified int digit
+ @param: input, the image to classify (only 1 digit), const reference from cv::Mat
+ @param: median_blur_kernel_size, define the kernel size of median blur pre-processing, default to int 5, set 0 to disable
+ @param: hsv_lowerb, the lower range for hsv image, pixels inside the range equals to 1, otherwise equals to 0, default is the cv::Scalar() default
+ @param: hsv_upperb, the upper range for hsv image, pixels inside the range equals to 1, otherwise equals to 0, default is the cv::Scalar() default
+ @param: probability_threshold, the min probability of considerable probability to iterate, determined by the model, mnist-8.onnx has the output array from -1e5 to 1e5, default is 0
+ @return: max_probability_idx, the most probable digit classified from input image in int type, -1 means all the probability is out of the threahold
+ */
+ inline int inferring(const cv::Mat& hsv_input, const int median_blur_kernel_size = 5, const cv::Scalar& hsv_lowerb = cv::Scalar(), const cv::Scalar& hsv_upperb = cv::Scalar(), const float probability_threshold = 0) {
+ cv::resize(hsv_input, tmp, input_size);
+ if (median_blur_kernel_size != 0) {
+ cv::medianBlur(tmp, tmp, median_blur_kernel_size);
+ }
+
+ cv::inRange(tmp, hsv_lowerb, hsv_upperb, tmp);
+ //开运算
+ // cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(3,3));
+ // cv::morphologyEx(tmp, tmp, cv::MORPH_OPEN,element);
+ // cv::dilate(tmp,tmp,cv::Mat(cv::Size(3, 3), CV_8UC1));
+ // cv::bitwise_not(tmp, tmp);
+
+ cv::imshow("number_input_tmp", tmp);
+
+ opencv_net.setInput(cv::dnn::blobFromImage(tmp));
+
+ float max_probability { 0 };
+ int max_probability_idx { 0 };
+ int i { -1 };
+ opencv_net.forward().forEach([&probability_threshold, &max_probability, &max_probability_idx, &i](float &data, [[maybe_unused]] const int * position) -> void {
+ if (++i) {
+ if (data > max_probability) {
+ max_probability = data;
+ max_probability_idx = i;
+ }
+ } else {
+ if (data > probability_threshold) {
+ max_probability = data;
+ } else {
+ max_probability = probability_threshold;
+ max_probability_idx = -1;
+ }
+ }
+ });
+
+ return max_probability_idx;
+ }
+
+ protected:
+ /*
+ @brief: Load model from onnx_model_path
+ @param: onnx_model_path, the path of the modle on your machine, downloadable at https://github.com/onnx/models/blob/master/vision/classification/mnist/model/mnist-8.onnx
+ */
+ inline void load(const char* onnx_model_path) {
+ std::cout << "[OOI] opencv version: " << cv::getVersionString() << std::endl;
+
+ model_path = onnx_model_path;
+ opencv_net = cv::dnn::readNetFromONNX(model_path);
+
+ if (!opencv_net.empty()) {
+ std::cout << "[OOI] load model success: " << model_path << std::endl;
+ } else {
+ std::cout << "[OOI] load model failed: " << model_path << std::endl;
+ return;
+ }
+
+#if __has_include()
+ opencv_net.setPreferableBackend(cv::dnn::DNN_TARGET_CUDA);
+#else
+ opencv_net.setPreferableBackend(cv::dnn::DNN_TARGET_CPU);
+#endif
+ }
+ /*
+ @brief: Print model layers detail from loaded model
+ */
+ inline void layers(void) {
+ if (opencv_net.empty()) {
+ std::cout << "[OOI] model is empty" << std::endl;
+ return;
+ }
+
+ std::cout << "[OOI] model from " << model_path << " has layers: " << std::endl;
+ for (const auto& layer_name : opencv_net.getLayerNames()) {
+ std::cout << "\t\t" << layer_name << std::endl;
+ }
+ }
+
+ private:
+ cv::dnn::Net opencv_net;
+ const char* model_path;
+
+ cv::Size input_size;
+ cv::Mat tmp;
+ };
+
+
+#endif
diff --git a/run.o b/run.o
index f5b5b3f..9ba2685 100755
Binary files a/run.o and b/run.o differ