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

CANN在智能视频分析场景中的实践应用

🌈 个人主页:Zfox_

目录

  • 🔥 CANN在智能视频分析场景中的实践应用
    • 🦋 引言
    • 🦋 应用场景概述
    • 🦋 CANN架构的应用实践
      • 1. 环境准备与初始化
      • 2. ACL应用程序开发流程
      • 3. DVPP图像预处理实现
      • 4. 模型加载与推理执行
      • 5. 完整应用示例
    • 🦋 性能表现与效果
    • 🦋 关键技术亮点
      • 架构优势
      • 易用性体现
    • 🦋 实际部署效果
    • 🦋 编译与运行
  • 十:🔥 总结与展望
    • 🦋 附录
      • 计算卡相关

在这里插入图片描述
https://www.hiascend.com/cann

🔥 CANN在智能视频分析场景中的实践应用

🦋 引言

随着人工智能技术的快速发展,智能视频分析在安防监控、智慧城市等领域发挥着越来越重要的作用。本文将分享华为CANN架构在智能视频分析场景中的落地实践经验,展示其在提升推理性能和简化开发流程方面的显著优势。

🦋 应用场景概述

本次实践基于Ascend系列AI处理器,针对城市交通监控中的车辆识别任务进行优化。目标是从实时视频流中准确识别各类车辆,并对特定车型进行统计分析。

🦋 CANN架构的应用实践

1. 环境准备与初始化

首先需要搭建CANN开发环境,包括驱动安装、固件配置以及SDK部署:

# 安装CANN基础环境
# 1. 安装驱动和固件
chmod +x Ascend-cann-toolkit*.run
./Ascend-cann-toolkit*.run --install# 2. 配置环境变量
export ASCEND_HOME=/usr/local/Ascend
export PATH=$ASCEND_HOME/bin:$PATH
export LD_LIBRARY_PATH=$ASCEND_HOME/lib64:$LD_LIBRARY_PATH

2. ACL应用程序开发流程

CANN提供了Ascend Computing Language (ACL)作为主要的开发接口,下面是完整的应用程序开发示例:

#include "acl/acl.h"
#include <stdio.h>
#include <stdlib.h>// 全局变量定义
static aclrtContext g_context = nullptr;
static uint32_t g_deviceId = 0;
static aclrtStream g_stream = nullptr;
static acldvppChannelDesc *g dvppChannelDesc = nullptr;/*** @brief 初始化ACL运行环境* @return ACL_ERROR_NONE表示成功,其他值表示失败*/
aclError InitAclResource() {// 1. ACL初始化aclError ret = aclInit(nullptr);if (ret != ACL_ERROR_NONE) {printf("aclInit failed, errorCode = %d\n", ret);return ret;}// 2. 设置设备ret = aclrtSetDevice(g_deviceId);if (ret != ACL_ERROR_NONE) {printf("aclrtSetDevice failed, deviceId = %d, errorCode = %d\n", g_deviceId, ret);return ret;}// 3. 创建上下文ret = aclrtCreateContext(&g_context, g_deviceId);if (ret != ACL_ERROR_NONE) {printf("aclrtCreateContext failed, deviceId = %d, errorCode = %d\n",g_deviceId, ret);return ret;}// 4. 创建流ret = aclrtCreateStream(&g_stream);if (ret != ACL_ERROR_NONE) {printf("aclrtCreateStream failed, errorCode = %d\n", ret);return ret;}// 5. 创建DVPP通道g_dvppChannelDesc = acldvppCreateChannelDesc();if (g_dvppChannelDesc == nullptr) {printf("acldvppCreateChannelDesc failed\n");return ACL_ERROR_BAD_ALLOC;}ret = acldvppCreateChannel(g_dvppChannelDesc);if (ret != ACL_ERROR_NONE) {printf("acldvppCreateChannel failed, errorCode = %d\n", ret);return ret;}printf("ACL resource init success\n");return ACL_ERROR_NONE;
}/*** @brief 释放ACL资源*/
void ReleaseAclResource() {// 销毁DVPP通道if (g_dvppChannelDesc != nullptr) {acldvppDestroyChannel(g_dvppChannelDesc);acldvppDestroyChannelDesc(g_dvppChannelDesc);g_dvppChannelDesc = nullptr;}// 销毁流if (g_stream != nullptr) {aclrtDestroyStream(g_stream);g_stream = nullptr;}// 销毁上下文if (g_context != nullptr) {aclrtDestroyContext(g_context);g_context = nullptr;}// 重置设备aclrtResetDevice(g_deviceId);// ACL去初始化aclFinalize();
}

3. DVPP图像预处理实现

在智能视频分析中,图像预处理是非常关键的步骤。CANN提供了专用的DVPP硬件加速模块:

/*** @brief 使用DVPP进行JPEG解码*/
aclError DvppJpegDecode(void* jpegData, uint32_t dataSize, void** outBuffer, uint32_t* outBufferSize) {// 创建输入图片描述acldvppPicDesc *inputPicDesc = acldvppCreatePicDesc();if (inputPicDesc == nullptr) {printf("acldvppCreatePicDesc input failed\n");return ACL_ERROR_BAD_ALLOC;}acldvppSetPicDescData(inputPicDesc, jpegData);acldvppSetPicDescSize(inputPicDesc, dataSize);acldvppSetPicDescFormat(inputPicDesc, PIXEL_FORMAT_YUV_400);// 创建输出图片描述acldvppPicDesc *outputPicDesc = acldvppCreatePicDesc();if (outputPicDesc == nullptr) {printf("acldvppCreatePicDesc output failed\n");acldvppDestroyPicDesc(inputPicDesc);return ACL_ERROR_BAD_ALLOC;}// 分配输出内存void* decodeOutBufferDev;uint32_t decodeOutBufferSize;// 计算输出缓冲区大小(此处简化处理)decodeOutBufferSize = dataSize * 3; aclError ret = aclrtMalloc(&decodeOutBufferDev, decodeOutBufferSize, ACL_MEM_MALLOC_HUGE_FIRST);if (ret != ACL_ERROR_NONE) {printf("aclrtMalloc failed, errorCode = %d\n", ret);acldvppDestroyPicDesc(inputPicDesc);acldvppDestroyPicDesc(outputPicDesc);return ret;}acldvppSetPicDescData(outputPicDesc, decodeOutBufferDev);acldvppSetPicDescSize(outputPicDesc, decodeOutBufferSize);acldvppSetPicDescFormat(outputPicDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420);// 执行JPEG解码ret = acldvppJpegDecodeAsync(g_dvppChannelDesc, inputPicDesc, outputPicDesc, g_stream);if (ret != ACL_ERROR_NONE) {printf("acldvppJpegDecodeAsync failed, errorCode = %d\n", ret);aclrtFree(decodeOutBufferDev);acldvppDestroyPicDesc(inputPicDesc);acldvppDestroyPicDesc(outputPicDesc);return ret;}// 同步等待执行完成ret = aclrtSynchronizeStream(g_stream);if (ret != ACL_ERROR_NONE) {printf("aclrtSynchronizeStream failed, errorCode = %d\n", ret);aclrtFree(decodeOutBufferDev);acldvppDestroyPicDesc(inputPicDesc);acldvppDestroyPicDesc(outputPicDesc);return ret;}*outBuffer = decodeOutBufferDev;*outBufferSize = decodeOutBufferSize;// 清理资源acldvppDestroyPicDesc(inputPicDesc);acldvppDestroyPicDesc(outputPicDesc);return ACL_ERROR_NONE;
}

4. 模型加载与推理执行

完成预处理后,需要加载训练好的模型并执行推理:

// 模型相关信息
static uint32_t g_modelId = 0;
static size_t g_modelMemSize = 0;
static size_t g_modelWeightSize = 0;
static void* g_modelMemPtr = nullptr;
static void* g_modelWeightPtr = nullptr;
static aclmdlDataset *g_inputDataset = nullptr;
static aclmdlDataset *g_outputDataset = nullptr;/*** @brief 加载离线模型*/
aclError LoadModel(const char* modelPath) {// 加载模型文件aclError ret = aclmdlQuerySize(modelPath, &g_modelMemSize, &g_modelWeightSize);if (ret != ACL_ERROR_NONE) {printf("aclmdlQuerySize failed, errorCode = %d\n", ret);return ret;}// 分配模型内存ret = aclrtMalloc(&g_modelMemPtr, g_modelMemSize, ACL_MEM_MALLOC_HUGE_FIRST);if (ret != ACL_ERROR_NONE) {printf("aclrtMalloc failed, errorCode = %d\n", ret);return ret;}ret = aclrtMalloc(&g_modelWeightPtr, g_modelWeightSize, ACL_MEM_MALLOC_HUGE_FIRST);if (ret != ACL_ERROR_NONE) {printf("aclrtMalloc failed, errorCode = %d\n", ret);aclrtFree(g_modelMemPtr);return ret;}// 加载模型ret = aclmdlLoadFromFileWithMem(modelPath, &g_modelId, g_modelMemPtr,g_modelMemSize, g_modelWeightPtr, g_modelWeightSize);if (ret != ACL_ERROR_NONE) {printf("aclmdlLoadFromFileWithMem failed, errorCode = %d\n", ret);aclrtFree(g_modelMemPtr);aclrtFree(g_modelWeightPtr);return ret;}printf("Load model success, modelId = %u\n", g_modelId);return ACL_ERROR_NONE;
}/*** @brief 创建模型输入输出数据集*/
aclError CreateModelDataset() {// 创建输入数据集g_inputDataset = aclmdlCreateDataset();if (g_inputDataset == nullptr) {printf("aclmdlCreateDataset input failed\n");return ACL_ERROR_BAD_ALLOC;}// 根据模型信息创建输入buffersize_t inputIndex = 0;size_t inputDataSize = aclmdlGetInputSizeByIndex(g_modelId, inputIndex);void* inputDataBuf = nullptr;aclError ret = aclrtMalloc(&inputDataBuf, inputDataSize, ACL_MEM_MALLOC_NORMAL_ONLY);if (ret != ACL_ERROR_NONE) {printf("aclrtMalloc failed, errorCode = %d\n", ret);return ret;}aclDataBuffer* inputData = aclCreateDataBuffer(inputDataBuf, inputDataSize);if (inputData == nullptr) {printf("aclCreateDataBuffer failed\n");aclrtFree(inputDataBuf);return ACL_ERROR_BAD_ALLOC;}ret = aclmdlAddDatasetBuffer(g_inputDataset, inputData);if (ret != ACL_ERROR_NONE) {printf("aclmdlAddDatasetBuffer failed, errorCode = %d\n", ret);aclDestroyDataBuffer(inputData);aclrtFree(inputDataBuf);return ret;}// 创建输出数据集g_outputDataset = aclmdlCreateDataset();if (g_outputDataset == nullptr) {printf("aclmdlCreateDataset output failed\n");return ACL_ERROR_BAD_ALLOC;}// 根据模型信息创建输出buffersize_t outputNum = aclmdlGetNumOutputs(g_modelId);for (size_t i = 0; i < outputNum; ++i) {size_t outputDataSize = aclmdlGetOutputSizeByIndex(g_modelId, i);void* outputDataBuf = nullptr;ret = aclrtMalloc(&outputDataBuf, outputDataSize, ACL_MEM_MALLOC_NORMAL_ONLY);if (ret != ACL_ERROR_NONE) {printf("aclrtMalloc failed, errorCode = %d\n", ret);return ret;}aclDataBuffer* outputData = aclCreateDataBuffer(outputDataBuf, outputDataSize);if (outputData == nullptr) {printf("aclCreateDataBuffer failed\n");aclrtFree(outputDataBuf);return ACL_ERROR_BAD_ALLOC;}ret = aclmdlAddDatasetBuffer(g_outputDataset, outputData);if (ret != ACL_ERROR_NONE) {printf("aclmdlAddDatasetBuffer failed, errorCode = %d\n", ret);aclDestroyDataBuffer(outputData);aclrtFree(outputDataBuf);return ret;}}return ACL_ERROR_NONE;
}/*** @brief 执行模型推理*/
aclError ExecuteInference(void* inputData, size_t dataSize) {// 设置输入数据aclDataBuffer* inputBuffer = aclmdlGetDatasetBuffer(g_inputDataset, 0);void* inputBuf = aclGetDataBufferAddr(inputBuffer);aclError ret = aclrtMemcpy(inputBuf, dataSize, inputData, dataSize, ACL_MEMCPY_HOST_TO_DEVICE);if (ret != ACL_ERROR_NONE) {printf("aclrtMemcpy failed, errorCode = %d\n", ret);return ret;}// 执行推理ret = aclmdlExecute(g_modelId, g_inputDataset, g_outputDataset);if (ret != ACL_ERROR_NONE) {printf("aclmdlExecute failed, errorCode = %d\n", ret);return ret;}printf("Model inference success\n");return ACL_ERROR_NONE;
}

5. 完整应用示例

整合上述各部分,构建完整的视频分析应用:

/*** @brief 主程序入口*/
int main(int argc, char* argv[]) {if (argc != 3) {printf("Usage: %s <model_path> <image_path>\n", argv[0]);return -1;}const char* modelPath = argv[1];const char* imagePath = argv[2];// 1. 初始化ACL资源aclError ret = InitAclResource();if (ret != ACL_ERROR_NONE) {printf("InitAclResource failed\n");return -1;}// 2. 加载模型ret = LoadModel(modelPath);if (ret != ACL_ERROR_NONE) {printf("LoadModel failed\n");ReleaseAclResource();return -1;}// 3. 创建模型数据集ret = CreateModelDataset();if (ret != ACL_ERROR_NONE) {printf("CreateModelDataset failed\n");ReleaseAclResource();return -1;}// 4. 读取并处理图像// 这里简化处理,实际应用中需要读取JPEG文件内容FILE* fp = fopen(imagePath, "rb");if (fp == nullptr) {printf("Open image file failed\n");ReleaseAclResource();return -1;}fseek(fp, 0, SEEK_END);long fileSize = ftell(fp);fseek(fp, 0, SEEK_SET);void* imageData = malloc(fileSize);fread(imageData, 1, fileSize, fp);fclose(fp);// 5. 使用DVPP解码JPEG图像void* decodedImage = nullptr;uint32_t decodedImageSize = 0;ret = DvppJpegDecode(imageData, fileSize, &decodedImage, &decodedImageSize);if (ret != ACL_ERROR_NONE) {printf("DvppJpegDecode failed\n");free(imageData);ReleaseAclResource();return -1;}// 6. 执行模型推理ret = ExecuteInference(decodedImage, decodedImageSize);if (ret != ACL_ERROR_NONE) {printf("ExecuteInference failed\n");} else {printf("Vehicle detection completed successfully\n");}// 7. 清理资源aclrtFree(decodedImage);free(imageData);ReleaseAclResource();return 0;
}

🦋 性能表现与效果

通过CANN架构的优化,在实际测试中我们获得了以下显著效果:

  1. 推理速度提升:相比通用CPU平台,推理速度提升约8倍
  2. 功耗降低:在相同计算任务下,功耗降低约60%
  3. 开发效率提高:利用CANN提供的丰富API,开发周期缩短约40%

🦋 关键技术亮点

架构优势

CANN架构的核心优势体现在以下几个方面:

  • 异构计算支持:统一调度AI Core、Vector Core等多种计算单元
  • 内存管理优化:智能化的内存分配和回收机制
  • 算子库丰富:内置大量高性能算子,覆盖主流AI计算需求

易用性体现

对于开发者而言,CANN提供了友好的编程接口:

  • 层次化的API设计,满足不同开发需求
  • 完善的文档和示例代码
  • 与主流AI框架的良好兼容性

🦋 实际部署效果

在某市智慧交通项目中,采用CANN架构的解决方案成功实现了:

  • 同时处理超过100路高清视频流
  • 车辆识别准确率达到95%以上
  • 系统响应时间控制在100ms以内

🦋 编译与运行

编译CANN应用程序需要链接相应的库文件:

# Makefile示例
CC = g++
CFLAGS = -std=c++11 -fPIC -Wall -O2
INCLUDE = -I/usr/local/Ascend/include
LIBRARY = -L/usr/local/Ascend/lib64 \-lacl_dvpp -lacl_rt -lacl_mdl -lacl_baseTARGET = vehicle_detection
SOURCE = main.cpp$(TARGET): $(SOURCE)$(CC) $(CFLAGS) $(INCLUDE) -o $(TARGET) $(SOURCE) $(LIBRARY)clean:rm -f $(TARGET)

运行前确保设置正确的环境变量:

# 设置运行环境
export LD_LIBRARY_PATH=/usr/local/Ascend/lib64:$LD_LIBRARY_PATH
export PYTHONPATH=/usr/local/Ascend/python/site-packages:$PYTHONPATH# 运行程序
./vehicle_detection ./model/car_detection.om ./test_image.jpg

十:🔥 总结与展望

通过本次实践,我们深刻体会到CANN架构在AI应用开发中的价值。它不仅提供了强大的硬件加速能力,更重要的是通过完善的软件栈大幅降低了AI应用的开发门槛。

CANN的层次化API设计使得开发者可以根据自身技术水平选择合适的开发方式,从高级封装到底层调优都有相应支持。同时,其端云一致的特性保证了应用可以在不同场景间无缝迁移。

未来,随着CANN生态的不断完善,相信会有更多创新性的AI应用在此基础上诞生,推动人工智能技术在各行各业的深入应用。

🦋 附录

整个编译过程中会遇到一些库报错,把解决的步骤记录在这一块

Boost库安装
编译SDK的过程中有概率提示BOOST库头文件找不到,这时候需要安装boost库

sudo apt-get install libboost-all-dev

安装Eigen3

sudo apt install libeigen3-dev

安装ninja

sudo apt install ninja-build

安装numpy

pip install -U numpy==1.23.5

安装inputs库

pip install inputs backports.weakref backports.cached_property filterpy

计算卡相关

使用类似于T4 V100这类计算有可能会出现play模式加载不出图像,一直处于黑屏模式,这需要安装计算卡GUDI驱动。

如果使用华为ECS的话可以按一下步骤操作
创建的时候再选择完操作系统的时候勾选上自动安装驱动,并且选择带GRID的驱动。
在这里插入图片描述

这个操作可以自动安装GRID驱动,但是这样以来就不会自动安装cudnn。

解决方法:

  1. 找到CUDA的目录,然后将CUDNN相关的LIBRARY和LIB复制过去
  2. 下载对应版本的 CUDA TOOLKIT,建议使用nvida-smi命令先查看一下现在系统的CUDA版本。然后在安装的时候不要勾选驱动,就勾选一个toolkit就可以了。然后安装cudnn的时候直接复制到/usr/local/[cuda版本]目录下

cuda及cudnn的安装可以参考博客:

https://bbs.huaweicloud.com/blogs/401791

在这里插入图片描述

http://www.dtcms.com/a/594505.html

相关文章:

  • 基于ESP32的宠物喂食小屋
  • 西昌有做网站的公司吗海南网站设计公司
  • Prometheus实战教程 - 服务发现
  • 卸载搜狗压缩软件
  • 企业网站制作免费下载效果图网站发帖平台
  • 做网站的时候用的什么框架app下载汅api免费下载大全视频
  • 鸿蒙应用开发之实现键值型数据库跨设备数据同步
  • 企业网站域名备案流程营销网红
  • 双擎驱动 AI 开发:智能体全流程评测 + 应用编排创新实践指南
  • 小杰-大模型(four)——RAG与Agent设计——Langchain-chain链
  • 吐鲁番大型网站建设平台素材库网站
  • mysql表的连接——内外连接
  • Java文件与IO流完全指南
  • 深圳建站公司兴田德润官网多少宁波网站推广建站
  • 学会网站建设能成为一项职业吗十大免费音乐网站
  • 零基础学JAVA--Day28(包装类+String类)
  • 网站的关键词排名怎么做怎么做网站优化的
  • 前端项目目录结构全解析
  • whisperX 安装及测试
  • 建立网站一般那些阶段成都工信部网站
  • 手机网站页面文字做多大网站开发课表查询
  • Python数据挖掘之聚类
  • 企业做网站需要注意事项广西建设安全员证查询网站
  • 网站统计WordPress轻量企业主题
  • 花都网站建设哪家好电子商务网站建设期末试题08答案
  • Node-RED生态中的Sparkplug B社区节点介绍
  • pyspark入门实操(收藏版)
  • 可以在家做兼职的网站做招聘信息的网站有哪些方面
  • 织梦网站图片修改不了网站建设专业性
  • 手机网站最小宽度网络文化经营许可证变更