OpenCv-C++-深度神经网络(DNN)模块-使用MobileNet模型实现实时对象检测

版权声明:本文为博主原创文章,转载请附上博文链接! https://blog.csdn.net/Daker_Huang/article/details/87563817

上篇文章中使用了SSD模型进行对象检测,虽然没有说明模型运行时间,但是ssd是非常耗时的,速度有点慢,因为它的支持数目比较多。而MobileNet其实就是ssd的删减版,运作速度有所提升,但支持的检测对象比较少。所以它是一种轻量级网络,主要应用于移动端。
具体需参考以下文章:https://blog.csdn.net/u011974639/article/details/79199306
https://blog.csdn.net/wfei101/article/details/78310226

上面说到,mobilenet是ssd的精简版,所以在代码层面上没有什么变化,只是一些参数有少许变化。
完整代码:

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

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

const size_t width = 300;
const size_t height = 300;//定义图像文件宽高

vector<String> labels();

string label_file = "D:/test/ssd/mobilenet-ssd/labelmap.txt";
string deploy_file = "D:/test/ssd/mobilenet-ssd/MobileNetSSD_deploy.prototxt";
string model_file = "D:/test/ssd/mobilenet-ssd/MobileNetSSD_deploy.caffemodel";



int main(int argc, char **argv)
{
	VideoCapture capture;
	capture.open("D:/test/dog.avi");
	if (!capture.isOpened())
	{
		cout << "视频文件未找到!!!" << endl;
		return -1;
	}
	Mat frame;
	vector<string>objnames=labels();
	Net net;
	net = readNetFromCaffe(deploy_file, model_file);//读取二进制文件和描述文件
	Mat inputblob,detection;
	while (capture.read(frame))
	{
		imshow("input video", frame);
		inputblob = blobFromImage(frame, 0.007843f, Size(width , height), 127.5, false, false);
		//0.007843f是开发作者文档中唯一确定的,就是这个参数
		net.setInput(inputblob, "data");
		detection =net.forward("detection_out");
		Mat detectionMat(detection.size[2], detection.size[3],CV_32F, detection.ptr<float>());

		float confidence_threshold = 0.3;
		for (int i = 0; i < detectionMat.rows; i++)
		{
			float confidence = detectionMat.at<float>(i, 2);
			if (confidence > confidence_threshold)
			{
				size_t objnameIndex = (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 objrect((int)tl_x,(int)tl_y,int(br_x-tl_x),int(br_y-tl_y));
				rectangle(frame, objrect, Scalar(0, 0, 255), 2, 8, 0);
				putText(frame,objnames[objnameIndex], Point(tl_x, tl_y), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255, 0, 0), 2);
			}

		}
		imshow("output video",frame);
		char c = waitKey(20);
		if (c == 27)
		{
			break;
		}

	}
	capture.release();
	waitKey(0);
	destroyAllWindows();
	return 0;

}

vector<String> labels()
{
	vector<String>objNames;


	ifstream fp(label_file);//打开输入流,读入文件
	if (!fp.is_open())
	{
		printf("文件读入失败!!!\n");
		exit(-1);//直接退出

	}
	string name;//标签文件中都有对应的名字
	while (!fp.eof())//当文件没有读到结尾
	{
		getline(fp, name);//读取每一行
		if (name.length())
		{
			string temp1 = name.substr(name.find(",") + 1);   //找到每行第一个逗号,从逗号后面开始取数据
			string temp2 = temp1.substr(temp1.find(",") + 1);//找到新的(第二个)逗号,从逗号后面开始取数据
			objNames.push_back(temp2);
		}
	}
	/*for (vector<string>::iterator iter = objNames.begin(); iter != objNames.end(); ++iter)
	{
		//输出*iter才是输出那些字符串
		cout << *iter << endl;
	}*/
	return objNames;
}




运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Daker_Huang/article/details/87563817