blobFromImage函数
blobFromImage(InputArray image,
double scalefactor=1.0,
const Size& size = Size(),
const Scalar& mean = Scalar(),
bool swapRB = false,
bool crop = false,
int ddepth = CV_32F)image:读取的图片数据
scalefactor: 缩放像素值,如 [0, 255] - [0, 1]
size: 输出blob(图像)的尺寸
mean: 从各通道减均值. 如果输入 image 为 BGR 次序,且swapRB=True,则通道次序为 (mean-R, mean-G, mean-B).
swapRB: 交换 3 通道图片的第一个和最后一个通道,如 BGR - RGB
crop: 图像尺寸 resize 后是否裁剪. 如果crop=True,则,输入图片的尺寸调整resize后,一个边对应与 size 的一个维度,而另一个边的值大于等于 size 的另一个维度;然后从 resize 后的图片中心进行 crop. 如果crop=False,则无需 crop,只需保持图片的长宽比
ddepth: 输出 blob 的 Depth. 可选: CV_32F 或 CV_8U
NMSBoxes函数
void cv::dnn::NMSBoxes( vector<cv::Rect> _boxes,
vector<float> _scores,
float _score_threshold,
float _nms_threshold,
vector<int> _indices)
_boxes: 输入边界框,一般为(x, y, w, h)格式的Rect格式的容器。
_scores: 输入边界框的预测分数,一般为每个边界框的类别概率或类别得分。
_score_threshold: 分数阈值,低于此阈值的边界框将被过滤掉。
_nms_threshold: 非极大值抑制阈值,用于决定哪些边界框之间的重叠度过高,需要抑制。
_indices: 输出参数,包含被选中的边界框的索引。
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\dnn.hpp>
#include<fstream>
using namespace std;
using namespace cv;
using namespace dnn;
const std::vector<cv::Scalar> colors = { cv::Scalar(255, 255, 0), cv::Scalar(0, 255, 0), cv::Scalar(0, 255, 255), cv::Scalar(255, 0, 0) };
const float SCORE_THRESHOLD = 0.2;
const float CONFIDENCE_THRESHOLD = 0.6;
const float NMS_THRESHOLD = 0.4;
struct Detection
{
int class_id;
float confidence;
cv::Rect box;
};
int main() {
Net net = readNetFromONNX("best.onnx");//加载模型
net.setPreferableBackend(DNN_BACKEND_DEFAULT);//setPreferableBackend实际计算后台,defau1t默认是DNNBACKEND_OPENCV作为计算后台,使用此就行(也有加速后台ENGINE)
net.setPreferableTarget(DNN_TARGET_CUDA); //设置在什么设备上进行计算
cv::Mat mat = imread("C:/Users/Administrator/Documents/visual studio 2015/Projects/test/test/box/0002 (2654).jpg");
cv::Mat blob = cv::dnn::blobFromImage(mat, 1.0 / 255, cv::Size(960, 960), cv::Scalar(0, 0, 0), true);
net.setInput(blob);
std::vector<cv::Mat>outputs;
net.forward(outputs);
float* data = (float*)outputs[0].data;
//dimensions为6,[0][1]为中心点xy坐标;[2][3]为wh;[4]为置信度,本模型一个类别,所以为5+1
const int dimensions = 6;
//rows为56700,对960*960像素的图片的3个通道分别进行了8、16、32倍采样,所以结果为120*120*3+60*60*3+30*30*3=56700
const int rows = 56700;
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 >= CONFIDENCE_THRESHOLD) {
float* classes_scores = data + 5;
cv::Mat scores(1, 3, 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);
int top = int(y - 0.5 * h);
int width = int(w);
int height = int(h);
boxes.push_back(cv::Rect(left, top, width, height));
}
}
data += 8;
}
std::vector<int> nms_result;
cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, nms_result);
std::vector<Detection> 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];
output.push_back(result);
}
int detections = output.size();
for (int i = 0; i < detections; ++i)
{
auto detection = output[i];
auto box = detection.box;
auto classId = detection.class_id;
auto color = colors[classId % colors.size()];
cv::rectangle(mat, box, color, 3);
}
cv::imshow("output", mat);
waitKey();
}