- 環境準備
首先,確保你已經安裝了以下工具:
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 模型會自動檢測影像中的物體,並顯示帶有邊界框的影像。