首先需要确保使用的opencv4为最新的版本,该版本需要支持
cv::dnn::DNN_BACKEND_CUDA
变量的声明使用
这里我在github上放了一个简单使用opencv4调用yolov3的链接
项目链接
具体关键代码段
读入权重和网络结构,调用cv::dnn对应的后端设置函数
net = cv::dnn::readNetFromDarknet(modelConfiguration, modelBinary);
// net.setPreferableTarget(cv::dnn::DNN_TARGET_OPENCL);
// net.setPreferableBackend(cv::dnn::DNN_BACKEND_INFERENCE_ENGINE);
// when using opencv 4 and data > 20191022, the cuda is support
net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
这样子程序再运行dnn计算时,会使用gpu加速
然后进行网络调用
cv::Mat inputBlob = cv::dnn::blobFromImage(frame, 1 / 255.F, cv::Size(416, 416), cv::Scalar(), true, false);
net.setInput(inputBlob, input_layer_);
std::vector<cv::Mat> detectionMats;
if (outputBlobName.size() < 1)
{
// default using yolo v3
outputBlobName.push_back("yolo_82");
outputBlobName.push_back("yolo_94");
outputBlobName.push_back("yolo_106");
}
net.forward(detectionMats, outputBlobName);
上述应用中,提取了yolov3的三个层的输出
mat size of detection : 507, 85
mat size of detection : 2028, 85
mat size of detection : 8112, 85
85 = [x, y, w, h] + box_confidence + 80 classes
507 = 13 x 13 x 3
2028 = 26 x 26 x 3
8112 = 52 x 52 x 3
很明显先这三层即为yolov3的分类输出层,根据Mat每一行数据的理解,就可以完成对识别结果框取
该部分的具体实现可以参考到github链接上,是opencv比较常用的方法
ps: 当时的opencv编译版本参考另一篇 基于CUDA和Intel INF_BACKEND的OpenCV4编译
目前cv已经更新到了4.3.0,当时是基于4.1.2的未发布版本实现的cuda backend加速