Modelo de red neuronal profunda DNN: uso del modelo SSD para lograr la detección de objetivos

1. Modelo de red neuronal profunda

  • Funciones compatibles con openCV DNN: clasificación de imágenes, detección de objetos, segmentación de imágenes, detección de texto de escena, detección y reconocimiento de rostros

  • Red de detección de objetos compatible con openCV DNN: Faster-RCNN, SSD (VGG/mobile-net backbone), YOLO (YOLOv3/YOLOv3-tiny/YOLOv4)

                输入------------------>黑盒------------------------>输出
    

2. OpenCV usa un modelo de red entrenado

三、SSD (Detector MultiBox de Disparo Único)

Opencv admite muchos marcos de aprendizaje profundo y hay muchos modelos de red profunda de código abierto.Tome el modelo SSD como ejemplo:
MobileNetSSD_deploy.caffemodel

Resumen de los archivos de descripción del modelo admitidos por openCV: sitio inalcanzable

# Caffe implementation of SSD model from https://github.com/chuanqi305/MobileNet-SSD //模型来源地址
ssd_caffe:
load_info:
url: "https://drive.google.com/uc?export=download&id=0B3gersZ2cHIxRm5PMWRoTkdHdHc"
sha1: "994d30a8afaa9e754d17d2373b2d62a7dfbaaf7a"
model: "MobileNetSSD_deploy.caffemodel" //模型二进制文件名
config: "MobileNetSSD_deploy.prototxt"  //模型描述文件名 ,二者均在模型来源地址下载
mean: [127.5, 127.5, 127.5]
scale: 0.007843
width: 300
height: 300
rgb: false
classes: "object_detection_classes_pascal_voc.txt"
sample: "object_detection"

Archivo de descripción del modelo

name: "MobileNet-SSD"
input: "data" //输入层名称
input_shape {
    
     //输入参数格式
dim: 1 //每次接受一张图片
dim: 3 //三通道
dim: 300
dim: 300  //图像尺寸300*300
}
.....//中间省略网络各层描述
layer {
    
     
name: "detection_out"
type: "DetectionOutput"
bottom: "mbox_loc"
bottom: "mbox_conf_flatten"
bottom: "mbox_priorbox"
top: "detection_out"    //最后一层描述示例
include {
    
    
phase: TEST
}
detection_output_param {
    
    
num_classes: 21
share_location: true
background_label_id: 0
nms_param {
    
    
nms_threshold: 0.45
top_k: 100
}
  • Entrada: [ 1 × 3 × 300 × 300 ] [ 1\times3\times300\times300][ 1×3×300×300 ]
  • Salida: [ 1 × 1 × 100 × 7 ] [ 1\times1\times100\times7][ 1×1×100×7 ] , los datos de coma flotante correspondientes a 7 son los siguientes: [image_id, label, conf, x_min, y_min, x_max, y_max]
  • Ejemplo:

4. Proceso de uso de la red OpenCV

Referencias: Módulo OpenCv-C+±Deep Neural Network (DNN) - Clasificación de imágenes usando el modelo Goolenet

1. Cargue el modelo de red

Archivos de descripción del modelo admitidos por openCV: sitio inalcanzable

Net cv::dnn::readNet(const String& model, //模型的二进制文件
					 const String& config="", //模型的配置参数,通常在模型的voc文件夹下寻找
					 const String& framework="" //具体的框架名
					 )

2. Computar back-end

El módulo OpenCV dnn admite la configuración de diferentes backends informáticos en el dispositivo de destino especificado.

void cv::dnn::Net::setPreferableBackend(int backendId);
void cv::dnn::Net::setPreferableTarget(int targetId);

3. Entrada de compilación

Mat cv::dnn::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 
						   )

4. Ejecutar inferencia de razonamiento

Mat cv::dnn::Net::forward(const String& outputName=String())

5. Analizar la salida

usardetection函数

Cinco, código completo

Referencia: Red neuronal profunda (DNN) II (Detección de objetos mediante SSD)

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>			//包含dnn模块的头文件
#include <iostream>

using namespace cv;
using namespace cv::dnn;			//包含dnn的命名空间
using namespace std;

String objNames[] = {
    
     "background",
"aeroplane","bicycle","bird","boat",
"bottle","bus","car","cat","chair",
"cow","diningtable","dog","horse",
"motorbike","person","pottedplant",
"sheep","sofa","train","tvmonitor" };

int main() {
    
    

	string bin_model = "D:/OpenCV/project/opencv_tutorial-master/data/models/ssd/MobileNetSSD_deploy.caffemodel";		//定义模型权重文件的加载路径
	string protxt = "D:/OpenCV/project/opencv_tutorial-master/data/models/ssd/MobileNetSSD_deploy.prototxt";			//定义模型描述文件的加载路径

	//load DNN model
	Net net = readNetFromCaffe(protxt, bin_model);

	//设置计算后台(OpenCVdnn模块支持设置不同的计算后台和在不同的设备上进行)
	net.setPreferableBackend(DNN_BACKEND_OPENCV);				//setPreferableBackend实际计算后台,default默认是DNN_BACKEND_OPENCV作为计算后台,使用此就行(也有加速后台ENGINE)
	net.setPreferableTarget(DNN_TARGET_CPU);						//设置在什么设备上进行计算(opencl(需要有interl图形卡)、FPGA、CPU)

	//获取各层信息
	vector<string> layer_names = net.getLayerNames();		//此时我们就可以获取所有层的名称了,有了这些可以将其ID取出
	for (int i = 0; i < layer_names.size(); i++) {
    
    
		int id = net.getLayerId(layer_names[i]);			//通过name获取其id
		auto layer = net.getLayer(id);						//通过id获取layer
		printf("layer id:%d,type:%s,name:%s\n", id, layer->type.c_str(), layer->name.c_str());	//将每一层的id,类型,姓名打印出来(可以明白此网络有哪些结构信息了)
	}

	Mat src = imread("G:/OpenCV/opencv笔记所用图片/gou.jpg");	//plane
	if (src.empty()) {
    
    
		cout << "could not load image.." << endl;
		getchar();
		return -1;
	}
	imshow("src", src);

	//构建输入(根据models.yml)
	Mat blob = blobFromImage(src, 0.007843, Size(300, 300), Scalar(127.5, 127.5, 127.5), false, false);	//交换通道false,是否剪切false
	net.setInput(blob, "data");		//输入层名称就是data,通过描述文件也可以看到输入层名称

	//推测结果
	Mat detection = net.forward("detection_out");	//将名称为detection_out的层的结果返回,不输入名称默认也是返回最后一层,输入可以返回特定层的结果
	//上方得到的detection宽高为0(使用imagewatch查看,原因是其为tensor,它的宽高维度等信息都存在size结构中,所以要在下方通过size获取)
													
	//重新定义一个Mat对象接收
	Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());		//此处是初始化一个行为size[2],列为size[3]大小,深度为浮点型,数据从detection中获取
																								//使用imagewatch可以看到7*100的数组,单通道32F深度
	
	//获取浮点型数据后就可以进行数据的解析了
	float confidence_threshold = 0.5;		//在后面通过此判断合适的结果进行保存
	

	//解析输出数据
	//上方获取的detectionMat是100行,7列的,每行对应一个对象
	//输出结果[1x1xNx7], 其中输出的七个维度浮点数如下:
	//[image_id, label, conf, x_min, y_min, x_max, y_max]
	for (int i = 0; i < detectionMat.rows; i++) {
    
    
		float score = detectionMat.at<float>(i, 2);			//此处获取的是conf(i, 2),也就是得分
		if (score > confidence_threshold) {
    
    					//如果获取的score大于0.5,就将box保存,不要扔掉
			size_t objIndex = (size_t)(detectionMat.at<float>(i, 1));		//此处获取的是label(i, 2),就是索引
			//得到四个点的矩形框位置
			float tl_x = detectionMat.at<float>(i, 3)*src.cols;		//x_min(此处detectionMat.at<float>(i, 3)得到的是一个图像的比例值不是真实值,需要变换)
			float tl_y = detectionMat.at<float>(i, 4)*src.rows;		//y_min
			float br_x = detectionMat.at<float>(i, 5)*src.cols;		//x_max
			float br_y = detectionMat.at<float>(i, 6)*src.rows;		//y_max
			//得到box
			Rect box((int)tl_x, (int)tl_y, (int)br_x - tl_x, (int)br_y - tl_y);
			//画矩形
			rectangle(src, box, Scalar(0, 0, 255), 2, 8, 0);
			//写文字(在box的做上角写文字)
			putText(src, format("score:%2f,%s",score,objNames[objIndex].c_str()), box.tl(), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(255, 0, 0), 2, 8);
		}
	}
	imshow("ssd-detection-demo", src);

	waitKey(0);
	return 0;
}

六、API de detección de objetos TensorFlow

La introducción anterior es el modelo SSD bajo el marco Caff. De manera similar, también se pueden usar modelos bajo el marco TensorFlow como YOLO.

Supongo que te gusta

Origin blog.csdn.net/weixin_43949950/article/details/126341068
Recomendado
Clasificación