赞
踩
在终端中输入以下命令
- sudo apt-get update //更新包列表
- sudo apt-get install build-essential //安装构建必需工具
- sudo apt-get install wget //安装wget
官网:https://docs.conda.io/en/latest/miniconda.html
或者
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
然后给文件添加运行权限
chmod +x Miniconda3-latest-Linux-x86_64.sh
./Miniconda3-latest-Linux-x86_64.sh
照着提示按步骤安装,过程中可以修改安装路径
sudo vim ~/.bashrc //打开.bashrc文件
在文件末尾处添加
export PATH="/home/你的用户名/miniconda/bin:$PATH" //这个是默认路径下的
保存退出后,使配置生效
source ~/.bashrc
可以添加清华的conda源来使用
- conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
- conda config --set show_channel_urls yes
- conda create -n yolov5 python=3.8 //创建名为yolov5且python版本3.8的虚拟环境
- conda activate yolov5 //用来激活环境的
-
- 在该环境下可以使用conda install来安装包
官网:https://github.com/ultralytics/yolov5
点击全部发行版,选择自己需要的yolov5版本的源代码和预训练权重文件下载
把预训练模型放入yolov5文件夹后,打开requirements.txt。
- #onnx>=1.9.0 # ONNX export
- #onnx-simplifier>=0.4.1 # ONNX simplifier
将这两行开头的的#号去掉,保存,然后在之前创建的conda环境中执行
pip install -r requirements.txt
python export.py --weights yolov5m6.pt --include onnx --imgsz 640 640
我用一个json文件存放模型的对应参数信息,调用时将从文件里读取存入到一个封装的struct结构体里。
- struct Net5_config
- {
- std::vector<float> CONFIDENCE_THRESHOLD; // 置信度
- std::vector<float> NMS_THRESHOLD; // nms阙值
- std::vector<float> SCORE_THRESHOLD; //得分阙值
- std::vector<int> INPUT_WIDTH; // 输入图像的宽度
- std::vector<int> INPUT_HEIGHT; // 输入图像的长度
- std::vector<std::string> classesFile; //coco.name等物品分类名称文件路径
- std::vector<std::string> modelWeights; //模型权重文件路径
- std::vector<std::string> netname; //模型权重文件名称
- int id = 0; //用于判断当前使用哪个模型
- };
然后又写了一个类来实现调用
- class Recognizerv5
- {
- public:
-
- Recognizerv5(Net5_config config); //yolo初始化配置
-
- bool IdentifyTarget(cv::Mat &frame, Result &output); //yolo模型推理
-
- bool drawRect(cv::Mat &frame, Result &output); //将识别结果画出来
-
- private:
-
- float confThreshold; //置信度阙值
- float nmsThreshold; //nms阙值
- float SCORE_THRESHOLD; //得分阙值
- int inpWidth; //图片输入宽度
- int inpHeight; //图片输入高度
- char netname[20]; //使用的模型的名字
- std::vector<std::string> classes; //物品类别目录
- cv::dnn::Net net; //用于模型推理
- };
-
- //存放识别的定位信息
- struct Result
- {
- std::vector<int> x;
- std::vector<int> y;
- std::vector<int> width;
- std::vector<int> height;
- std::vector<std::string> name;
- };
-
- //清空定位信息
- void Result_clear(struct Result &p)
- {
- p.name.clear();
- p.x.clear();
- p.y.clear();
- p.height.clear();
- p.width.clear();
- }
-
- //用于存放识别出来的物品框的信息
- struct Detection
- {
- int class_id; //物品类别下标
- float confidence; //置信度
- cv::Rect box; //方框信息
- };
-
- //用于复制图像
- cv::Mat format_yolov5(const cv::Mat &source)
- {
- int col = source.cols;
- int row = source.rows;
- int _max = MAX(col, row);
- cv::Mat result = cv::Mat::zeros(_max, _max, CV_8UC3);
- source.copyTo(result(cv::Rect(0, 0, col, row)));
- return result;
- }
-
- //yolo初始化配置
- Recognizerv5::Recognizerv5(Net5_config config)
- {
- //将数据从struct结构体里传入class里
- std::cout << "Net use " << config.netname[config.id] << std::endl;
- this->confThreshold = config.CONFIDENCE_THRESHOLD[config.id];
- this->nmsThreshold = config.NMS_THRESHOLD[config.id];
- this->inpWidth = config.INPUT_WIDTH[config.id];
- this->inpHeight = config.INPUT_HEIGHT[config.id];
- this->SCORE_THRESHOLD = config.SCORE_THRESHOLD[config.id];
- strcpy(this->netname, config.netname[config.id].c_str());
- std::ifstream ifs(config.classesFile[config.id].c_str());
- std::string line;
- while (getline(ifs, line))
- this->classes.push_back(line);
- //使用opencv的dnn模块读取模型文件
- auto result = cv::dnn::readNet(config.modelWeights[config.id]);
- //设置运行方式
- std::cout << "Running on CPU\n";
- result.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
- result.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
- //将读取结果存入net
- this->net = result;
- }
-
- //yolo模型推理
- bool Recognizerv5::IdentifyTarget(cv::Mat &frame, Result &output)
- {
- std::vector<Detection> p;
- cv::Mat blob;
- auto input_image = format_yolov5(frame);
- //为推理模型设置参数
- cv::dnn::blobFromImage(input_image, blob, 1. / 255., cv::Size(this->inpWidth, this->inpHeight), cv::Scalar(), true, false);
- this->net.setInput(blob);
- //网络推理
- std::vector<cv::Mat> outputs;
- this->net.forward(outputs, net.getUnconnectedOutLayersNames());
-
- float x_factor = input_image.cols / this->inpWidth;
- float y_factor = input_image.rows / this->inpHeight;
-
- float *data = (float *)outputs[0].data;
-
- const int dimensions = 85;
- const int rows = 25200;
-
- std::vector<int> class_ids;
- std::vector<float> confidences;
- std::vector<cv::Rect> boxes;
- //对推理的结果进行检测
- for (int i = 0; i < rows; ++i)
- {
-
- float confidence = data[4];
- if (confidence >= this->confThreshold) //如果置信度大于设置的阙值说明是可信的
- {
-
- float *classes_scores = data + 5;
- cv::Mat scores(1, this->classes.size(), CV_32FC1, classes_scores);
- cv::Point class_id;
- double max_class_score;
- minMaxLoc(scores, 0, &max_class_score, 0, &class_id);
- if (max_class_score > SCORE_THRESHOLD) //如果检测的分数大于阙值,则是可信的
- {
-
- confidences.push_back(confidence);
-
- class_ids.push_back(class_id.x);
-
- float x = data[0];
- float y = data[1];
- float w = data[2];
- float h = data[3];
- int left = int((x - 0.5 * w) * x_factor);
- int top = int((y - 0.5 * h) * y_factor);
- int width = int(w * x_factor);
- int height = int(h * y_factor);
- boxes.push_back(cv::Rect(left, top, width, height));
- }
- }
-
- data += 85;
- }
-
- std::vector<int> nms_result;
- //进行极大值抑制nms算法
- cv::dnn::NMSBoxes(boxes, confidences,SCORE_THRESHOLD,this->nmsThreshold, nms_result,0.8);//eta这个参数默认1.0,范围0.1-1.0,设置代表启用soft-nms算法,top_k表示保留框的个数
- //将结果存入output
- for (int i = 0; i < nms_result.size(); i++)
- {
- int idx = nms_result[i];
- Detection result;
- result.class_id = class_ids[idx];
- result.confidence = confidences[idx];
- result.box = boxes[idx];
- p.push_back(result);
- }
- int detections = p.size();
- for (int i = 0; i < detections; ++i)
- {
-
- auto detection = p[i];
- auto box = detection.box;
- auto classId = detection.class_id;
- output.name.push_back(this->classes[classId]);
- output.x.push_back(box.x);
- output.y.push_back(box.y);
- output.width.push_back(box.width);
- output.height.push_back(box.height);
- }
-
- return true;
- }
-
- //将识别结果画出来
- bool Recognizerv5::drawRect(cv::Mat &frame, Result &output)
- {
- for (int i = 0; i < output.name.size(); i++)
- {
- cv::Rect box(output.x[i], output.y[i], output.width[i], output.height[i]);
- cv::rectangle(frame, box, cv::Scalar(0, 255, 0), 3);
- cv::rectangle(frame, cv::Point(box.x, box.y - 20), cv::Point(box.x + box.width, box.y), cv::Scalar(0, 255, 0), cv::FILLED);
- cv::putText(frame, output.name[i].c_str(), cv::Point(box.x, box.y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
- }
- return true;
- }

以上可以分装在namespcae里便于使用
main函数
- int main(int argc, char const *argv[]){
- cv::VideoCapture camera=cv::VideoCapture(0);
- if (camera.isOpened() == false)
- {
- std::cout<< "camera couldn't open" <<std::endl;
- return -1;
- }
- struct Net5_config yolov5_net;
- //这里可以自己写一个从文件读取配置信息的函数,或者直接赋值在结构体里
- Recognizerv5 recognizer(yolov5_net);
- Result yolo_result;
- while (true)
- {
- cv::Mat image;
- camera >> image;
- if (image.empty() == true)
- {
- break;
- }
- cv::namedWindow("test",cv::WINDOW_NORMAL);
- YOLO::Result_clear(yolo_result);
- recognizer.IdentifyTarget(image, yolo_result);
- recognizer.drawRect(image, yolo_result);
- cv::imshow("test", image);
- if (cv::waitKey(1) > 0)
- {
- break;
- }
- }
- camera.release();
- cv::destroyAllWindows();
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。