当前位置: 首页 > news >正文

Python OpenCV图像处理与深度学习:Python OpenCV性能优化与高效图像处理

OpenCV性能优化实战

学习目标

本课程将深入探讨如何通过多线程和NPU加速等技术优化OpenCV程序的性能,提高图像处理的速度和效率。通过本课程的学习,学员将能够掌握提升OpenCV应用性能的关键技术,使图像处理程序更加高效。

相关知识点

  • OpenCV性能优化

学习内容

1 OpenCV性能优化

1.1 多线程在OpenCV中的应用

在图像处理领域,多线程技术可以显著提高程序的执行效率,尤其是在处理大量图像数据时。OpenCV提供了多种方法来实现多线程处理,包括使用C++标准库中的std::thread和OpenCV自身的并行处理框架。
多线程技术的基本原理是将一个任务分解成多个子任务,每个子任务由一个独立的线程执行。这样可以充分利用多核处理器的计算能力,提高程序的执行效率。在OpenCV中,可以使用std::thread来创建和管理线程,也可以使用OpenCV的并行处理框架cv::parallel_for_来简化多线程编程。

下面是一个使用std::thread处理图像的简单示例:

#include <opencv2/opencv.hpp>
#include <thread>
#include <vector>void processImage(const cv::Mat& img, cv::Mat& result, int startRow, int endRow) {for (int i = startRow; i < endRow; ++i) {for (int j = 0; j < img.cols; ++j) {result.at<uchar>(i, j) = 255 - img.at<uchar>(i, j); // 简单的图像反转}}
}int main() {cv::Mat img = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);if (img.empty()) {std::cerr << "Could not open or find the image" << std::endl;return -1;}cv::Mat result = cv::Mat::zeros(img.size(), img.type());int numThreads = 4;std::vector<std::thread> threads;int rowsPerThread = img.rows / numThreads;for (int i = 0; i < numThreads; ++i) {int startRow = i * rowsPerThread;int endRow = (i == numThreads - 1) ? img.rows : (i + 1) * rowsPerThread;threads.emplace_back(processImage, std::ref(img), std::ref(result), startRow, endRow);}for (auto& t : threads) {t.join();}cv::imwrite("output.jpg", result);return 0;
}

input.jpg:
在这里插入图片描述
将以上代码复制粘贴到main2.cpp中,然后运行(需要提前安装好g++/opencv等)

g++ main2.cpp -o mycpp2 `pkg-config --cflags --libs opencv4`

在这里插入图片描述

output.jpg:
在这里插入图片描述

1.2 NPU加速技术

昇腾NPU(神经网络处理单元)在图像处理和计算机视觉任务中具有显著优势,其架构专为深度学习和大规模并行计算设计,能够高效处理大量数据。OpenCV可通过与昇腾NPU相关的接口和框架来利用NPU加速图像处理。

与GPU类似,NPU加速的原理是将计算任务从CPU转移到NPU,借助NPU的并行计算能力加速处理。但NPU在架构和优化方向上更贴合深度学习等特定计算任务,能更高效地执行与图像处理相关的深度学习模型推理等操作。

昇腾NPU(神经网络处理单元)是专为深度学习和大规模并行计算设计的硬件加速器。其架构特点包括:

  • 高并行性:NPU拥有大量的计算核心,能够同时处理多个数据流,显著提高计算效率。
  • 专用指令集:NPU针对深度学习任务优化了指令集,能够更高效地执行卷积、矩阵运算等操作。
  • 内存优化:NPU配备了高带宽内存(HBM),减少了数据传输的延迟和能耗。

OpenCV 当前支持 20+ 昇腾算子,此处根据图像处理应用场景,选取 add, rotate 和 flip 算子的应用作示例代码。

#include <iostream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/cann.hpp>
#include <opencv2/cann_interface.hpp>int main(int argc, char* argv[])
{cv::CommandLineParser parser(argc, argv,"{@input|puppy.png|path to input image}""{@output|output.png|path to output image}""{help||show help}");parser.about("This is a sample for image processing with Ascend NPU. \n");if (argc != 3 || parser.has("help")){parser.printMessage();return 0;}std::string imagePath = parser.get<std::string>(0);std::string outputPath = parser.get<std::string>(1);// 读取输入图像cv::Mat img = cv::imread(imagePath);// 生成高斯噪声cv::Mat gaussNoise(img.rows, img.cols, img.type());cv::RNG rng;rng.fill(gaussNoise, cv::RNG::NORMAL, 0, 25);// cann 初始化及指定设备cv::cann::initAcl();cv::cann::setDevice(0);cv::Mat output;// 添加高斯噪声到输入图像cv::cann::add(img, gaussNoise, output);// 旋转图像 (0, 1, 2, 分别代表旋转 90°, 180°, 270°)cv::cann::rotate(output, output, 0);// 翻转图像 (0, 正数, 负数, 分别代表沿 x, y, x 和 y 轴进行翻转)cv::cann::flip(output, output, 0);// 写入输出图像cv::imwrite(outputPath, output);// cann 去初始化cv::cann::resetDevice();cv::cann::finalizeAcl();return 0;
}

这个需要NPU硬件支持,有条件的去试试。

1.3 OpenCV性能优化技巧

除了多线程和NPU加速,还有一些其他的技术和技巧可以用来优化OpenCV程序的性能,例如使用更高效的算法、减少不必要的内存拷贝、使用预分配内存等。

  1. 选择高效的算法:不同的算法在性能上可能有显著差异。例如,使用快速傅里叶变换(FFT)进行图像卷积通常比直接卷积更快。
  2. 减少内存拷贝:频繁的内存拷贝会显著降低程序的性能。尽量使用引用或指针来传递数据,避免不必要的拷贝。
  3. 预分配内存:在处理大量数据时,动态分配内存可能会导致性能瓶颈。预分配足够的内存可以避免频繁的内存分配和释放。

下面是一个减少内存拷贝的示例:

#include <opencv2/opencv.hpp>void processImage(cv::Mat& img) {cv::Mat gray;cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);cv::Mat blurred;cv::GaussianBlur(gray, blurred, cv::Size(5, 5), 0);cv::Mat edges;cv::Canny(blurred, edges, 50, 150);if (img.channels() == 3) {cv::cvtColor(edges, img, cv::COLOR_GRAY2BGR);} else {img = edges.clone();}
}int main() {cv::Mat img = cv::imread("input.jpg");if (img.empty()) {std::cerr << "Could not open or find the image" << std::endl;return -1;}processImage(img);cv::imwrite("output.jpg", img);return 0;
}

在这里插入图片描述
瞬间执行完:
在这里插入图片描述

http://www.xdnf.cn/news/1428193.html

相关文章:

  • 为什么神经网络网络算法比机器学习模型算法更加强大?
  • 关于嵌入式学习——嵌入式硬件1
  • More Effective C++ 条款23:考虑使用其他程序库
  • 没有天硕工业级SSD固态硬盘,物联网痛点如何解决?
  • 虚实交互新突破:Three.js融合AR技术的孪生数据操控方法
  • Angular事件处理全攻略:从基础到进阶的完整指南
  • JSON Schema 格式详解、版本介绍和示例教程
  • 利用 Python 获取微店商品详情 API 接口数据的实战指南
  • 最新!阿里财报电话会蒋凡与吴泳铭透露重要信息:淘宝闪购成绩斐然;零售与AI双轮驱动;阿里云推出“Agent Bay”新产品···
  • 【学Python自动化】 8.1 Python 与 Rust 错误处理对比学习笔记
  • Spring Security资源服务器在高并发场景下的认证性能优化实践指南
  • 使用DataLoader加载本地数据
  • 深度学习——基于卷积神经网络实现食物图像分类(数据增强)
  • JVM1.8与1.9的区别是什么?
  • 【系统架构设计(11)】软件测试全景解析:从方法论到实践策略
  • 面试tips--JVM(4)--Minor GC Major GC Full GC
  • STL库——deque/priority_queue
  • 【爬油管搜索视频软件】youtube爬虫工具,根据关键词采集搜到的视频数据
  • 数据分析与挖掘工程师学习规划
  • React学习教程,从入门到精通, React 入门指南:React JSX 语法知识点详解及案例代码(8)
  • 工业界实战之数据存储格式与精度
  • MySQL 事务隔离与 MVCC
  • MySQL事务+MVCC(精简版,包教包废)
  • 【彻底搞懂Java垃圾回收机制(附调优参数)】
  • 从电脑底层到进程创建:一篇看懂冯诺依曼、OS和进程
  • 【Qt开发】按钮类控件(二)-> QRadioButton
  • 【译】更好地控制您的 Copilot 代码建议
  • ResponseBodyEmitter介绍
  • Linux IPv4路由子系统深度解析
  • 什么是Token?——理解自然语言处理中的基本单位