DNN系列3_SSD模型实现对象检测

本例程用到的模型文件、源码和图片素材

贾志刚OpenCV3.3深度神经网络DNN模块系列学习资料整理

3 使用SSD模型实现对象检测

 SSD模型与数据介绍
 使用模型实现对象检测

3.1 SSD模型与数据介绍

 SSD模型
- https://github.com/weiliu89/caffe/tree/ssd#models
 Fast –R-CNN模型基础上延伸
 基于PASCAL VOC数据集实现200个分类对象检测

3.2 模型文件

 二进制模型
- VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel
 网络描述
- ILSVRC2016/SSD_300x300/deploy.prototxt
 分类信息
- ILSVRC2016/SSD_300x300/labelmap_det.txt

3.3 使用模型实现图像分类

 编码处理
- 加载Caffem模型
- 使用模型预测

实例3:SSD模型实现对象检测

​
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <iostream>

using namespace cv;
using namespace cv::dnn;
using namespace std;

const size_t width = 300;//模型尺寸为300*300
const size_t height = 300;
//label文件
String labelFile = "D:/opencv3.3/opencv/sources/samples/data/dnn/labelmap_det.txt";
//模型文件
String modelFile = "D:/opencv3.3/opencv/sources/samples/data/dnn/VGG_ILSVRC2016_SSD_300x300_iter_440000.caffemodel";
//模型描述文件
String model_text_file = "D:/opencv3.3/opencv/sources/samples/data/dnn/deploy.prototxt";

vector<String> readLabels();
const int meanValues[3] = { 104, 117, 123 };
static Mat getMean(const size_t &w, const size_t &h) {
	Mat mean;
	vector<Mat> channels;
	for (int i = 0; i < 3; i++) {
		Mat channel(h, w, CV_32F, Scalar(meanValues[i]));
		channels.push_back(channel);
	}
	merge(channels, mean);
	return mean;
}

static Mat preprocess(const Mat &frame) {
	Mat preprocessed;
	frame.convertTo(preprocessed, CV_32F);
	resize(preprocessed, preprocessed, Size(width, height)); // 300x300 image
	Mat mean = getMean(width, height);
	subtract(preprocessed, mean, preprocessed);
	return preprocessed;
}

int main(int argc, char** argv) {
	Mat frame = imread("persons.png");
	if (frame.empty()) {
		printf("could not load image...\n");
		return -1;
	}
	namedWindow("input image", CV_WINDOW_AUTOSIZE);
	imshow("input image", frame);

	vector<String> objNames = readLabels();
	// import Caffe SSD model
	Ptr<dnn::Importer> importer;
	try {
		importer = createCaffeImporter(model_text_file, modelFile);
	}
	catch (const cv::Exception &err) {
		cerr << err.msg << endl;
	}
	//初始化网络
	Net net;
	importer->populateNet(net);
	importer.release();

	Mat input_image = preprocess(frame);//获取输入图像
	Mat blobImage = blobFromImage(input_image);//将图像转换为blob

	net.setInput(blobImage, "data");//将图像转换的blob数据输入到网络的第一层“data”层,见deploy.protxt文件
	Mat detection = net.forward("detection_out");//结果输出(最后一层“detection_out”层)输出给detection
	Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());
	float confidence_threshold = 0.2;//自信区间,可以修改,越低检测到的物体越多
	for (int i = 0; i < detectionMat.rows; i++) {
		float confidence = detectionMat.at<float>(i, 2);
		if (confidence > confidence_threshold) {
			size_t objIndex = (size_t)(detectionMat.at<float>(i, 1));
			float tl_x = detectionMat.at<float>(i, 3) * frame.cols;
			float tl_y = detectionMat.at<float>(i, 4) * frame.rows;
			float br_x = detectionMat.at<float>(i, 5) * frame.cols;
			float br_y = detectionMat.at<float>(i, 6) * frame.rows;

			Rect object_box((int)tl_x, (int)tl_y, (int)(br_x - tl_x), (int)(br_y - tl_y));
			//标记框
			rectangle(frame, object_box, Scalar(0, 0, 255), 2, 8, 0);
			//设置颜色
			putText(frame, format("%s", objNames[objIndex].c_str()), Point(tl_x, tl_y), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255, 0, 0), 2);
		}
	}
	imshow("ssd-demo", frame);

	waitKey(0);
	return 0;
}

vector<String> readLabels() {
	vector<String> objNames;
	ifstream fp(labelFile);
	if (!fp.is_open()) {
		printf("could not open the file...\n");
		exit(-1);
	}
	string name;
	while (!fp.eof()) {
		getline(fp, name);
		if (name.length() && (name.find("display_name:") == 0)) {
			string temp = name.substr(15);
			temp.replace(temp.end() - 1, temp.end(), "");
			objNames.push_back(temp);
		}
	}
	return objNames;
}

​

     

      

由于SSD模型支持200个分类,分类数目比较多,所以运行时间会长一些

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
这个表达式是计算二分类(通常涉及机器学习中的预测模型,如DNN,即深度神经网络)中模型的准确率(Accuracy)。其中: - TP (True Positive): 真正例,预测为正且实际为正的样本数。 - TN (True Negative): 真负例,预测为负且实际为负的样本数。 - FP (False Positive): 假正例,预测为正但实际为负的样本数。 - FN (False Negative): 假负例,预测为负但实际为正的样本数。 公式 `(TP_DNN + TN_DNN) / (TP_DNN + TN_DNN + FP_DNN + FN_DNN)` 就是将正确预测(TP和TN)的总数除以所有预测总数(包括正确和错误预测),得到分类器在给定数据集上的准确率。 为了增加一个固定的阈值为0.5(通常用于二元分类问题中的概率阈值决策),我们通常会这样操作: 1. 对于模型输出的概率或预测概率进行比较。如果预测概率大于等于0.5,我们可以将其分类为正例(例如1),否则为负例(例如0)。 2. 计算新的TP、TN、FP和FN,基于新的分类标准。 这是一个示例代码片段: ```python # 假设model_output是DNN模型的输出概率列表 threshold = 0.5 new_predictions = [1 if prob >= threshold else 0 for prob in model_output] # 更新计数 TP_new = sum([1 for pred, actual in zip(new_predictions, labels) if pred == 1 and actual == 1]) TN_new = sum([1 for pred, actual in zip(new_predictions, labels) if pred == 0 and actual == 0]) FP_new = sum([1 for pred, actual in zip(new_predictions, labels) if pred == 1 and actual == 0]) FN_new = sum([1 for pred, actual in zip(new_predictions, labels) if pred == 0 and actual == 1]) # 新的精度计算 accuracy_DNN_thresholded = (TP_new + TN_new) / (TP_new + TN_new + FP_new + FN_new) print(f"Accuracy with 0.5 threshold: {accuracy_DNN_thresholded}") ``` 这里`labels`是对应的实际标签列表,`model_output`是模型预测的概率输出。这个新精度值就是基于0.5阈值后的模型性能。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亦我飞也

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值