模型推理
抠图贴图
功能介绍
对输入的图像进行抠图并粘贴到背景图片中的操作,输出到Image对象中。
接口调用流程
使用抠图贴图接口前,用户需准备好被抠图以及被粘贴的图片对象。
图1 图像处理(抠图贴图)接口调用流程

关键步骤说明如下:
-
调用MxInit()接口进行全局初始化。
-
ImageProcessor初始化。
用户构造ImageProcessor对象,之后可以调用InitVpcChannel()初始化通道,若不调用该接口,ImageProcessor会在执行抠图并贴图前自动进行通道初始化。
-
使用图片解码接口对输入图片进行解码。
根据业务对图片进行解码,生成可抠图贴图的Image对象。后续可以通过图像处理接口对图片进行处理,生成最终需要抠图贴图的Image对象。
-
构造抠图贴图参数和输出Image。
- 根据业务要求,设置被抠图片的矩阵并设置粘贴图片位置的矩阵,二者大小不一样时将自动进行缩放。
- 构造输出图片的背景图片,使用预申请内存的Image()构造函数构造被粘贴图片或其他非空图片作为输出。
-
调用CropAndPaste()对输入图片进行抠图并将图片粘贴至指定位置。
- 同步执行。
- 不创建Stream,将输入图片及其他参数传入接口,获取抠图贴图结果。
- 异步执行。
- 创建Stream,具体请参见异步调用。
- 将输入图片、已创建的Stream及其他参数传入接口,获取抠图贴图结果。
- 调用MxDeInit()接口对初始化的全局资源进行去初始化。
- 同步执行。
示例代码
以下为功能特性关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
//初始化
MxInit();
{
//构造图像处理类
ImageProcessor imageProcessor(deviceId);
//图像解码生成Image
//解码后的图像类
Image decodedImage;
//根据图像路径进行解码
APP_ERROR ret = imageProcessor.Decode(imagePath, decodedImage);
if (ret != APP_ERR_OK) {
return 0;
}
//(可选)初始化图像处理通道
imageProcessor.InitVpcChannel();
//构造背景Image(也可以选择其他已有数据的Image对象)
Size imageSize(640, 640);
size_t dataSize = 640 * 640 * 3 / 2;
MemoryData imgData(dataSize, MemoryData::MemoryType::MEMORY_DVPP, deviceId);
if (MemoryHelper::Malloc(imgData) != APP_ERR_OK) {
return 0;
}
std::shared_ptr<uint8_t> pastedData((uint8_t*)imgData.ptrData, imgData.free);
/ 抠图贴图操作后图像类
Image pastedImage(pastedData, dataSize, deviceId, imageSize);
//执行抠图贴图
//抠图和贴图尺寸
Rect rectFrom(0, 0, 240, 240);
Rect rectTo(0, 0, 480, 480);
std::pair<Rect, Rect> cropPasteRect = {rectFrom, rectTo};
//抠图贴图操作
ret = imageProcessor.CropAndPaste(resizeImage, cropPasteRect, pastedImage) ;
if (ret != APP_ERR_OK) {
return 0;
}
}
//去初始化
MxDeInit();
父主题: 通过接口进行图像处理(Image)
视频编码
功能介绍
通过构造VideoEncoder类实例可实现视频编码功能,编码功能配置项及各项约束与支持情况请参考VideoEncodeConfig数据结构说明。
视频编码支持自定义输出数据格式,通过自定义回调函数传入编码功能配置项,方便用户使用编码后的数据,详情可参考VideoEncodeCallBack。
接口调用流程
首先根据需求定义需要的输出数据组合方式,根据组合方式参考VideoEncodeCallBack定义回调函数传入编码功能配置项,然后实例化VideoEncoder类,最后调用Encode成员函数完成编码,获取数据。
视频编码接口调用流程参考如下:
图1 视频编码接口调用流程

mxVision提供VideoEncoder类进行视频编码,关键步骤说明如下:
-
调用MxInit()接口进行全局初始化。
-
定义输出数据组合形式。
- 输出数据包含视频帧编码后得到的的Image类数据、当前编码帧的“frameId”和通道“channelId”。
- 根据需要选择获取以上哪些数据。
-
定义输出回调函数。
-
根据要获取的数据定义回调函数,在函数内组装自定义数据。
-
回调函数输入参数固定为VideoEncodeCallBack形式,函数内可选择输出。
请勿在回调函数内实现过于复杂的操作,建议使用自定义“userData”来接收视频编码回调结果,否则回调线程会发生卡住的现象,导致视频编码速度变慢。
-
-
构造视频编码配置项。
配置项及各项约束与支持情况请参考VideoEncodeConfig数据结构说明。
-
实例化视频编码类。
将配置好的VideoEncodeConfig传入构造函数接口,实例化视频编码类。
-
调用MxDeInit()接口对初始化的全局资源进行去初始化。
示例代码
如下提供关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
// 初始化
MxBase::MxInit();
{
// 定义要接收的编码数据
struct FrameImage {
Image image; // Video Image Class
uint32_t frameId = 0; // Video Frame Index
uint32_t channelId = 0; // Video Channel Index
};
// 定义获取编码数据到自定义结构的回调函数
APP_ERROR CallBackVenc(std::shared_ptr<uint8_t>& outDataPtr, uint32_t& outDataSize, uint32_t& channelId,
uint32_t& frameId, void* userData)
{
Image image(outDataPtr, outDataSize, -1, Size(1920, 1080));
FrameImage* encodedVec = static_cast<FrameImage*>(userData);
FrameImage frameImage;
encodedVec.image = image;
encodedVec.channelId = channelId;
encodedVec.frameId = frameId;
return APP_ERR_OK;
}
// 构造编码配置项
VideoEncodeConfig vEncodeConfig;
VideoEncodeCallBack cPtr2 = CallBackVenc;
vEncodeConfig.callbackFunc = cPtr2;
vEncodeConfig.width = 1920;
vEncodeConfig.height = 1080;
vEncodeConfig.keyFrameInterval = 1;
vEncodeConfig.srcRate = 30;
vEncodeConfig.rcMode = 1;
vEncodeConfig.maxBitRate = 30000;
vEncodeConfig.ipProp = 70;
// 实例化编码类
VideoEncoder videoEncoder(vEncodeConfig, deviceId);
// 执行编码操作
FrameImage encodedFrame;
for (size_t i = 0; i < inputFrameList.size(); i++) {
ret = videoEncoder.Encode(image, frameId, &encodedFrame);
}
}
// 去初始化
MxBase::MxDeInit();
父主题: 媒体数据处理
视频解码
功能介绍
通过构造VideoDecoder类实例可实现视频解码功能,解码功能配置项及各项约束与支持情况请参考VideoDecodeConfig数据结构说明。
视频解码支持自定义输出数据格式,通过自定义回调函数传入解码功能配置项,方便用户解码后的数据,详情可参考VideoDecodeCallBack数据结构说明。
接口调用流程
首先根据需求定义需要的输出数据组合方式,根据组合方式参考VideoDecodeCallBack定义回调函数传入解码功能配置项,然后实例化VideoDecoder类,最后调用Decode成员函数完成解码,获取数据。
视频解码接口调用流程参考如下:
图1 视频解码接口调用流程

mxVision提供VideoDecoder类进行视频解码,关键步骤说明如下:
-
调用MxInit()接口进行全局初始化。
-
定义输出数据组合形式。
- 输出数据包含视频帧解码后得到的的Image类数据、当前解码帧的“frameId”和通道“channelId”。
- 可根据需要选择获取以上哪些数据。
-
定义输出回调函数。
- 根据要获取的数据定义回调函数,在函数内组装自定义数据。
- 回调函数输入参数固定为VideoDecodeCallBack形式,函数内可选择输出。
- 请勿在回调函数内实现过于复杂的操作,建议只进行自定义获取解码数据操作。
-
构造视频解码配置项。
配置项及各项约束与支持情况请参考VideoDecodeConfig数据结构说明。
-
实例化视频解码类。
将配置好的VideoDecodeConfig传入构造函数接口,实例化视频解码类。
-
调用解码接口。
- 一个实例化的解码器在首次调用Decode接口时,会判断是否为预申请场景。
- 使用预申请场景时,需要在后续调用Decode接口进行预申请输出内存,防止接口调用失败。
-
调用MxDeInit()接口对初始化的全局资源进行去初始化。
示例代码
如下提供关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
// 初始化
MxBase::MxInit();
{
// 定义要接收的解码数据
struct FrameImage {
Image image; // Video Image Class
uint32_t frameId = 0; // Video Frame Index
uint32_t channelId = 0; // Video Channel Index
};
//定义获取解码数据到自定义结构的回调函数
APP_ERROR CallBackVdec(Image& decodedImage, uint32_t channelId, uint32_t frameId, void* userData)
{
FrameImage* decodedVec = static_cast<FrameImage*>(userData);
decodedVec->image = decodedImage;
decodedVec->channelId = channelId;
decodedVec->frameId = frameId;
}
// 构造解码配置项
VideoDecodeConfig config;
VideoDecodeCallBack cPtr = CallBackVdec;
config.width = 1920;
config.height = 1080;
config.callbackFunc = cPtr;
config.skipInterval = 0;
config.inputVideoFormat = StreamFormat::H264_MAIN_LEVEL;
config.outputImageFormat = ImageFormat::YUV_SP_420;
// 实例化解码类
VideoDecoder videoDecoder(config, deviceId, channelId);
// 执行解码操作
ret = videoDecoder.Decode(dataPtr, dataSize, frameId, &decodedFrame);
}
// 去初始化
MxBase::MxDeInit();
父主题: 媒体数据处理
模型推理
功能介绍
使用mxVision模型推理功能通过给定输入和指定模型,进行推理获得输出结果,支持om格式的模型推理,可使用ATC工具构建的动态Batch、动态分辨率和分档动态维度模型进行推理。
接口调用流程
使用模型推理前,用户需准备好输入数据以及需要加载的模型,根据模型路径或者内存方式初始化Model类,通过调用Model类的Infer接口获取模型推理结果。输入数据必须和模型输入数据类型以及格式一致,如果用户自行申请输出数据内存,则输出数据类型和格式需和模型输出保持一致,模型输入输出信息可以通过Model类的相关接口进行查询。
模型推理调用流程参考如下:
关键接口说明如下:
-
调用MxInit()接口进行全局初始化。
-
模型初始化。
用户需根据实际业务情况确认模型加载方式,选择从文件加载模型或从内存加载模型。如果从内存加载,需要先将模型文件读取到内存,可通过以下两种方式传入。
- 从文件加载模型,可选择直接向Model接口传入模型路径,进行初始化。
- 通过结构体ModelLoadOptV2中的“loadType”字段指定加载方式后,再传入Model接口,其中加载方式在模型方面区分从文件加载模型,还是从内存加载模型,在内存方面区分是由系统内部管理,还是由用户管理,具体可参见ModelLoadOptV2。
-
调用MxDeInit()接口对初始化的全局资源进行去初始化。
示例代码
以下为功能特性关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
// 初始化
MxBase::MxInit();
{
// 输入二进制数据, 需用户自行准备
std::string filePath = "./test.bin";
// 读取输入数据到内存
void* dataPtr = ReadTensor(filePath);
// 输入数据类型,和模型输入数据类型一致
auto dataType = MxBase::TensorDType::INT32;
// 构造输入shape,和模型输入shape一致
std::vector<uint32_t> shape = {1, 128};
// 构造tensor
MxBase::Tensor tensor(dataPtr, shape, dataType, 0);
// 构造模型输入
std::vector<MxBase::Tensor> inputs{tensor};
// 模型路径,需用户自行指定
std::string modelPath = "./test.om";
// 根据模型路径加载模型
MxBase::Model model(modelPath);
// 执行模型推理, outputs即为推理结果
std::vector<MxBase::Tensor> outputs = model.Infer(inputs);
}
//去初始化
MxBase::MxDeInit();
根据结构体ModelLoadOptV2方式初始化示例参考如下:
MxBase::ModelLoadOptV2 mdlLoadOpt;
mdlLoadOpt.loadType = ModelLoadOptV2::LOAD_MODEL_FROM_FILE; // 指定模型加载方式
mdlLoadOpt.modelPath = modelPath;
MxBase::Model model(mdlLoadOpt);
父主题: 使用API接口方式开发(C++)
异步调用
功能介绍
mxVision默认采用同步执行模式,部分接口已支持用户通过申请AscendStream异步执行,具体接口异步支持情况请参见API参考(C++)。
接口调用流程
- 用户通过自定义AscendStream类构造需要的Stream实例传入异步接口,通过接口传入并在指定Stream上执行,同一Stream串行指定接口任务后可通过调用Synchronize()接口阻塞应用程序或线程运行,直到该Stream中的所有任务全部完成。
- 支持多Stream异步执行,每个Stream内接口顺序执行,如果用户使用多Stream异步执行或异步执行结果需传入不支持异步接口情况,需要用户可选择执行Synchronize()接口,在适当位置执行同步Stream操作,保证结果已正确返回供后续使用。
- 对于异步调用进行媒体数据处理时,需要调用Synchronize()接口使异步任务完成才能及时归还使用的通道,避免资源池被耗尽。
图1 Stream异步模式接口调用流程(以Resize操作为例)

mxVision提供AscendStream类进行Stream管理,关键步骤说明如下:
-
调用MxInit()接口进行全局初始化。
-
初始化Stream。
用户通过向构造函数传入“deviceId”指定要创建Stream的设备,支持的“deviceId”根据用户环境存在差异。
-
创建Stream。
- 与Stream初始化绑定使用,在使用Stream前需要调用CreateAscendStream()成员函数完成Stream创建。
- 同一设备(deviceId),Stream最大支持创建1021个,具体请参见《CANN AscendCL应用软件开发指南 (C&C++)》。
-
调用异步接口。
- 支持异步的接口传入指定Stream,同一Stream中接口按顺序串行执行。
- 指定不同Stream的接口之间并行执行。
-
同步Stream。
如需保证异步执行结果在作为下一个接口入参时已执行完成,可调用Synchronize()成员函数显式同步Stream。
-
销毁Stream。
用户在业务流程完成或Stream结束时,需调用DestroyAscendStream()成员函数销毁Stream,否则可能会造成Stream耗尽情况。
-
调用MxDeInit()接口对初始化的全局资源进行去初始化。
示例代码
以图像异步缩放和yoloV3模型异步推理为例,提供关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
// 初始化
MxBase::MxInit();
{
// 用户创建目标deviceId的stream
AscendStream stream(deviceId)
stream.CreatAscendStream();
// 创建图像解码类实例
ImageProcessor imageProcessor(deviceId);
// 解码后的Image类实例
Image decodedImage;
// 根据图像路径进行解码
APP_ERROR ret = imageProcessor.Decode(imagePath, decodedImage);
// 缩放后的图像类实例
Image resizedImage;
// 异步调用缩放接口
ret = imageProcessor.Resize(decodedImage, Size(416, 416), resizedImage, Interpolation::HUAWEI_HIGH_ORDER_FILTER, stream);
// 调用同步接口,可以显式保证调用后续接口时缩放已完成
stream.Synchronize();
// 将 Image 类转换为 Tensor 类
Tensor tensorImg = resizedImage.ConvertToTensor();
// yoloV3模型推理
string yoloPath = "./model/yolov3_tf_bs1_fp16.om";
Model yoloV3(yoloPath, deviceId);
// 构造推理输入输出 (单batch)
vector<Tensor> yoloV3Inputs = {tensorImg};
vector<Tensor> yoloV3Outputs = {};
// 开始异步推理
ret = yoloV3.Infer(yoloV3Inputs, yoloV3Outputs,stream);
// 调用同步接口,可以显式保证调用后续接口时缩放已完成
// 用户也可选择同步前在该stream串行其他异步接口
stream.Synchronize();
// 调用DestroyAscendStream销毁stream
stream.DestroyAscendStream();
}
//去初始化
MxBase::MxDeInit();
父主题: 使用API接口方式开发(C++)
编译运行
运行样例前,需设置mxVison环境变量。
source {mxVison安装目录}/mxVision/set_env.sh
编译
-
文件准备,用户准备好自己的源码文件“main.cpp”,以及“CMakeLists.txt”文件,“CMakeLists.txt”编写可参考如下内容:
# CMake lowest version requirementcmake_minimum_required(VERSION 3.5.2)# project informationproject(MindX_SDK_Sample)set(MX_SDK_HOME $ENV{MX_SDK_HOME})if (NOT DEFINED ENV{MX_SDK_HOME})string(REGEX REPLACE "(.*)/(.*)/(.*)/(.*)" "\\1" MX_SDK_HOME ${CMAKE_CURRENT_SOURCE_DIR})message(STATUS "set default MX_SDK_HOME: ${MX_SDK_HOME}")else ()message(STATUS "env MX_SDK_HOME: ${MX_SDK_HOME}")endif()# Compile optionsadd_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)add_definitions(-Dgoogle=mindxsdk_private)add_compile_options(-std=c++11 -fPIC -fstack-protector-all -Wall)set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})set(CMAKE_CXX_FLAGS_DEBUG "-g")set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro,-z,now,-z,noexecstack -s -pie")set(CMAKE_SKIP_RPATH TRUE)# add mxbase header pathinclude_directories(${MX_SDK_HOME}/include/${MX_SDK_HOME}/opensource/include/)# add mxbase lib pathlink_directories(${MX_SDK_HOME}/lib/${MX_SDK_HOME}/lib/modelpostprocessors/${MX_SDK_HOME}/opensource/lib/${MX_SDK_HOME}/opensource/lib64/)add_executable(main main.cpp)target_link_libraries(main glog mxbase opencv_world cpprest pthread mindxsdk_protobuf)install(TARGETS main DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -
CMake编译。
-
在“CMakeLists.txt”文件所在目录新建“build”目录。
mkdir build -
进入“build”目录。
cd build -
执行cmake命令。
cmake .. -
执行make命令生成可执行文件“main”。
make -j
-
运行
执行编译生成的可执行文件即可运行程序。
./main
:::note 说明
- 若程序执行出现libascendcl.so报错,请参见程序执行出现libascendcl.so报错解决。
- 若尝试打印Device侧的Tensor、Image内存数据时出现coredump提示,请参见尝试打印Device侧的Tensor、Image内存数据时,发生coredump解决。 :::
父主题: 使用API接口方式开发(C++)
开发流程
流程介绍
图1 API开发流程

关键步骤说明
- 使用mxVision接口进行应用开发,需首先进行初始化才能进行后续处理,具体请参见初始化。
- 媒体数据处理/模型推理。
父主题: 使用API接口方式开发(Python)
在线提单