- 环境准备
首先,确保你已经安装了以下工具:
OpenCV:用于图像处理。
Darknet:用于 YOLO 模型的推理。
C++ 编译器:如 g++。
2. 安装 Darknet
克隆 Darknet 仓库并进入目录:
bash
git clone https://github.com/pjreddie/darknet.git
cd darknet
使用 Makefile 编译 Darknet(如果使用 GPU 支持,记得修改 Makefile,启用 GPU 和 CUDNN):
bash
make
下载 YOLOv3 的预训练权重文件:
bash
wget https://pjreddie.com/media/files/yolov3.weights
3. 使用 C++ 进行物体检测
接下来我们编写一个简单的 C++ 程序,使用 YOLOv3 模型进行物体检测。
C++ 程序 (yolo_detect.cpp)
cpp
include
include <opencv2/opencv.hpp>
include <opencv2/dnn.hpp>
using namespace std;
using namespace cv;
using namespace cv::dnn;
// 加载 YOLO 模型文件
const String modelConfiguration = "cfg/yolov3.cfg"; // YOLO 配置文件路径
const String modelWeights = "yolov3.weights"; // YOLO 权重文件路径
const String classesFile = "cfg/coco.names"; // 类别文件,包含检测物体的类别名称
vector
// 加载类别文件
void loadClassNames(const string& filename) {
ifstream classFile(filename);
string line;
while (getline(classFile, line)) {
classNames.push_back(line);
}
}
// 加载 YOLO 模型
Net loadYOLOModel() {
// 加载 YOLO 配置文件和权重文件
Net net = readNetFromDarknet(modelConfiguration, modelWeights);
return net;
}
// 物体检测函数
void detectObjects(Mat& frame, Net& net) {
Mat blob;
// 将图像转换为 blob(神经网络的输入格式)
blobFromImage(frame, blob, 1/255.0, Size(416, 416), Scalar(), true, false);
// 将 blob 设置为网络输入
net.setInput(blob);
// 获取网络的所有输出层
vector<String> outNames = net.getUnconnectedOutLayersNames();
vector<Mat> outs;
net.forward(outs, outNames);
// 解析 YOLO 输出
for (size_t i = 0; i < outs.size(); ++i) {
float* data = (float*)outs[i].data;
for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols) {
// 获取每个框的概率
float confidence = data[4];
if (confidence > 0.5) {
// 计算类别
int classID = -1;
float maxClassProb = -1;
for (int k = 5; k < outs[i].cols; ++k) {
if (data[k] > maxClassProb) {
maxClassProb = data[k];
classID = k - 5;
}
}
// 如果类别有效,画出矩形框
if (classID >= 0) {
int x = (int)(data[0] * frame.cols);
int y = (int)(data[1] * frame.rows);
int w = (int)(data[2] * frame.cols);
int h = (int)(data[3] * frame.rows);
// 绘制边界框
rectangle(frame, Point(x, y), Point(x + w, y + h), Scalar(0, 255, 0), 2);
// 在框上写上类别名
putText(frame, classNames[classID], Point(x, y - 5), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 2);
}
}
}
}
}
int main() {
// 加载类别名称
loadClassNames(classesFile);
// 加载 YOLO 模型
Net net = loadYOLOModel();
// 打开视频或摄像头
VideoCapture cap("test.jpg"); // 可以换成视频路径或者摄像头索引(0 为默认摄像头)
if (!cap.isOpened()) {
cerr << "Error: Cannot open video stream or image." << endl;
return -1;
}
// 循环读取每一帧
while (true) {
Mat frame;
cap >> frame; // 读取一帧
if (frame.empty()) {
break; // 如果没有帧则退出
}
// 检测物体
detectObjects(frame, net);
// 显示结果
imshow("YOLO Object Detection", frame);
// 按下 'q' 键退出
if (waitKey(1) == 'q') {
break;
}
}
return 0;
}
4. 编译和运行
确保你已经安装了 OpenCV 和 C++ 编译器。
编译 C++ 程序:
bash更多内容访问ttocr.com或联系1436423940
g++ -o yolo_detect yolo_detect.cpp pkg-config --cflags --libs opencv4
运行程序:
bash
./yolo_detect
5. 程序说明
加载 YOLO 模型: 我们使用 cv::dnn::readNetFromDarknet 来加载 YOLOv3 的配置和权重文件。
物体检测: 在 detectObjects 函数中,我们将图像转换为模型可以接受的输入格式(blob),然后通过 net.forward() 进行推理,得到检测结果。我们从每个检测框中提取置信度,并在图像中绘制边界框。
OpenCV 显示图像: 使用 imshow 展示检测结果,按 q 键退出。
6. 结果展示
运行程序后,YOLO 模型会自动检测图像中的物体,并显示带有边界框的图像。