This action will force synchronization from Ascend/mindxsdk-referenceapps, which will overwrite any changes that you have made since you forked the repository, and can not be recovered!!!
Synchronous operation will process in the background and will refresh the page when finishing processing. Please be patient.
本章节将指导在SDK自带的图像分类识别样例中挂载自定义proto结构并输出的流程。
在执行本样例前,应已成功远程部署并运行4-1章节的自定义插件样例。
点击跳转代码样例
stream支持挂载特定格式的proto结构体到metadata中并向下传递
必须具备以下结构:
以下为最简化示例,该文件与样例代码中proto相同。
syntax = "proto3";
package sampleproto;
message MxpiMetaHeader
{
string parentName = 1;
int32 memberId = 2;
string dataSource = 3;
}
message MxpiSampleProto
{
repeated MxpiMetaHeader headerVec = 1;
int32 intSample = 2;
string stringSample = 3;
bytes bytesSample = 4;
}
message MxpiSampleProtoList
{
repeated MxpiSampleProto sampleProtoVec = 1;
}
步骤1 准备基础工程
参考4-1插件开发调试指导部署自定义插件样例,示例使用sampleCustomProto作为工程名,远程目录名同样为sampleCustomProto。
部署proto文件夹至工程中,完成后目录结构和项目名称如下:
"outputDataKeys": "mxpi_sampleproto"
,使输出的结果为自定义的proto结构该文件位于样例根目录,但代码中实际指向mxVision/pipeline文件夹下,这是为了与使用原有Sample.pipeline的样例统一目录。实际使用时复制pipeline文件或更改代码中的路径均可
步骤2 添加proto相关文件编译
修改顶层目录的cmakelist.txt,参考如下:
cmake_minimum_required(VERSION 3.6)
project(mxpi_samplecustomproto)
#该语句中%MX_SDK_HOME%根据实际SDK安装位置修改,可通过在终端运行env命令查看
set(ENV{MX_SDK_HOME} %MX_SDK_HOME%)
add_subdirectory("./mxVision/C++")
add_subdirectory("./mindx_sdk_plugin")
add_subdirectory("./proto")
相比4-1样例中的cmakelist仅添加了
add_subdirectory("./proto")
该行内容
完成后右键cmakelist并reload,执行完毕后在远程环境下可看到已在proto目录下生成相关头文件和库(lib目录中)
步骤3 添加自定义proto的赋值 本样例中包含的mindx_sdk_plugin基于4-1样例修改得到,包含以下改动:
第20行添加了指向自定义proto的编译链接
# add custom proto dir
include_directories(${PROJECT_SOURCE_DIR}/../../../proto)
link_directories(${PROJECT_SOURCE_DIR}/../../../proto/lib)
倒数第2行添加了自定义proto库
mxpisampleproto
第24行添加了自定义proto相关头文件
#include "mxpiSampleProto.pb.h"
127-147行为新增一自定义proto结构并赋值后将其加入metadata
// Generate sample proto
auto mxpiSampleProtoListptr = std::make_shared<sampleproto::MxpiSampleProtoList>();
auto mxpiSampleProtoptr = mxpiSampleProtoListptr->add_sampleprotovec();
sampleproto::MxpiMetaHeader* dstMxpiMetaHeaderList = mxpiSampleProtoptr->add_headervec();
dstMxpiMetaHeaderList->set_datasource(parentName_);
dstMxpiMetaHeaderList->set_memberid(0);
mxpiSampleProtoptr->set_intsample(648);
mxpiSampleProtoptr->set_stringsample("sample proton string with id 648");
std::string sampleProtoName = "mxpi_sampleproto";
ret = mxpiMetadataManager.AddProtoMetadata(sampleProtoName, static_pointer_cast<void>(mxpiSampleProtoListptr));
if (ret != APP_ERR_OK) {
ErrorInfo_ << GetError(ret, sampleProtoName) << "MxpiSamplePlugin add metadata failed.";
mxpiErrorInfo.ret = ret;
mxpiErrorInfo.errorInfo = ErrorInfo_.str();
SetMxpiErrorInfo(*buffer, sampleProtoName, mxpiErrorInfo);
return ret;
}
步骤4 运行测试
使用菜单项Build/Rebuild All ....后运行该程序,如果无错误可在输出中看到类似的以下字段
I0720 18:39:36.202248 31340 main.cpp:129] Results:{"MxpiSampleProto":[{"bytesSample":"","intSample":648,"stringSample":"sample proton string with id 648"}]}
修改python样例目录下的run.sh脚本(该脚本用于配置环境变量),确认MX_SDK_HOME环境变量指向正确的位置,自定义插件路径已位于GST_PLUGIN_PATH中,或手动修改环境变量,然后执行程序。正常情况下输出以下类似字段
{"MxpiSampleProto":[{"bytesSample":"","intSample":648,"stringSample":"sample proton string with id 648"}]}
步骤5 取出protobuf数据
本章节提供修改后的main.cpp和main.py代码原文,位于protoRead文件夹下
本步骤讲解如何单独取出自定义的protbuf数据(使用GetProtobuf接口而非GetResult)
在当前clion项目的LD_LIBRARY_PATH环境变量中添加自定义proto库的位置
第31行添加了指向自定义proto的编译链接
# add custom proto dir
include_directories(${PROJECT_SOURCE_DIR}/../../proto)
link_directories(${PROJECT_SOURCE_DIR}/../../proto/lib)
倒数第2行添加了自定义proto库
mxpisampleproto
第20行添加了自定义proto相关头文件
#include "mxpiSampleProto.pb.h"
122-130行替换为以下内容
// choose which metadata to be got.In this case we use the custom "mxpi_sampleproto"
std::vector<std::string> keyVec;
keyVec.push_back("mxpi_sampleproto");
// get stream output
std::vector<MxStream::MxstProtobufOut> output = mxStreamManager.GetProtobuf(streamName, inPluginId, keyVec);
if (output.size() == 0) {
LogError << "output size is 0";
return APP_ERR_ACL_FAILURE;
}
if (output[0].errorCode != APP_ERR_OK) {
LogError << "GetProtobuf error. errorCode=" << output[0].errorCode;
return output[0].errorCode;
}
LogInfo << "key=" << output[0].messageName;
LogInfo << "value=" << output[0].messagePtr.get()->DebugString();
删除145行的
delete output;
此时输出结果应该类似:
I0722 17:58:00.161918 22272 main.cpp:134] key=mxpi_sampleproto
I0722 17:58:00.161969 22272 main.cpp:135] value=sampleProtoVec {
headerVec {
dataSource: "mxpi_modelinfer0"
}
intSample: 648
stringSample: "sample proton string with id 648"
}
如果需要获取protobuf内部数据项,需要执行强制转换,本样例中添加到140行后:
auto protoResList = std::static_pointer_cast<sampleproto::MxpiSampleProtoList>(output[0].messagePtr);
LogInfo << "protobuf stringSample=" << protoResList->sampleprotovec(0).stringsample();
输出类似I0722 19:28:03.550653 28737 main.cpp:141] protobuf stringSample=sample proton string with id 648
import sys
sys.path.append("../../proto")
import mxpiSampleProto_pb2 as mxpiSampleProto
更改数据输入方式为SendData
而非SendDataWithUniqueId
(63行),后者不兼容GetProtobuf
替换67-72行为以下内容
# get protobuf with custom
key_vec = StringVector()
# choose which metadata to be got.In this case we use the custom "mxpi_sampleproto"
key_vec.push_back(b"mxpi_sampleproto")
infer_result = streamManagerApi. \
GetProtobuf(streamName, inPluginId, key_vec)
if infer_result.size() == 0:
print("infer_result is null")
exit()
if infer_result[0].errorCode != 0:
print("infer_result error. \
errorCode=%d" % (infer_result[0].errorCode))
exit()
# print the infer result
print("GetProtobuf errorCode=%d" % (infer_result[0].errorCode))
print("KEY: {}".format(str(infer_result[0].messageName)))
result_protolist = mxpiSampleProto.MxpiSampleProtoList()
result_protolist.ParseFromString(infer_result[0].messageBuf)
print("result: {}".format(
result_protolist.sampleProtoVec[0].stringSample))
输出类似于:
GetProtobuf errorCode=0
KEY: b'mxpi_sampleproto'
result: sample proton string with id 648
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。