Opencv---深度学习开发

在OpenCV中进行深度学习开发,主要围绕其dnn模块展开,该模块支持加载预训练模型、预处理输入数据、执行推理计算以及解析输出结果。本文讲解基于OpenCV进行深度学习开发的基本流程。

一、准备工作

在开始开发前,需完成环境配置和资源准备,确保基础条件满足:

  1. 安装OpenCV
    需安装包含dnn模块的OpenCV版本(建议4.0以上),可通过源码编译(支持更多模型格式)或直接安装预编译包(如pip install opencv-python)。
  2. 获取预训练模型
    OpenCV的dnn模块支持多种深度学习框架的模型,需提前准备模型文件,常见来源包括:
    • 公开数据集预训练模型(如ImageNet上的ResNet、VGG等);
    • 自定义训练的模型(需导出为dnn支持的格式,如TensorFlow的.pb、PyTorch的.onnx、Caffe的.caffemodel等)。
    • 模型需包含网络结构文件(如Caffe的.prototxt、TensorFlow的.pbtxt)和权重文件(如.caffemodel.pb)。
  3. 了解模型输入输出要求
    不同模型对输入数据的格式(尺寸、通道顺序、归一化方式等)和输出的解析方式不同,需提前查阅模型文档(如输入尺寸为224x224,通道顺序为BGR,均值和方差等)。

二、基本开发流程

步骤1:加载深度学习模型

使用cv::dnn::readNet函数加载模型,该函数支持多种格式,自动根据文件后缀识别框架类型:

// 示例:加载Caffe模型(需.prototxt和.caffemodel文件)
cv::dnn::Net net = cv::dnn::readNetFromCaffe("deploy.prototxt", "model.caffemodel");// 其他格式示例:
// TensorFlow模型:readNetFromTensorflow("model.pb", "graph.pbtxt")
// ONNX模型(支持PyTorch导出):readNetFromONNX("model.onnx")
// Darknet模型(YOLO):readNetFromDarknet("yolov3.cfg", "yolov3.weights")
  • 关键说明cv::dnn::Net是OpenCV中表示神经网络的类,封装了模型的加载、推理等功能。
步骤2:读取输入数据

输入数据可以是图像、视频帧或摄像头实时流,使用OpenCV的常规函数读取:

// 读取单张图像
cv::Mat image = cv::imread("input.jpg");
if (image.empty()) {// 处理读取失败的情况
}// 读取视频或摄像头(循环读取帧)
cv::VideoCapture cap("video.mp4"); // 或 cap(0) 表示摄像头
cv::Mat frame;
while (cap.read(frame)) {// 对每一帧执行后续处理
}
步骤3:预处理输入数据

深度学习模型对输入格式有严格要求,需将原始图像转换为模型可接受的“ blob ”(二进制大对象,即网络输入的4D张量:[batch_size, channels, height, width])。
核心函数:cv::dnn::blobFromImage,用于完成图像到blob的转换,包含多种预处理操作:

// 示例:将图像转换为模型输入blob
cv::Mat blob;
// 参数说明:
// image:输入图像(OpenCV默认BGR通道)
// scalefactor:缩放因子(如1/255.0将像素值归一化到0~1)
// size:模型要求的输入尺寸(如(224, 224))
// mean:均值减法(如(104.0, 117.0, 123.0),对应BGR通道)
// swapRB:是否交换R和B通道(OpenCV读入为BGR,若模型要求RGB则设为true)
// crop:是否裁剪图像(超出尺寸部分裁剪,否则拉伸)
cv::dnn::blobFromImage(image, blob, 1.0/255.0, cv::Size(224, 224), cv::Scalar(0, 0, 0), true, false);
  • 关键预处理操作
    • 尺寸调整:将图像缩放或裁剪到模型要求的输入尺寸(如224x224、320x320);
    • 通道转换:OpenCV默认图像为BGR通道,若模型要求RGB(如TensorFlow模型),需通过swapRB=true转换;
    • 归一化:通过scalefactor(缩放)和mean(均值减法)将像素值调整到模型训练时的范围(如1/255.0将0255转为01,或减去ImageNet均值(103.939, 116.779, 123.68));
    • 批处理blobFromImage默认生成单张图像的blob(batch_size=1),若需多图批量推理,可使用blobFromImages
步骤4:设置网络输入

将预处理后的blob设置为神经网络的输入层,需指定输入层名称(可通过模型结构文件查看,如Caffe模型通常为data,TensorFlow可能为input):

// 设置输入blob到网络的输入层(输入层名称需与模型结构一致)
net.setInput(blob, "data"); // "data"为输入层名称,需根据模型修改
步骤5:执行模型推理

调用forward方法执行推理,获取输出结果。根据模型类型,输出可能是单一层的结果或多个层的结果:

// 方法1:获取指定输出层的结果(推荐,效率更高)
cv::Mat output;
// 需指定输出层名称(可通过模型结构文件查看,如"prob"、"detection_out")
output = net.forward("prob"); // 方法2:获取所有输出层的结果(返回vector<Mat>)
std::vector<cv::Mat> outputs;
net.forward(outputs);
  • 关键说明
    输出结果output是一个cv::Mat对象,维度根据模型而定(如分类模型可能为[1, N, 1, 1],其中N为类别数;目标检测模型可能包含边界框、类别、置信度等信息)。
步骤6:解析输出结果

根据模型任务类型(分类、检测、分割等),解析输出的cv::Mat数据,提取有意义的结果:

  1. 图像分类任务
    输出通常是每个类别的概率,需找到概率最大的类别索引,对应类别名称:

    // 假设output为[1, 1000, 1, 1](1000类分类)
    cv::Mat probMat = output.reshape(1, 1); // 转换为1x1000的矩阵
    cv::Point classIdPoint;
    double confidence;
    // 找到最大概率的位置和值
    cv::minMaxLoc(probMat, nullptr, &confidence, nullptr, &classIdPoint);
    int classId = classIdPoint.x; // 类别索引
    
  2. 目标检测任务(如SSD、YOLO)
    输出包含边界框坐标(x1, y1, x2, y2)、类别ID、置信度等,需过滤低置信度结果并绘制边界框:

    // 以SSD为例,输出格式为[N, 1, M, 7],其中M为检测框数量,7个值分别为:
    // [batch_id, class_id, confidence, x1, y1, x2, y2](坐标为归一化值,需映射回原图)
    float* data = (float*)output.data;
    for (int i = 0; i < output.total() / 7; ++i) {float confidence = data[i * 7 + 2];if (confidence > 0.5) { // 过滤置信度>0.5的框int classId = static_cast<int>(data[i * 7 + 1]);// 边界框坐标(归一化到0~1,需乘以原图宽高)int x1 = static_cast<int>(data[i * 7 + 3] * image.cols);int y1 = static_cast<int>(data[i * 7 + 4] * image.rows);int x2 = static_cast<int>(data[i * 7 + 5] * image.cols);int y2 = static_cast<int>(data[i * 7 + 6] * image.rows);// 绘制边界框和类别信息cv::rectangle(image, cv::Rect(x1, y1, x2-x1, y2-y1), cv::Scalar(0, 255, 0), 2);}
    }
    
  3. 其他任务(如语义分割、姿态估计)
    需根据具体模型的输出格式解析(如分割模型输出每个像素的类别,需转换为彩色掩码)。

步骤7:可视化或后处理结果

将解析后的结果(如分类标签、检测框、分割掩码)叠加到原始图像上,或保存为文件、输出到控制台:

// 显示结果图像
cv::imshow("Result", image);
cv::waitKey(0);
// 保存结果
cv::imwrite("result.jpg", image);

三、高级优化(可选)

为提升推理效率,可利用硬件加速(需OpenCV编译时支持对应后端):

// 设置推理后端(如OpenVINO、CUDA、DNN_TARGET_CPU等)
net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV); // 或DNN_BACKEND_CUDA
// 设置目标设备(CPU、GPU等)
net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU); // 或DNN_TARGET_CUDA

总结

OpenCV深度学习开发的核心流程可概括为:
加载模型 → 读取并预处理输入 → 设置输入 → 执行推理 → 解析输出 → 可视化结果
该流程适用于分类、检测、分割等多种任务,关键在于根据模型类型正确预处理输入和解析输出,同时可通过硬件加速优化推理速度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/88742.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/88742.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++11】右值引用详解

文章目录前言1. 左、右值的概念1.1 左值1.2 右值1.3 右值引用2. 右值引用的价值和使用场景2.1 左值引用的价值和缺陷2.2 右值引用的价值和使用场景2.3 小结3. 完美转发4. 类的移动构造和移动赋值前言 在C11之前&#xff0c;面对C11之前出现的临时对象的传参构造&#xff0c;都…

如何用自指理解世界

自指即自我指涉&#xff0c;即自己的描述关联到了自己&#xff0c;典型例子是“这句话是假话”这个悖论。人类对自指的研究由来已久&#xff0c;很多概念、定理都与之相关&#xff0c;由于它的巧妙性&#xff0c;很多学者对其展开了深入研究&#xff0c;并且认为自指是理解宇宙…

Next.js 实战笔记 2.0:深入 App Router 高阶特性与布局解构

Next.js 实战笔记 2.0&#xff1a;深入 App Router 高阶特性与布局解构 上一篇笔记&#xff1a; Next.js 实战笔记 1.0&#xff1a;架构重构与 App Router 核心机制详解 上篇笔记主要回顾了一些 Next12 到 Next15 的一些变化&#xff0c;这里继续学习/复习一些已有或者是新的…

TCP 传输时 sk_buff 的 clone 和 unclone

周一有位朋友咨询个问题&#xff0c;问题本身不重要&#xff0c;但牵扯出的细节却是非常有趣。 Linux 内核协议栈的 skb 设计非常高效和精巧&#xff0c;多个 skb 可以指向同一块 data&#xff0c;这就是 clone&#xff0c;当 data 不止一个 skb 指示时&#xff0c;任何一个 s…

【51单片机】51单片机学习笔记-课程简介

00. 目录 文章目录00. 目录01. 学习哪种类型的单片机02. 学习单片机方法03. 学习单片机硬件设备04. 学习单片机软件设备05. 学完单片机能做什么06. 附录01. 学习哪种类型的单片机 单片机的型号那么多&#xff0c;该如何选择一款合适的进行学习呢&#xff1f;这里给读者首推的当…

【Docker基础】Docker端口映射(-p参数)深度解析与实践指南

目录 前言 1 Docker网络基础 1.1 Docker网络模型概述 1.2 容器网络隔离性 2 端口映射基础 2.1 端口映射概念 2.2 为什么需要端口映射 3 -p参数详解 3.1 基本语法 3.2 四种映射格式 3.2.1 完整格式 3.2.2 省略宿主机IP 3.2.3 随机宿主机端口 3.2.4 指定协议类型 …

2、鸿蒙Harmony Next开发:ArkTS语言

目录 什么是ArkTS&#xff1f; ArkTS的发展趋势 ArkTS的定位及约束 ArkTS的对UI的拓展 1、UI描述 2、状态管理&#xff1a; ArkTS语法基础 基本知识&#xff1a;声明 基本知识&#xff1a;类型 基本知识&#xff1a;空安全 基本知识&#xff1a;类型安全与类型推断 …

【Elasticsearch】function_score

如果你希望在 Elasticsearch 查询中降低某些特定 `id` 的文档评分,可以通过 `function_score` 查询结合 `script_score` 函数来实现。`script_score` 允许你使用自定义脚本对文档的评分进行调整。 以下是一个示例,展示如何降低某些特定 `id` 的文档评分: 示例场景 假设我们…

vscode打开stm32CubeIDE的项目的注释问题

文章目录 目的是为消除红色底线打开命令面板&#xff1a;CtrlShiftP 搜索并打开&#xff1a;C/C: Edit Configurations (JSON) 修改并添加。&#xff08;注意里面的版本号&#xff09; {"configurations": [{"name": "Win32","includePath&…

ESP32使用freertos更新lvgl控件内容

LVGL不是线程安全&#xff0c;所有 lv_xxx方法只能在GUI主线程调用。 freertos都是线程池&#xff0c;子线程&#xff0c;不能直接更新lvgl&#xff0c;不然看门狗被触发&#xff0c;死机。 推荐方法案例&#xff1a; 假如搜索wifi列表得到参数是wifi_options&#xff0c;需要通…

OBOO鸥柏丨满天星(MTSTAR)多媒体信息发布系统技术解析

初次启动欢迎您使用鸥柏(OBOO)满天星(MTSTAR)多媒体信息发布系统&#xff0c;在使用本系统的独立服务器模式前&#xff0c;我们需要完成设备的一些必须设置教程技术说明。其总体流程分为两步&#xff1a;录入本地服务器IP地址->连接网络您获取到的OBOO鸥柏满天星(MTSTAR)液晶…

数据结构:栈、队列、链表

目录 栈 ​队列 链表 栈 栈数据结构特点&#xff1a;先入栈的数据后出&#xff0c;此数据结构常用的方法有&#xff1a;入栈push、出栈pop、查看栈顶元素peek等&#xff0c;下方示例以数组实现栈结构。 package com.ginko.datastructure; import lombok.extern.slf4j.Slf4j…

Python-难点-uinttest

1 需求要求&#xff1a;unittest.TestCase放在列表中&#xff0c;列表存储的是脚本文件名import使用动态加载方式&#xff1a;importlib.import_module()unittest.TestLoader使用loadTestsFromModule()2 接口3 示例4 参考资料

开源 python 应用 开发(五)python opencv之目标检测

最近有个项目需要做视觉自动化处理的工具&#xff0c;最后选用的软件为python&#xff0c;刚好这个机会进行系统学习。短时间学习&#xff0c;需要快速开发&#xff0c;所以记录要点步骤&#xff0c;防止忘记。 链接&#xff1a; 开源 python 应用 开发&#xff08;一&#xf…

ABP VNext + OpenTelemetry + Jaeger:分布式追踪与调用链可视化

ABP VNext OpenTelemetry Jaeger&#xff1a;分布式追踪与调用链可视化 &#x1f680; &#x1f4da; 目录ABP VNext OpenTelemetry Jaeger&#xff1a;分布式追踪与调用链可视化 &#x1f680;背景与动机 &#x1f31f;环境与依赖 &#x1f4e6;必装 NuGet 包系统架构概览…

C语言中整数编码方式(原码、反码、补码)

在 C 语言中&#xff0c;原码、反码、补码的运算规则与其编码特性密切相关&#xff0c;核心差异体现在符号位是否参与运算、进位如何处理以及减法是否能转化为加法等方面。以下是三者的运算规则及特点分析&#xff08;以 8 位整数为例&#xff0c;符号位为最高位&#xff09;&a…

js二维数组如何变为一维数组

在 JavaScript 中&#xff0c;将二维数组转换为一维数组&#xff08;扁平化&#xff09;有多种方法&#xff0c;可根据数组结构复杂度、性能需求和兼容性选择。以下是最常用的实现方式&#xff1a; 1. 使用 flat() 方法&#xff08;ES2019&#xff09; MDN释义&#xff1a;flat…

Claude code在Windows上的配置流程

前言 昨天在服务器上配置好了 Claude code&#xff0c;发现其编码性能和效率都非常不错。 然而&#xff0c;尝试用它修改带 UI 界面的客户端程序时颇为不便&#xff0c;因为服务器没有图形化界面&#xff0c;无法直接将应用界面直接显示到开发机上&#xff0c;调试起来颇为不…

手把手教你用YOLOv10打造智能垃圾检测系统

无需编程基础&#xff01;手把手教你用YOLOv10打造智能垃圾检测系统 垃圾分类不再难&#xff0c;AI助手秒识别 你是否曾站在分类垃圾桶前犹豫不决&#xff1f;塑料瓶是可回收还是其他垃圾&#xff1f;外卖餐盒到底该丢哪里&#xff1f;随着垃圾分类政策推广&#xff0c;这样的困…

batchnorm类

1. 伪代码&#xff1a;2. python代码&#xff1a;3. 测试&#xff1a;4. 加深理解&#xff1a;以 为例&#xff0c;x3&#xff0c;可见输出的batchnorm后y0.2627.查看模型记录的均值及方差&#xff0c;计算y0.286799&#xff0c;理解是大致这样的计算过程。&#xff08;为什么数…