-
我在用点云的onnx模型向om模型转换的时候,转换报错:Input shape digit should be -1 or greater than 0。我看文档说onnx模型转换shape是NCHW,而我的onnx模型是(15000,5),因为是点云模型,不需要NCHW,请问这种情况该怎么处理?
-
详细情况如下:1、在SD卡模式下,RGMII网络能正常访问。2、在SD卡模式下,短接uart1,RGMII网络不通3、把硬件从SD卡模式切换到EMMC模式,并短接uart1 RGMII网络还是不通4、模组已升级(指定版本):https://support.huawei.com/enterprise/zh/software/252823273-ESW2000337766https://support.huawei.com/enterprise/zh/software/251857128-ESW2000262521
-
使用官方教程中的脚本,尝试MindSpore上云时,报错如图:
-
MindX SDK——Overlap-CRNN重叠文本识别设计案例1 案例概述本开发样例使用CRNN完成重叠文本的识别任务,供用户参考。 本系统基于昇腾Ascend310卡。本仓库是重叠文本任务的下游任务,即在完成对重叠文本还原后针对mask识别出文本。1.1 支持的产品本系统采用Atlas300-3010作为实验验证的硬件平台,并支持Atlas200RC以及Atlas500的硬件平台.具体产品实物图和硬件参数请参见《Atlas 300 AI加速卡 用户指南(型号 3010)》。由于采用的硬件平台为含有Atlas 300的Atlas 800 AI服务器 (型号3010),而服务器一般需要通过网络访问,因此需要通过笔记本或PC等客户端访问服务器,而且展示界面一般在客户端。1.2 支持的版本版本号查询方法,在Ascend产品环境下,运行命令:npu-smi info1.3 软件方案介绍软件方案主要为还原文本的识别系统,子系统功能具体描述请参考 表1.1 系统方案各子系统功能描述。重叠文本识别子系统可以实现识别还原后图像的mask的输入,然后通过等比例放缩等操作最后对图像进行识别,本方案选择使用crnn作为重叠文本识别模型。系统方案中各模块功能如表1.2 所示。表1.1 系统方案各子系统功能描述:序号子系统功能描述1重叠文本识别子系统重叠文本识别子系统将上一个子系统得到的结果,进行等比例放缩操作,放缩的大小与模型的输入大小有关,之后将结果送入到文字识别模型进行文字识别,并将识别结果进行输出。表1.2 系统方案中各模块功能:序号子系统功能描述1输入图像将图像(JPG格式)通过pillow库读入。2输入字典将字典(txt格式)通过本地代码输入到pipeline中。3图像解码通过PILLOW第三方库对图像解码。4图像放缩文字识别模型的输入为固定维度,所以需要放射变换的结果进行等比例放缩。5文字识别在图像放缩后,将缓存区数据送入文字识别模型。本方案选用crnn进行文本识别6结果可视化通过pillow库可视化单张图像的识别。1.4 代码目录结构与说明eg:本sample工程名称为Overlap-CRNN,工程目录如下图所示:├── crnn_single_infer.py #单张图片推理 ├── crnn_infer.py #精度测试 ├── README.md ├── ch_sim_en_digit_symble.txt #字典 ├── models #不同类型的模型文件 │ ├── air_model │ │ ├── crnn.air │ └── ckpt_model │ │ ├── crnn.ckpt │ └── om_model │ │ ├── crnn.om ├── dataset #测试数据集 │ ├── img │ ├── map_record.json │ └── annotation.json1.5 技术实现流程图实现流程图如下图所示:1.6 特性及适用场景本案例中的 CRNN模型适用于英文的灰度图像的识别,并可以返回测试图像的word-based的精度值。本模型在以下几种情况去噪效果良好:图像中文字清晰可见、排版工整、字符大小适中等。在以下几种情况去噪效果不太好:图像中文字模糊、排版随意、字符较小等。1.7 代码地址本项目的代码地址为:cid:link_32 环境依赖请列出环境依赖软件和版本。推荐系统为ubuntu 18.04或centos 7.6,环境依赖软件和版本如下表:软件名称版本mindspore1.8.1MindX SDK3.0RC2Ascend-CANN-toolkit5.1.RC2ubuntu18.04.1 LTSpython3.9.2cv24.5.5.64numpy1.23.1pillow9.1.0在编译运行项目前,需要设置环境变量:环境变量介绍. ${sdk_path}/set_env.sh . ${ascend_toolkit_path}/set_env.sh3 模型训练模型均在GPU下训练得到,如果需要使用本仓库提供的模型进行推理或模型转换,请务必参照GPU所需的参数设置,然后将模型按照提供的文件夹目录放至即可。相关模型的下载链接如下:[下载链接]cid:link_1)步骤1 从昇腾社区的modelzoo中下载官方CRNN模型代码,并按安装官方文档中的步骤完成训练:下载链接CRNN_for_MindSpore_1.2_code/default_config.yamlmodel_version: "V2" # V2可以在GPU和Ascend上训练 label_dict: "PATH/TO/ch_sim_en_digit_symble.txt" # 使用自己的字典的路径 max_text_length: 12 image_width: 112 class_num: 6703 blank: 6702 train_dataset_path: "" # 训练数据集路径 train_eval_dataset: "synth" # 名称使用synth train_eval_dataset_path: "" # 测试数据路径CRNN_for_MindSpore_1.2_code/src/dataset.py将第41行的:letters = [letter for letter in config1.label_dict]修改为:letters = [] with open(config1.label_dict, 'r') as f: for line in f: letter = line.strip('\n') letters.append(letter) f.close()将CaptchaDataset函数更换为:class CaptchaDataset: """ create train or evaluation dataset for crnn Args: img_root_dir(str): root path of images max_text_length(int): max number of digits in images. device_target(str): platform of training, support Ascend and GPU. """ def __init__(self, img_root_dir, is_training=True, config=config1): if not os.path.exists(img_root_dir): raise RuntimeError( "the input image dir {} is invalid!".format(img_root_dir)) self.img_root_dir = img_root_dir if is_training: self.imgslist = os.path.join(self.img_root_dir, 'annotation_train.txt') else: self.imgslist = os.path.join(self.img_root_dir, 'annotation_test.txt') self.img_names = {} self.img_list = [] with open(self.imgslist, 'r') as f: for line in f: img_name, img_label = line.strip('\n').split('\t') self.img_list.append(img_name) self.img_names[img_name] = str(img_label) f.close() self.max_text_length = config.max_text_length self.blank = config.blank self.class_num = config.class_num self.sample_num = len(self.img_list) self.batch_size = config.batch_size print("There are totally {} samples".format(self.sample_num)) def __len__(self): return self.sample_num def __getitem__(self, item): img_name = self.img_list[item] try: im = Image.open(os.path.join(self.img_root_dir, img_name)) except IOError: print("%s is a corrupted image" % img_name) return self[item + 1] im = im.convert("RGB") r, g, b = im.split() im = Image.merge("RGB", (b, g, r)) image = np.array(im) if not check_image_is_valid(image): print("%s is a corrupted image" % img_name) return self[item + 1] text = self.img_names[img_name] label_unexpanded = text_to_labels(text) label = np.full(self.max_text_length, self.blank) if self.max_text_length < len(label_unexpanded): label_len = self.max_text_length else: label_len = len(label_unexpanded) for j in range(label_len): label[j] = label_unexpanded[j] return image, labelCRNN_for_MindSpore_1.2_code/src/metric.py将第18行的字典label_dict = "abcdefghijklmnopqrstuvwxyz0123456789"修改为( dict_path 为自行准备的字典 ch_sim_en_digit_symble.txt ,可在本仓库下找到):label_dict = [] with open("[dict_path]", 'r') as f: for line in f: letter = line.strip('\n') label_dict.append(letter) f.close()步骤2 训练得到ckpt模型文件后,进入CRNN_for_MindSpore_1.2_code文件夹下执行命令(修改ckpt_file和air_file_name参数为自己的路径):python export.py --ckpt_file [ckpt_file] --file_name [air_file_name] --file_format AIR4 模型推理步骤1 将生成的AIR模型转移到推理服务器,放至在Overlap-CRNN/models/air_model路径下。cd ./Overlap-CRNN mkdir models cd models mkdir air_model步骤2 进入推理服务器执行命令(修改air_model_path和output_model_path参数为自己的路径):atc --model=[air_model_path] --framework=1 --output=[output_model_path] --soc_version=Ascend310 --output_type=FP32 --op_select_implmode=high_precision --input_shape="input:1,3,32,112"模型转换工具(ATC)相关介绍如下:ATC介绍相关模型的下载链接如下:模型下载步骤3 执行该命令会在当前目录下生成项目需要的模型文件[output_model].om。执行后终端输出为:ATC start working now, please wait for a moment. ATC run success, welcome to the next use.表示命令执行成功。步骤4 将任意一张jpg格式的图片存到当前目录下(./Overlap-CRNN),命名为test.jpg。步骤5 按照模型转换获取om模型,放置在Overlap-CRNN/models/om_model/路径下。若未自行转换模型,使用的是仓库提供的模型,则无需修改相关文件,否则修改crnn_single_infer.py中相关配置,将MODEL_PATH对象的路径改成实际的om模型的路径;IMAGE_PATH对象的路径改成实际的测试图片的路径;SAVE_PATH对象设置成需要保存可视化图像的路径。相关参数在Overlap-CRNN/crnn_single_infer.py下:MODEL_PATH = "./models/om_model/crnn.om" IMAGE_PATH = "./test.jpg" SAVE_PATH = "./show.jpg"步骤6 在命令行输入 如下命令运行整个工程:python crnn_single_infer.py步骤7 运行结束输出show.jpg5 测试精度步骤1 在Overlap-CRNN/dataset/路径下准备相同格式的数据集(已提供测试用的数据集,按照文件目录放至即可:下载链接)步骤2 在命令行输入 如下命令运行整个工程:python crnn_infer.py模型在测试集上的精度达标,最终模型的的acc为89.17%,满足精度要求(acc≥80%)。
-
使用的是mindspore1.7版本源代码为
-
bilibili视频链接:使用MindStudio开发基于MindX SDK的X射线图像缺陷检测应用9、本地编写python文件1、main.pymain.py主要进行一些推理前的操作和调用infer.py进行推理,以及调用postprocess.py进行推理结果后处理。步骤一:导入相关包,并定义相关函数步骤二:编写各个函数parser_args函数用于读入执行改文件时所需的一些参数def parser_args(): parser = argparse.ArgumentParser(description="FasterRcnn inference") parser.add_argument("--img_path", type=str, required=False, default="../data/test/crop/", help="image directory.") parser.add_argument( "--pipeline_path", type=str, required=False, default="../pipeline/fasterrcnn_ms_dvpp.pipeline", help="image file path. The default is 'config/maskrcnn_ms.pipeline'. ") parser.add_argument( "--model_type", type=str, required=False, default="dvpp", help= "rgb: high-precision, dvpp: high performance. The default is 'dvpp'.") parser.add_argument( "--infer_mode", type=str, required=False, default="infer", help= "infer:only infer, eval: accuracy evaluation. The default is 'infer'.") parser.add_argument( "--infer_result_dir", type=str, required=False, default="../data/test/infer_result", help= "cache dir of inference result. The default is '../data/test/infer_result'.") parser.add_argument("--ann_file", type=str, required=False, help="eval ann_file.") arg = parser.parse_args() return argget_img_metas函数用于记录图像缩放比例def get_img_metas(file_name): img = Image.open(file_name) img_size = img.size org_width, org_height = img_size resize_ratio = cfg.MODEL_WIDTH / org_width if resize_ratio > cfg.MODEL_HEIGHT / org_height: resize_ratio = cfg.MODEL_HEIGHT / org_height img_metas = np.array([img_size[1], img_size[0]] + [resize_ratio, resize_ratio]) return img_metasprocess_img函数用于对图像进行预处理def process_img(img_file): img = cv2.imread(img_file) model_img = mmcv.imrescale(img, (cfg.MODEL_WIDTH, cfg.MODEL_HEIGHT)) if model_img.shape[0] > cfg.MODEL_HEIGHT: model_img = mmcv.imrescale(model_img, (cfg.MODEL_HEIGHT, cfg.MODEL_HEIGHT)) pad_img = np.zeros( (cfg.MODEL_HEIGHT, cfg.MODEL_WIDTH, 3)).astype(model_img.dtype) pad_img[0:model_img.shape[0], 0:model_img.shape[1], :] = model_img pad_img.astype(np.float16) return pad_imgcrop_on_slide函数用于对图片进行滑窗裁剪,因为输入的图片尺寸大多都为4000*1000左右,不利于缺陷的识别和推理,对其进行滑窗裁剪后,得到的多张小图片更利于缺陷识别和推理def crop_on_slide(cut_path, crop_path, stride): if not os.path.exists(crop_path): os.mkdir(crop_path) else: remove_list = os.listdir(crop_path) for filename in remove_list: os.remove(os.path.join(crop_path, filename)) output_shape = 600 imgs = os.listdir(cut_path) for img in imgs: if img.split('.')[1] != "jpg" and img.split('.')[1] != "JPG": raise ValueError("The file {} is not jpg or JPG image!".format(img)) origin_image = cv2.imread(os.path.join(cut_path, img)) height = origin_image.shape[0] width = origin_image.shape[1] x = 0 newheight = output_shape newwidth = output_shape while x < width: y = 0 if x + newwidth <= width: while y < height: if y + newheight <= height: hmin = y hmax = y + newheight wmin = x wmax = x + newwidth else: hmin = height - newheight hmax = height wmin = x wmax = x + newwidth y = height # test crop_img = os.path.join(crop_path, ( img.split('.')[0] + '_' + str(wmax) + '_' + str(hmax) + '_' + str(output_shape) + '.jpg')) cv2.imwrite(crop_img, origin_image[hmin: hmax, wmin: wmax]) y = y + stride if y + output_shape == height: y = height else: while y < height: if y + newheight <= height: hmin = y hmax = y + newheight wmin = width - newwidth wmax = width else: hmin = height - newheight hmax = height wmin = width - newwidth wmax = width y = height # test crop_img = os.path.join(crop_path, ( img.split('.')[0] + '_' + str(wmax) + '_' + str(hmax) + '_' + str( output_shape) + '.jpg')) cv2.imwrite(crop_img, origin_image[hmin: hmax, wmin: wmax]) y = y + stride x = width x = x + stride if x + output_shape == width: x = widthimage_inference函数用于流的初始化,推理所需文件夹的创建、图片预处理、推理时间记录、推理后处理、推理结果可视化def image_inference(pipeline_path, s_name, img_dir, result_dir, rp_last, model_type): sdk_api = SdkApi(pipeline_path) if not sdk_api.init(): exit(-1) if not os.path.exists(result_dir): os.makedirs(result_dir) img_data_plugin_id = 0 img_metas_plugin_id = 1 logging.info("\nBegin to inference for {}.\n\n".format(img_dir)) file_list = os.listdir(img_dir) total_len = len(file_list) if total_len == 0: logging.info("ERROR\nThe input directory is EMPTY!\nPlease place the picture in '../data/test/cut'!") for img_id, file_name in enumerate(file_list): if not file_name.lower().endswith((".jpg", "jpeg")): continue file_path = os.path.join(img_dir, file_name) save_path = os.path.join(result_dir, f"{os.path.splitext(file_name)[0]}.json") if not rp_last and os.path.exists(save_path): logging.info("The infer result json({}) has existed, will be skip.".format(save_path)) continue try: if model_type == 'dvpp': with open(file_path, "rb") as fp: data = fp.read() sdk_api.send_data_input(s_name, img_data_plugin_id, data) else: img_np = process_img(file_path) sdk_api.send_img_input(s_name, img_data_plugin_id, "appsrc0", img_np.tobytes(), img_np.shape) # set image data img_metas = get_img_metas(file_path).astype(np.float32) sdk_api.send_tensor_input(s_name, img_metas_plugin_id, "appsrc1", img_metas.tobytes(), [1, 4], cfg.TENSOR_DTYPE_FLOAT32) start_time = time.time() result = sdk_api.get_result(s_name) end_time = time.time() - start_time if os.path.exists(save_path): os.remove(save_path) flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL modes = stat.S_IWUSR | stat.S_IRUSR with os.fdopen(os.open((save_path), flags, modes), 'w') as fp: fp.write(json.dumps(result)) logging.info( "End-2end inference, file_name: {}, {}/{}, elapsed_time: {}.\n".format(file_path, img_id + 1, total_len, end_time)) draw_label(save_path, file_path, result_dir) except Exception as ex: logging.exception("Unknown error, msg:{}.".format(ex)) post_process()步骤三:main方法编写if __name__ == "__main__": args = parser_args() REPLACE_LAST = True STREAM_NAME = cfg.STREAM_NAME.encode("utf-8") CUT_PATH = "../data/test/cut/" CROP_IMG_PATH = "../data/test/crop/" STRIDE = 450 crop_on_slide(CUT_PATH, CROP_IMG_PATH, STRIDE) image_inference(args.pipeline_path, STREAM_NAME, args.img_path, args.infer_result_dir, REPLACE_LAST, args.model_type) if args.infer_mode == "eval": logging.info("Infer end.\nBegin to eval...") get_eval_result(args.ann_file, args.infer_result_dir)2、infer.pyinfer.py中是主要的sdk推理步骤,包括流的初始化到流的销毁,编写完成后在main.py中调用。步骤一:导入相关包,并定义相关类和函数步骤二:编写各个函数init魔法属性用来构造sdk实例化对象def __init__(self, pipeline_cfg): self.pipeline_cfg = pipeline_cfg self._stream_api = None self._data_input = None self._device_id = Nonedel魔法属性用来销毁实例化对象def __del__(self): if not self._stream_api: return self._stream_api.DestroyAllStreams()_convert_infer_result函数用来将推理结果输出def _convert_infer_result(infer_result): data = infer_result.get('MxpiObject') if not data: logging.info("The result data is empty.") return infer_result for bbox in data: if 'imageMask' not in bbox: continue mask_info = json_format.ParseDict(bbox["imageMask"], MxpiDataType.MxpiImageMask()) mask_data = np.frombuffer(mask_info.dataStr, dtype=np.uint8) bbox['imageMask']['data'] = "".join([str(i) for i in mask_data]) bbox['imageMask'].pop("dataStr") return infer_resultinit函数用来stream manager的初始化def init(self): try: with open(self.pipeline_cfg, 'r') as fp: self._device_id = int( json.loads(fp.read())[self.STREAM_NAME]["stream_config"] ["deviceId"]) logging.info("The device id: {}.".format(self._device_id)) # create api self._stream_api = StreamManagerApi() # init stream mgr ret = self._stream_api.InitManager() if ret != 0: logging.info("Failed to init stream manager, ret={}.".format(ret)) return False # create streams with open(self.pipeline_cfg, 'rb') as fp: pipe_line = fp.read() ret = self._stream_api.CreateMultipleStreams(pipe_line) if ret != 0: logging.info("Failed to create stream, ret={}.".format(ret)) return False self._data_input = MxDataInput() except Exception as exe: logging.exception("Unknown error, msg:{}".format(exe)) return False return Truesend_data_input函数用来传输推理数据def send_data_input(self, stream_name, plugin_id, input_data): data_input = MxDataInput() data_input.data = input_data unique_id = self._stream_api.SendData(stream_name, plugin_id, data_input) if unique_id < 0: logging.error("Fail to send data to stream.") return False return Truesend_img_input函数用来传入图片def send_img_input(self, stream_name, plugin_id, element_name, input_data, img_size): vision_list = MxpiDataType.MxpiVisionList() vision_vec = vision_list.visionVec.add() vision_vec.visionInfo.format = 1 vision_vec.visionInfo.width = img_size[1] vision_vec.visionInfo.height = img_size[0] vision_vec.visionInfo.widthAligned = img_size[1] vision_vec.visionInfo.heightAligned = img_size[0] vision_vec.visionData.memType = 0 vision_vec.visionData.dataStr = input_data vision_vec.visionData.dataSize = len(input_data) buf_type = b"MxTools.MxpiVisionList" return self._send_protobuf(stream_name, plugin_id, element_name, buf_type, vision_list)send_tensor_input函数用来传入张量数据def send_tensor_input(self, stream_name, plugin_id, element_name, input_data, input_shape, data_type): tensor_list = MxpiDataType.MxpiTensorPackageList() tensor_pkg = tensor_list.tensorPackageVec.add() # init tensor vector tensor_vec = tensor_pkg.tensorVec.add() tensor_vec.deviceId = self._device_id tensor_vec.memType = 0 tensor_vec.tensorShape.extend(input_shape) tensor_vec.tensorDataType = data_type tensor_vec.dataStr = input_data tensor_vec.tensorDataSize = len(input_data) buf_type = b"MxTools.MxpiTensorPackageList" return self._send_protobuf(stream_name, plugin_id, element_name, buf_type, tensor_list)get_result函数用来获得推理结果def get_result(self, stream_name, out_plugin_id=0): infer_res = self._stream_api.GetResult(stream_name, out_plugin_id, self.INFER_TIMEOUT) if infer_res.errorCode != 0: logging.info("GetResultWithUniqueId error, errorCode={}, errMsg={}".format(infer_res.errorCode, infer_res.data.decode())) return None res_dict = json.loads(infer_res.data.decode()) return self._convert_infer_result(res_dict)_send_protobuf函数用来对目标检测结果进行序列化def _send_protobuf(self, stream_name, plugin_id, element_name, buf_type, pkg_list): protobuf = MxProtobufIn() protobuf.key = element_name.encode("utf-8") protobuf.type = buf_type protobuf.protobuf = pkg_list.SerializeToString() protobuf_vec = InProtobufVector() protobuf_vec.push_back(protobuf) err_code = self._stream_api.SendProtobuf(stream_name, plugin_id, protobuf_vec) if err_code != 0: logging.error( "Failed to send data to stream, stream_name:{}, plugin_id:{}, " "element_name:{}, buf_type:{}, err_code:{}.".format( stream_name, plugin_id, element_name, buf_type, err_code)) return False return True3、postprocess.py对经过滑窗裁剪后的小图片进行推理,最后得到的推理结果也是在小图片上,因此需要对推理结果进行后处理,将小图片上的推理结果还原到未经过滑窗裁剪的图片上。步骤一:导入相关包,并定义相关函数步骤二:编写各个函数json_to_txt函数用来将得到的json格式推理结果转为txt格式def json_to_txt(infer_result_path, savetxt_path): if os.path.exists(savetxt_path): shutil.rmtree(savetxt_path) os.mkdir(savetxt_path) files = os.listdir(infer_result_path) for file in files: if file.endswith(".json"): json_path = os.path.join(infer_result_path, file) with open(json_path, 'r') as fp: result = json.loads(fp.read()) if result: data = result.get("MxpiObject") txt_file = file.split(".")[0] + ".txt" flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL modes = stat.S_IWUSR | stat.S_IRUSR with os.fdopen(os.open(os.path.join(savetxt_path, txt_file), flags, modes), 'w') as f: if file.split('_')[0] == "W0003": temp = int(file.split("_")[2]) - 600 else: temp = int(file.split("_")[1]) - 600 for bbox in data: class_vec = bbox.get("classVec")[0] class_id = int(class_vec["classId"]) confidence = class_vec.get("confidence") xmin = bbox["x0"] ymin = bbox["y0"] xmax = bbox["x1"] ymax = bbox["y1"] if xmax - xmin >= 5 and ymax - ymin >= 5: f.write( str(xmin + temp) + ',' + str(ymin) + ',' + str(xmax + temp) + ',' + str( ymax) + ',' + str( round(confidence, 2)) + ',' + str(class_id) + '\n')hebing_txt函数用来将滑窗裁剪后的小图片推理结果还原到原始图片上def hebing_txt(txt_path, save_txt_path, remove_txt_path, cut_path): if not os.path.exists(save_txt_path): os.makedirs(save_txt_path) if not os.path.exists(remove_txt_path): os.makedirs(remove_txt_path) fileroot = os.listdir(save_txt_path) remove_list = os.listdir(remove_txt_path) for filename in remove_list: os.remove(os.path.join(remove_txt_path, filename)) for filename in fileroot: os.remove(os.path.join(save_txt_path, filename)) data = [] for file in os.listdir(cut_path): data.append(file.split(".")[0]) txt_list = os.listdir(txt_path) flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL modes = stat.S_IWUSR | stat.S_IRUSR for image in data: fw = os.fdopen(os.open(os.path.join(save_txt_path, image + '.txt'), flags, modes), 'w') for txtfile in txt_list: if image.split('_')[0] == "W0003": if image.split('_')[1] == txtfile.split('_')[1]: for line in open(os.path.join(txt_path, txtfile), "r"): fw.write(line) else: if image.split('_')[0] == txtfile.split('_')[0]: for line in open(os.path.join(txt_path, txtfile), "r"): fw.write(line) fw.close() fileroot = os.listdir(save_txt_path) for file in fileroot: oldname = os.path.join(save_txt_path, file) newname = os.path.join(remove_txt_path, file) shutil.copyfile(oldname, newname)py_cpu_nms、plot_bbox、nms_box函数用来对还原后的推理结果进行nms去重处理,在进行滑窗裁剪时,为了不在裁剪时将缺陷切断从而保留所有缺陷,所以设置的滑窗步长小于小图片尺寸,因此得到的推理结果会有重复,需进行nms去重处理def py_cpu_nms(dets, thresh): x1 = dets[:, 0] y1 = dets[:, 1] x2 = dets[:, 2] y2 = dets[:, 3] areas = (y2 - y1 + 1) * (x2 - x1 + 1) scores = dets[:, 4] keep = [] index = scores.argsort()[::-1] while index.size > 0: i = index[0] # every time the first is the biggst, and add it directly keep.append(i) x11 = np.maximum(x1[i], x1[index[1:]]) # calculate the points of overlap y11 = np.maximum(y1[i], y1[index[1:]]) x22 = np.minimum(x2[i], x2[index[1:]]) y22 = np.minimum(y2[i], y2[index[1:]]) w = np.maximum(0, x22 - x11 + 1) # the weights of overlap h = np.maximum(0, y22 - y11 + 1) # the height of overlap overlaps = w * h ious = overlaps / (areas[i] + areas[index[1:]] - overlaps) idx = np.where(ious <= thresh)[0] index = index[idx + 1] # because index start from 1 return keep def plot_bbox(dets, c='k'): x1 = dets[:, 0] y1 = dets[:, 1] x2 = dets[:, 2] y2 = dets[:, 3] plt.plot([x1, x2], [y1, y1], c) plt.plot([x1, x1], [y1, y2], c) plt.plot([x1, x2], [y2, y2], c) plt.plot([x2, x2], [y1, y2], c) plt.title(" nms") def nms_box(image_path, image_save_path, txt_path, thresh, obj_list): if not os.path.exists(image_save_path): os.makedirs(image_save_path) remove_list = os.listdir(image_save_path) for filename in remove_list: os.remove(os.path.join(image_save_path, filename)) txt_list = os.listdir(txt_path) for txtfile in tqdm.tqdm(txt_list): boxes = np.loadtxt(os.path.join(txt_path, txtfile), dtype=np.float32, delimiter=',') if boxes.size > 5: if os.path.exists(os.path.join(txt_path, txtfile)): os.remove(os.path.join(txt_path, txtfile)) flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL modes = stat.S_IWUSR | stat.S_IRUSR fw = os.fdopen(os.open(os.path.join(txt_path, txtfile), flags, modes), 'w') keep = py_cpu_nms(boxes, thresh=thresh) img = cv.imread(os.path.join(image_path, txtfile[:-3] + 'jpg'), 0) for label in boxes[keep]: fw.write(str(int(label[0])) + ',' + str(int(label[1])) + ',' + str(int(label[2])) + ',' + str( int(label[3])) + ',' + str(round((label[4]), 2)) + ',' + str(int(label[5])) + '\n') x_min = int(label[0]) y_min = int(label[1]) x_max = int(label[2]) y_max = int(label[3]) color = (0, 0, 255) if x_max - x_min >= 5 and y_max - y_min >= 5: cv.rectangle(img, (x_min, y_min), (x_max, y_max), color, 1) font = cv.FONT_HERSHEY_SIMPLEX cv.putText(img, (obj_list[int(label[5])] + str(round((label[4]), 2))), (x_min, y_min - 7), font, 0.4, (6, 230, 230), 1) cv.imwrite(os.path.join(image_save_path, txtfile[:-3] + 'jpg'), img) fw.close()post_process函数用来调用以上编写的函数,最后在main.py中被调用def post_process(): infer_result_path = "../data/test/infer_result" txt_save_path = "../data/test/img_txt" json_to_txt(infer_result_path, txt_save_path) txt_path = "../data/test/img_txt" all_txt_path = "../data/test/img_huizong_txt" nms_txt_path = "../data/test/img_huizong_txt_nms" cut_path = "../data/test/cut" hebing_txt(txt_path, all_txt_path, nms_txt_path, cut_path) cut_path = "../data/test/cut" image_save_path = "../data/test/draw_result" nms_txt_path = "../data/test/img_huizong_txt_nms" obj_lists = ['qikong', 'liewen'] nms_box(cut_path, image_save_path, nms_txt_path, thresh=0.1, obj_list=obj_lists)10、代码运行前面的步骤完成之后,我们就可以进行代码的运行了,本项目中,图片的输入输出位置都是用的相对路径,因此不需要修改路径参数,按以下步骤进行模型推理:步骤一:放置待检测图片本项目中,将图片放置在./python/data/test/cut目录下,例如我放的图片:步骤二:在main.py中设置好初始图片所在位置和结果图片保存位置。步骤三:设置运行脚本运行应用点击下图箭头所指,设置自己的运行脚本点击绿色箭头,开始运行运行成功,查看推理结果五、常见问题在使用 MindStudio 时,遇到问题,可以登陆华为云论坛云计算论坛开发者论坛技术论坛-华为云 (huaweicloud.com)进行互动,提出问题,会有专家老师为你解答。1、CANN 连接错误连接服务器 SSH 成功,但是连接 CANN 失败:点击OK,点击Show Error Details,查看报错信息:问题:权限不够,无法连接。解决方案:在远程环境自己的工作目录下重新下载CANN后,再连接CANN即可。2、后处理插件权限问题如图,运行时显示权限不够:两种解决方案:方案一:在远程终端中找到后处理插件所在位置,修改其权限为640,如图:修改完成后,需将改文件设置为不同步,如图:方案二:在远程终端环境中找到后处理插件所在位置,将其复制到MindX SDK自带的后处理插件库文件夹下,并修改其权限为640,然后修改pipeline文件中后处理插件所在位置。注:MindX SDK自带的后处理插件库文件夹一般为${MX_SDK_HOME}/lib/modelpostprocessors/
-
bilibili视频链接:使用MindStudio开发基于MindX SDK的X射线图像缺陷检测应用一、MindStudio1、MindStudio介绍MindStudio简介:MindStudio 提供您在 AI 开发所需的一站式开发环境,支持模型开发、算子开发以及应用开发三个主流程中的开发任务。依靠模型可视化、算力测试、IDE 本地仿真调试等功能,MindStudio 能够帮助您在一个工具上就能高效便捷地完 成 AI 应用开发。MindStudio 采用了插件化扩展机制,开发者可以通过开发插件来扩展已有功能。功能简介针对安装与部署,MindStudio 提供多种部署方式,支持多种主流操作系统, 为开发者提供最大便利。针对网络模型的开发,MindStudio 支持 TensorFlow、PyTorch、MindSpore 框 架的模型训练,支持多种主流框架的模型转换。集成了训练可视化、脚本转换、模型转换、精度比对等工具,提升了网络模型移植、分析和优化的效率。针对算子开发,MindStudio 提供包含 UT 测试、ST 测试、TIK 算子调试等的全套算子开发流程。支持 TensorFlow、PyTorch、MindSpore 等多种主流框架 的 TBE 和 AI CPU 自定义算子开发。针对应用开发,MindStudio 集成了 Profiling 性能调优、编译器、MindX SDK 的应用开发、可视化 pipeline 业务流编排等工具,为开发者提供了图形化 的集成开发环境,通过 MindStudio 能够进行工程管理、编译、调试、性能分析等全流程开发,能够很大程度提高开发效率。功能框架MindStudio功能框架如下图所示,目前含有的工具链包括:模型转换工具、模型训练工具、自定义算子开发工具、应用开发工具、工程管理工具、编译工具、流程编排工具、精度比对工具、日志管理工具、性能分析工具、设备管理工具等多种工具。场景介绍开发场景:在非昇腾AI设备(如windosw平台)上安装MindStudio和Ascend-cann-toolkit开发套件包。在该开发场景下,我们仅用于代码开发、编译等不依赖昇腾设备的活动,如果要运行应用程序或者模型训练等,需要通过MindStudio远程连接(SSH)已经部署好运行环境所需要软件包(CANN、MindX SDK等)的昇腾AI设备。开发运行场景:在昇腾AI设备(昇腾AI服务器)上安装MindStudio、Ascend-cann-toolkit开发套件包等安装包和AI框架(进行模型训练时需要安装)。在该开发环境下,开发人员可以进行代码编写、编译、程序运行、模型训练等操作。软件包介绍MindStudio:提供图形化开发界面,支持应用开发、调试和模型转换功能, 同时还支持网络移植、优化和分析等功能,可以安装在linux、windows平台。Ascend-cann-toolkit:开发套件包。为开发者提供基于昇腾 AI 处理器的相关算法开发工具包,旨在帮助开发者进行快速、高效的模型、算子和应用的开发。开发套件包只能安装在 Linux 服务器上,开发者可以在安装开发套件包后,使用 MindStudio 开发工具进行快速开发。注:由于Ascend-cann-toolkit只能安装在linux服务器上,所以在Windows场景下代码开发时,需先安装MindStudio软件,再远程连接同步Linux服务器的CANN和MindX SDK到本地。二、MindX SDK1、MindX SDK介绍MindX SDK 提供昇腾 AI 处理器加速的各类 AI 软件开发套件(SDK),提供极简易用的 API,加速 AI 应用的开发。应用开发旨在使用华为提供的 SDK 和应用案例快速开发并部署人工智能应用,是基于现有模型、使用pyACL 提供的 Python 语言 API 库开发深度神经网络 应用,用于实现目标识别、图像分类等功能。mxManufacture & mxVision 关键特性:配置文件快速构建 AI 推理业务。插件化开发模式,将整个推理流程“插件化”,每个插件提供一种功能,通过组装不同的插件,灵活适配推理业务流程。提供丰富的插件库,用户可根据业务需求组合 Jpeg 解码、抠图、缩放、模型推理、数据序列化等插件。基于 Ascend Computing Language(ACL),提供常用功能的高级 API,如模型推理、解码、预处理等,简化 Ascend 芯片应用开发。支持自定义插件开发,用户可快速地将自己的业务逻辑封装成插件,打造自己的应用插件。三、可视化流程编排介绍1、SDK基础概念通过 stream(业务流)配置文件,Stream manager(业务流管理模块)可识别需要构建的 element(功能元件)以及 element 之间的连接关系,并启动业务流程。Stream manager 对外提供接口,用于向 stream 发送数据和获取结果,帮助用户实现业务对接。Plugin(功能插件)表示业务流程中的基础模块,通过 element 的串接构建成一个 stream。Buffer(插件缓存)用于内部挂载解码前后的视频、图像数据, 是 element 之间传递的数据结构,同时也允许用户挂载 Metadata(插件元数据), 用于存放结构化数据(如目标检测结果)或过程数据(如缩放后的图像)2、可视化流程编排MindX SDK 实现功能的最小粒度是插件,每一个插件实现特定的功能,如图片解码、图片缩放等。流程编排是将这些插件按照合理的顺序编排,实现负责的功能。可视化流程编排是以可视化的方式,开发数据流图,生成 pipeline 文件供应用框架使用。下图为推理业务流 Stream 配置文件 pipeline 样例。配置文件以 json 格式编写,用户必须指定业务流名称、元件名称和插件名称,并根据需要,补充元件属性和下游元件名称信息。四、项目开发(Python)本项目主要介绍在Windows场景下使用MindStudio软件,连接远程服务器配置的MindX SDK、CANN环境,采用Faster R-CNN模型对GDxray焊接缺陷数据集进行焊接缺陷检测的应用开发。项目参考模型地址:Faster R-CNN项目代码地址:contrib/Faster_R-CNN · Ascend/mindxsdk-referenceappsGDXray是一个公开X射线数据集,其中包括一个关于X射线焊接图像(Welds)的数据,该数据由德国柏林的BAM联邦材料研究和测试研究所收集。Welds集中W0003 包括了68张焊接公司的X射线图像。本项目基于W0003数据集并在焊接专家的帮助下将焊缝和其内部缺陷标注。数据集下载地址:cid:link_61、MindStudio安装点击超链接下载MindStudio安装包MindStudio安装包下载点击超链接,进入MindStudio用户手册,在安装指南下安装操作中可以看见MindStudio具体的安装操作。MindStudio用户手册2、新建一个项目点击Ascend App,新建一个项目,在D:\Codes\python\Ascend\MyApp位置下创建自己的项目。点击 Change 安装CANN,进入 Remote CANN Setting 界面,如下图所示,远程连接需要配置SSH连接,点击**"+"**,进入SSH连接界面。参数解释Remote Connection远程服务器 IPRemote CANN location远程服务器中 CANN 路径下图为SSH连接界面中,ssh远程连接需配置远程终端账号,点击**"+"**后,进入SSH连接配置界面。下图为SSH配置界面,配置好后点击Test Connection,出现 ”Sucessfully connected!“即配置成功。返回到 Remote CANN Setting 界面,输入远程CANN路径完成 CANN 安装,点击 OK。接着,选择MindX SDK Project(Python),如下图所示,被圈出来的4个项目,上面两个是空模板,在这里面创建我们自己的工程项目,因为我们要创建Python版的应用,所以被单独框出来的这个;下面两个是官方给出的样例项目,如果对目录结构和应该写哪些代码不太熟悉的话,也可以创建一个样例项目先学习一下。选择完成后,点击Finish完成项目的创建进入项目,项目创建完成后,可根据自己需要新建文件、文件夹。3、MindX SDK安装步骤1、 Windows 场景下基于 MindStuido 的 SDK 应用开发(本地远程连接服务器端MindX SDK),请先确保远端环境上 MindX SDK 软件包已安装完成。(远程安装MindX SDK开发套件)步骤2、在 Windows 本地进入工程创建页面,工具栏点击 File > Settings > Appearance & Behavior> System Settings > MindX SDK 进入 MindX SDK 管理界面(只有安装CANN后才会出现MindX SDK按钮)。界面中 MindX SDK Location 为软件包的默认安装路径,默认安装路径为 “C:\Users\用户\Ascend\mindx_sdk”。单击 Install SDK 进入Installation settings 界面。如图所示,为 MindX SDK 的安装界面,各参数选择如下:Remote Connection:远程连接的用户及 IP。Remote CANN location:远端环境上 CANN 开发套件包的路径,请配置到版 本号一级。Remote SDK location:远端环境上 SDK 的路径,请配置到版本号一级。IDE 将同步该层级下的include、opensource、python、samples 文件夹到本地 Windows 环境,层级选择错误将导致安装失败。Local SDK location:同步远端环境上 SDK 文件夹到本地的路径。默认安装路径为“C:\Users\用户名\Ascend\mindx_sdk”。步骤 3 :单击 OK 结束,返回 SDK 管理界面如下图,可查看安装后的 SDK 的信息,可单击 OK结束安装流程。4、工程目录结构介绍在实际开发中,需要在./postprocess下编写后处理插件,在./python/Main下编写需要运行的python文件,在./python/models下放置模型相关配置文件,在./python/pipeline下编写工作流文件,本项目工程开发结束后的目录如下图所示。5、文件同步(可选)本地文件与远程文件同步一般自行决定是否需要该功能,若不进行文件同步,在后续编译文件或者运行应用时,MindStudio也会自行将项目文件同步到远端用户目录下MindStudio-WorkSpace文件夹中。在顶部菜单栏中选择 Tools > Deployment > Configuration ,如图:点击已连接的远程环境后,点击Mappings可添加需要同步的文件夹,点击Excluded Paths可添加同步的文件下不需要同步的文件。6、Faster R-CNN模型转换用户使用 Caffe/TensorFlow 等框架训练好的第三方模型,可通过 ATC 工具将其转换为昇腾 AI 处理器支持的离线模型(*.om 文件),模型转换过程中可以实现算子调度的优化、权重数据重排、内存使用优化等,可以脱离设备完成模型的预处理,详细架构如下图。在本项目中,要将 mindspore 框架下训练好的模型(.air 文件),转换为昇腾 AI 处理器支持的离线模型(.om 文件),具体步骤如下:步骤 1: 点击 Ascend > Model Converter,进入模型转换界面,参数配置如图所示,若没有CANN Machine,请参见第四章第二节 CANN 安装。各参数解释如下表所示:参数解释CANN MachineCANN 的远程服务器Model File*.air 文件的路径(可以在本地,也可以在服务器上)Target SoC Version模型转换时指定芯片型号Model Name生成的 om 模型名字Output Path生成的 om 模型保存在本地的路径Input Format输入数据格式Input Nodes模型输入节点信息步骤 2: 配置完成后,点击Next,进行数据预处理设置,配置完成后点击Next,如图:步骤 3: 进行模型转换命令及环境变量设置,该项目配置示例如图:各参数解释如下表所示:参数解释Additional Arguments执行命令时需要添加的其他参数配置Environment Variables环境变量设置Command Preview查看经过前面一系列配置后最终的命名形式步骤 4: 配置完成后,点击Finish进行模型转换。步骤 5:等待出现如下图所示的提示,模型转换成功。步骤 6:双击转换成功的 om 模型文件,可以查看网络结构。如下图所示。7、编写后处理插件并编译以下需要编写的文件均在./postprocess/目录下1、头文件FasterRcnnMindsporePost.hFasterRcnnMindsporePost.h头文件包含了类的声明(包括类里面的成员和方法的声明)、函数原型、#define 常数等。其中,#include 类及#define 常数如代码所示;定义的初始化参数结构体如代码所示;类里面的成员和方法的声明如代码所示。/* * Copyright (c) 2022. Huawei Technologies Co., Ltd. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FASTERRCNN_MINSPORE_PORT_H #define FASTERRCNN_MINSPORE_PORT_H #include <algorithm> #include <vector> #include <map> #include <opencv4/opencv2/opencv.hpp> #include "MxBase/ErrorCode/ErrorCode.h" #include "MxBase/CV/Core/DataType.h" #include "MxBase/PostProcessBases/ObjectPostProcessBase.h" namespace MxBase { class FasterRcnnMindsporePost : public ObjectPostProcessBase { public: FasterRcnnMindsporePost() = default; ~FasterRcnnMindsporePost() = default; FasterRcnnMindsporePost(const FasterRcnnMindsporePost &other); FasterRcnnMindsporePost &operator=(const FasterRcnnMindsporePost &other); APP_ERROR Init(const std::map<std::string, std::shared_ptr<void>> &postConfig) override; APP_ERROR DeInit() override; APP_ERROR Process(const std::vector<TensorBase> &tensors, std::vector<std::vector<ObjectInfo>> &objectInfos, const std::vector<ResizedImageInfo> &resizedImageInfos = {}, const std::map<std::string, std::shared_ptr<void>> &configParamMap = {}) override; bool IsValidTensors(const std::vector<TensorBase> &tensors) const; private: void ObjectDetectionOutput(const std::vector<TensorBase> &tensors, std::vector<std::vector<ObjectInfo>> &objectInfos, const std::vector<ResizedImageInfo> &resizedImageInfos); void GetValidDetBoxes(const std::vector<TensorBase> &tensors, std::vector<DetectBox> &detBoxes, uint32_t batchNum); void ConvertObjInfoFromDetectBox(std::vector<DetectBox> &detBoxes, std::vector<ObjectInfo> &objectInfos, const ResizedImageInfo &resizedImageInfos); APP_ERROR ReadConfigParams(); private: const uint32_t DEFAULT_CLASS_NUM_MS = 8; const float DEFAULT_SCORE_THRESH_MS = 0.7; const float DEFAULT_IOU_THRESH_MS = 0.5; const uint32_t DEFAULT_RPN_MAX_NUM_MS = 1000; const uint32_t DEFAULT_MAX_PER_IMG_MS = 128; uint32_t classNum_ = DEFAULT_CLASS_NUM_MS; float scoreThresh_ = DEFAULT_SCORE_THRESH_MS; float iouThresh_ = DEFAULT_IOU_THRESH_MS; uint32_t rpnMaxNum_ = DEFAULT_RPN_MAX_NUM_MS; uint32_t maxPerImg_ = DEFAULT_MAX_PER_IMG_MS; }; extern "C" { std::shared_ptr<MxBase::FasterRcnnMindsporePost> GetObjectInstance(); } } // namespace MxBase #endif // FASTERRCNN_MINSPORE_PORT_H2、源文件FasterRcnnMindsporePost.cpp这里我们主要是实现在头文件中定义的函数,接下来做一个简要的概括ReadConfigParams函数用来读取目标检测类别信息、以及一些超参数如scoreThresh、iouThreshInit函数用来进行目标检测后处理中常用的初始化IsValidTensors函数用来判断输出结果是否有效GetValidDetBoxes函数用来获取有效的推理信息ConvertObjInfoFromDetectBox函数用来将推理信息转为标注框信息ObjectDetectionOutput函数用来输出得到的推理结果Process函数用来做预处理/* * Copyright (c) 2022. Huawei Technologies Co., Ltd. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <boost/property_tree/json_parser.hpp> #include <opencv4/opencv2/core.hpp> #include <opencv4/opencv2/opencv.hpp> #include "acl/acl.h" #include "FasterRcnnMindsporePost.h" #include "MxBase/CV/ObjectDetection/Nms/Nms.h" namespace { // Output Tensor const int OUTPUT_TENSOR_SIZE = 3; const int OUTPUT_BBOX_SIZE = 3; const int OUTPUT_BBOX_TWO_INDEX_SHAPE = 5; const int OUTPUT_BBOX_INDEX = 0; const int OUTPUT_CLASS_INDEX = 1; const int OUTPUT_MASK_INDEX = 2; const int BBOX_INDEX_LX = 0; const int BBOX_INDEX_LY = 1; const int BBOX_INDEX_RX = 2; const int BBOX_INDEX_RY = 3; const int BBOX_INDEX_PROB = 4; const int BBOX_INDEX_SCALE_NUM = 5; } // namespace namespace MxBase { FasterRcnnMindsporePost &FasterRcnnMindsporePost::operator=(const FasterRcnnMindsporePost &other) { if (this == &other) { return *this; } ObjectPostProcessBase::operator=(other); return *this; } APP_ERROR FasterRcnnMindsporePost::ReadConfigParams() { APP_ERROR ret = configData_.GetFileValue<uint32_t>("CLASS_NUM", classNum_); if (ret != APP_ERR_OK) { LogWarn << GetError(ret) << "No CLASS_NUM in config file, default value(" << classNum_ << ")."; } ret = configData_.GetFileValue<float>("SCORE_THRESH", scoreThresh_); if (ret != APP_ERR_OK) { LogWarn << GetError(ret) << "No SCORE_THRESH in config file, default value(" << scoreThresh_ << ")."; } ret = configData_.GetFileValue<float>("IOU_THRESH", iouThresh_); if (ret != APP_ERR_OK) { LogWarn << GetError(ret) << "No IOU_THRESH in config file, default value(" << iouThresh_ << ")."; } ret = configData_.GetFileValue<uint32_t>("RPN_MAX_NUM", rpnMaxNum_); if (ret != APP_ERR_OK) { LogWarn << GetError(ret) << "No RPN_MAX_NUM in config file, default value(" << rpnMaxNum_ << ")."; } ret = configData_.GetFileValue<uint32_t>("MAX_PER_IMG", maxPerImg_); if (ret != APP_ERR_OK) { LogWarn << GetError(ret) << "No MAX_PER_IMG in config file, default value(" << maxPerImg_ << ")."; } LogInfo << "The config parameters of post process are as follows: \n" << " CLASS_NUM: " << classNum_ << " \n" << " SCORE_THRESH: " << scoreThresh_ << " \n" << " IOU_THRESH: " << iouThresh_ << " \n" << " RPN_MAX_NUM: " << rpnMaxNum_ << " \n" << " MAX_PER_IMG: " << maxPerImg_ << " \n"; } APP_ERROR FasterRcnnMindsporePost::Init(const std::map<std::string, std::shared_ptr<void>> &postConfig) { LogInfo << "Begin to initialize FasterRcnnMindsporePost."; APP_ERROR ret = ObjectPostProcessBase::Init(postConfig); if (ret != APP_ERR_OK) { LogError << GetError(ret) << "Fail to superinit in ObjectPostProcessBase."; return ret; } ReadConfigParams(); LogInfo << "End to initialize FasterRcnnMindsporePost."; return APP_ERR_OK; } APP_ERROR FasterRcnnMindsporePost::DeInit() { LogInfo << "Begin to deinitialize FasterRcnnMindsporePost."; LogInfo << "End to deinitialize FasterRcnnMindsporePost."; return APP_ERR_OK; } bool FasterRcnnMindsporePost::IsValidTensors(const std::vector<TensorBase> &tensors) const { if (tensors.size() < OUTPUT_TENSOR_SIZE) { LogError << "The number of tensor (" << tensors.size() << ") is less than required (" << OUTPUT_TENSOR_SIZE << ")"; return false; } auto bboxShape = tensors[OUTPUT_BBOX_INDEX].GetShape(); if (bboxShape.size() != OUTPUT_BBOX_SIZE) { LogError << "The number of tensor[" << OUTPUT_BBOX_INDEX << "] dimensions (" << bboxShape.size() << ") is not equal to (" << OUTPUT_BBOX_SIZE << ")"; return false; } uint32_t total_num = classNum_ * rpnMaxNum_; if (bboxShape[VECTOR_SECOND_INDEX] != total_num) { LogError << "The output tensor is mismatched: " << total_num << "/" << bboxShape[VECTOR_SECOND_INDEX] << ")."; return false; } if (bboxShape[VECTOR_THIRD_INDEX] != OUTPUT_BBOX_TWO_INDEX_SHAPE) { LogError << "The number of bbox[" << VECTOR_THIRD_INDEX << "] dimensions (" << bboxShape[VECTOR_THIRD_INDEX] << ") is not equal to (" << OUTPUT_BBOX_TWO_INDEX_SHAPE << ")"; return false; } auto classShape = tensors[OUTPUT_CLASS_INDEX].GetShape(); if (classShape[VECTOR_SECOND_INDEX] != total_num) { LogError << "The output tensor is mismatched: (" << total_num << "/" << classShape[VECTOR_SECOND_INDEX] << "). "; return false; } auto maskShape = tensors[OUTPUT_MASK_INDEX].GetShape(); if (maskShape[VECTOR_SECOND_INDEX] != total_num) { LogError << "The output tensor is mismatched: (" << total_num << "/" << maskShape[VECTOR_SECOND_INDEX] << ")."; return false; } return true; } static bool CompareDetectBoxes(const MxBase::DetectBox &box1, const MxBase::DetectBox &box2) { return box1.prob > box2.prob; } static void GetDetectBoxesTopK(std::vector<MxBase::DetectBox> &detBoxes, size_t kVal) { std::sort(detBoxes.begin(), detBoxes.end(), CompareDetectBoxes); if (detBoxes.size() <= kVal) { return; } LogDebug << "Total detect boxes: " << detBoxes.size() << ", kVal: " << kVal; detBoxes.erase(detBoxes.begin() + kVal, detBoxes.end()); } void FasterRcnnMindsporePost::GetValidDetBoxes(const std::vector<TensorBase> &tensors, std::vector<DetectBox> &detBoxes, uint32_t batchNum) { LogInfo << "Begin to GetValidDetBoxes."; auto *bboxPtr = (aclFloat16 *)GetBuffer(tensors[OUTPUT_BBOX_INDEX], batchNum); // 1 * 80000 * 5 auto *labelPtr = (int32_t *)GetBuffer(tensors[OUTPUT_CLASS_INDEX], batchNum); // 1 * 80000 * 1 auto *maskPtr = (bool *)GetBuffer(tensors[OUTPUT_MASK_INDEX], batchNum); // 1 * 80000 * 1 // mask filter float prob = 0; size_t total = rpnMaxNum_ * classNum_; for (size_t index = 0; index < total; ++index) { if (!maskPtr[index]) { continue; } size_t startIndex = index * BBOX_INDEX_SCALE_NUM; prob = aclFloat16ToFloat(bboxPtr[startIndex + BBOX_INDEX_PROB]); if (prob <= scoreThresh_) { continue; } MxBase::DetectBox detBox; float x1 = aclFloat16ToFloat(bboxPtr[startIndex + BBOX_INDEX_LX]); float y1 = aclFloat16ToFloat(bboxPtr[startIndex + BBOX_INDEX_LY]); float x2 = aclFloat16ToFloat(bboxPtr[startIndex + BBOX_INDEX_RX]); float y2 = aclFloat16ToFloat(bboxPtr[startIndex + BBOX_INDEX_RY]); detBox.x = (x1 + x2) / COORDINATE_PARAM; detBox.y = (y1 + y2) / COORDINATE_PARAM; detBox.width = x2 - x1; detBox.height = y2 - y1; detBox.prob = prob; detBox.classID = labelPtr[index]; detBoxes.push_back(detBox); } GetDetectBoxesTopK(detBoxes, maxPerImg_); } void FasterRcnnMindsporePost::ConvertObjInfoFromDetectBox(std::vector<DetectBox> &detBoxes, std::vector<ObjectInfo> &objectInfos, const ResizedImageInfo &resizedImageInfo) { for (auto &detBoxe : detBoxes) { if (detBoxe.classID < 0) { continue; } ObjectInfo objInfo = {}; objInfo.classId = (float)detBoxe.classID; objInfo.className = configData_.GetClassName(detBoxe.classID); objInfo.confidence = detBoxe.prob; objInfo.x0 = std::max<float>(detBoxe.x - detBoxe.width / COORDINATE_PARAM, 0); objInfo.y0 = std::max<float>(detBoxe.y - detBoxe.height / COORDINATE_PARAM, 0); objInfo.x1 = std::max<float>(detBoxe.x + detBoxe.width / COORDINATE_PARAM, 0); objInfo.y1 = std::max<float>(detBoxe.y + detBoxe.height / COORDINATE_PARAM, 0); objInfo.x0 = std::min<float>(objInfo.x0, resizedImageInfo.widthOriginal - 1); objInfo.y0 = std::min<float>(objInfo.y0, resizedImageInfo.heightOriginal - 1); objInfo.x1 = std::min<float>(objInfo.x1, resizedImageInfo.widthOriginal - 1); objInfo.y1 = std::min<float>(objInfo.y1, resizedImageInfo.heightOriginal - 1); LogDebug << "Find object: " << "classId(" << objInfo.classId << "), confidence(" << objInfo.confidence << "), Coordinates(" << objInfo.x0 << ", " << objInfo.y0 << "; " << objInfo.x1 << ", " << objInfo.y1 << ")."; objectInfos.push_back(objInfo); } } void FasterRcnnMindsporePost::ObjectDetectionOutput(const std::vector<TensorBase> &tensors, std::vector<std::vector<ObjectInfo>> &objectInfos, const std::vector<ResizedImageInfo> &resizedImageInfos) { LogDebug << "FasterRcnnMindsporePost start to write results."; auto shape = tensors[OUTPUT_BBOX_INDEX].GetShape(); uint32_t batchSize = shape[0]; for (uint32_t i = 0; i < batchSize; ++i) { std::vector<MxBase::DetectBox> detBoxes; std::vector<ObjectInfo> objectInfo; GetValidDetBoxes(tensors, detBoxes, i); LogInfo << "DetBoxes size: " << detBoxes.size() << " iouThresh_: " << iouThresh_; NmsSort(detBoxes, iouThresh_, MxBase::MAX); ConvertObjInfoFromDetectBox(detBoxes, objectInfo, resizedImageInfos[i]); objectInfos.push_back(objectInfo); } LogDebug << "FasterRcnnMindsporePost write results successed."; } APP_ERROR FasterRcnnMindsporePost::Process(const std::vector<TensorBase> &tensors, std::vector<std::vector<ObjectInfo>> &objectInfos, const std::vector<ResizedImageInfo> &resizedImageInfos, const std::map<std::string, std::shared_ptr<void>> &configParamMap) { LogDebug << "Begin to process FasterRcnnMindsporePost."; auto inputs = tensors; APP_ERROR ret = CheckAndMoveTensors(inputs); if (ret != APP_ERR_OK) { LogError << "CheckAndMoveTensors failed, ret=" << ret; return ret; } ObjectDetectionOutput(inputs, objectInfos, resizedImageInfos); LogInfo << "End to process FasterRcnnMindsporePost."; return APP_ERR_OK; } extern "C" { std::shared_ptr<MxBase::FasterRcnnMindsporePost> GetObjectInstance() { LogInfo << "Begin to get FasterRcnnMindsporePost instance."; auto instance = std::make_shared<FasterRcnnMindsporePost>(); LogInfo << "End to get FasterRcnnMindsporePost Instance"; return instance; } } } // namespace MxBase3、CMakeLists.txt编译脚本在编译脚本中,需要指定 CMake最低版本要求、项目信息、编译选项等参数,并且需要指定特定头文件和特定库文件的搜索路径。除此之外,要说明根据FasterRcnnMindsporePost.cpp源文件生成libfasterrcnn_mindspore_post.so可执行文件,同时需要指定可执行文件的安装位置,通常为{MX_SDK_HOME}/lib/modelpostprocessors/cmake_minimum_required(VERSION 3.5.2) project(fasterrcnnpost) add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) set(PLUGIN_NAME "fasterrcnn_mindspore_post") set(TARGET_LIBRARY ${PLUGIN_NAME}) set(ACL_LIB_PATH $ENV{ASCEND_HOME}/ascend-toolkit/latest/acllib) include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories($ENV{MX_SDK_HOME}/include) include_directories($ENV{MX_SDK_HOME}/opensource/include) include_directories($ENV{MX_SDK_HOME}/opensource/include/opencv4) include_directories($ENV{MX_SDK_HOME}/opensource/include/gstreamer-1.0) include_directories($ENV{MX_SDK_HOME}/opensource/include/glib-2.0) include_directories($ENV{MX_SDK_HOME}/opensource/lib/glib-2.0/include) link_directories($ENV{MX_SDK_HOME}/lib) link_directories($ENV{MX_SDK_HOME}/opensource/lib/) add_compile_options(-std=c++11 -fPIC -fstack-protector-all -pie -Wno-deprecated-declarations) add_compile_options("-DPLUGIN_NAME=${PLUGIN_NAME}") add_compile_options("-Dgoogle=mindxsdk_private") add_definitions(-DENABLE_DVPP_INTERFACE) message("ACL_LIB_PATH:${ACL_LIB_PATH}.") include_directories(${ACL_LIB_PATH}/include) add_library(${TARGET_LIBRARY} SHARED ./FasterRcnnMindsporePost.cpp ./FasterRcnnMindsporePost.h) target_link_libraries(${TARGET_LIBRARY} glib-2.0 gstreamer-1.0 gobject-2.0 gstbase-1.0 gmodule-2.0) target_link_libraries(${TARGET_LIBRARY} plugintoolkit mxpidatatype mxbase) target_link_libraries(${TARGET_LIBRARY} -Wl,-z,relro,-z,now,-z,noexecstack -s) install(TARGETS ${TARGET_LIBRARY} LIBRARY DESTINATION $ENV{MX_SDK_HOME}/lib/modelpostprocessors/)4、配置编译环境步骤一:指定“CMakeLists.txt”编译配置文件在工程界面左侧目录找到“CMakeLists.txt”文件,右键弹出并单击如所示“Load CMake Project”,即可指定此配置文件进行工程编译。注:本项目编译文件CMakeLists.txt在目录./postprocess/下,上图仅作为功能展示步骤二:编译配置在MindStudio工程界面,依次选择“Build > Edit Build Configuration...”,进入编译配置页面,如图,配置完成后单击“OK”保存编译配置。5、执行编译单击“Build”编译工程。如果在编译过程中无错误提示,且编译进度到“100%”,则表示编译成功,如图。编译成功后,会在项目目录下生成build文件夹,里面有我们需要的可执行文件如图,也可在CMakeLists.txt中最后一行指定可执行文件安装的位置。8、pipeline文件编排pipeline文件编排是python版SDK最主要的推理开发步骤,作为一个目标检测任务,主要包括以下几个步骤: 图片获取 → 图片解码 → 图像缩放 → 目标检测 → 序列化 → 结果发送,以下介绍pipeline文件流程编排步骤:步骤一:在顶部菜单栏中选择“Ascend>MindX SDK Pipeline”,打开空白的pipeline绘制界面,如图:步骤二:从左方插件库中拖动所需插件,放入编辑区,如图:以下介绍本项目中,各个插件的功能:插件名称插件功能appsrc0第一个输入张量,包含了图像数据appsrc1第二个输入张量,包含了图像元数据,主要是图像原始尺寸和图像缩放比mxpi_imagedecoder0用于图像解码,当前只支持JPG/JPEG/BMP格式mxpi_imageresize0对解码后的YUV格式的图像进行指定宽高的缩放,暂时只支持YUV格式的图像mxpi_tensorinfer0对输入的两个张量进行推理mxpi_objectpostprocessor0继承图像后处理基类,用于对目标检测模型推理的输出张量进行后处理mxpi_dataserialize0将stream结果组装成json字符串输出appsink0从stream中获取数据步骤三:单击选中编辑区内的插件,在插件属性展示区自定义配置(如插件属性中的路径参数),如图:步骤四:单击编辑区空白区域,插件两端出现接口,按照一定顺序用鼠标连接以上插件,然后点击编辑区下方Format进行格式化,最后点击编辑区下方Save保存pipeline文件,编写好的pipeline文件可视化结果如下图所示:接下来展示文本代码:{ "im_fasterrcnn": { "stream_config": { "deviceId": "0" }, "appsrc0": { "props": { "blocksize": "409600" }, "factory": "appsrc", "next": "mxpi_imagedecoder0" }, "mxpi_imagedecoder0": { "factory": "mxpi_imagedecoder", "next": "mxpi_imageresize0" }, "mxpi_imageresize0": { "props": { "parentName": "mxpi_imagedecoder0", "resizeHeight": "768", "resizeWidth": "1280", "resizeType": "Resizer_KeepAspectRatio_Fit" }, "factory": "mxpi_imageresize", "next": "mxpi_tensorinfer0:0" }, "appsrc1": { "props": { "blocksize": "409600" }, "factory": "appsrc", "next": "mxpi_tensorinfer0:1" }, "mxpi_tensorinfer0": { "props": { "dataSource": "mxpi_imageresize0,appsrc1", "modelPath": "../models/conversion-scripts/fasterrcnn_mindspore.om" }, "factory": "mxpi_tensorinfer", "next": "mxpi_objectpostprocessor0" }, "mxpi_objectpostprocessor0": { "props": { "dataSource": "mxpi_tensorinfer0", "postProcessConfigPath": "../models/fasterrcnn_coco2017.cfg", "labelPath": "../models/coco2017.names", "postProcessLibPath": "../../postprocess/build/libfasterrcnn_mindspore_post.so" }, "factory": "mxpi_objectpostprocessor", "next": "mxpi_dataserialize0" }, "mxpi_dataserialize0": { "props": { "outputDataKeys": "mxpi_objectpostprocessor0" }, "factory": "mxpi_dataserialize", "next": "appsink0" }, "appsink0": { "factory": "appsink" } } }
-
我用pytorch1.4.0在gpu服务器上训练了一个图像分割模型,然后想在atlas200dk上部署我的模型,想问一下如何把pytorch的pth文件或者onnx文件,直接在atlas200dk上进行模型转化变成om模型?然后在python环境下推理?有没有相关的资料或者代码可以参考
-
【Atlas200产品】【Atlas200原理图功能】 原理图,申请帮忙审核,谢谢邮件已发送,请帮忙审核,谢谢3.8v电压可以测到,但是系统没有启动。
-
大版本号是5.1.rc2取用的openEuler版本是:openEuler-22.03-LTS-aarch64-dvd.iso用sd_maker制卡,查看log是解压iso后找不到文件。make_os_sd.sh处理iso时,并没有initrd.img.gz这个文件。是否还要其它的镜像文件?谢谢。
-
按照教程走了ROS安装,安装成功了。想试下turtle测试下,但没有出现可视化界面,实际操作过程中用键盘输入是有响应的。然后查了下说可以rosrun rqt_plot 或者rqt_graph或者rqt_publisher,但是全都报错This plugin does not support propagateSizeHints()请问该怎么解决,想打开可视化界面。
-
本文主要介绍通过 MindStudio 全流程开发工具链,将 PaddlePaddle 模型转成 om 模型,并在昇腾环境上进行推理的流程。一、模型介绍本文开发的模型为基于 PaddlePaddle 的模型库 PaddleOCR 中的SAST_ResNet50_vd模型。静态分析安全测试(SAST)是指不运行被测程序本身,仅通过分析或者检查源程序的语法、结构、过程、接口等来检查程序的正确性。相比于动态分析或运行时测试方案,它们能在开发阶段,而不是开发完成之后,探测出源码中的安全漏洞,从而大大降低修复安全问题的成本。它们还能找到许多动态分析工具通常无法找到的漏洞。而且,得益于其自动化的特性,SAST 工具能在成百上千款应用间实现伸缩,而这是仅靠人为分析方法无法企及的。 开发流程示意图如图1.1: 图1.1二、MindStudio环境搭建通过 MindStudio 官网介绍可以学习了解 MindStudio 的功能,以及按照MindStudio 用户手册进行安装和使用。 官网链接:cid:link_5 用户手册: cid:link_1通过官网连接步骤安装好Mindstudio后,点击桌面快捷方式启动 MindStudio,选择不导入配置,点击“OK”,如图2.1。图2.1在 Projects 标签下点击“New Project”创建一个新的工程。选择 Ascend App,输入工程名、和工程目录,点击“Change”选择或者添加CANN 版本,如图2.2。图2.2点击 Remote CANN Setting 对话框中的加号,弹出 SSH Configurations 对话框,然后点击其中的加号,填写红框中的服务器信息,点击“Test Connection” 弹出连接成功对话框,如图2.3。图2.3依次点击“OK”完成 Remote Connection 配置。点击文件夹图标,在弹出的对话框中选择 CANN 安装路径,点击“OK”,如图2.4。图2.4点击Finish后,开始同步远程 CANN 版本资源,如图2.5。图2.5同步完成后点击“Next”,如图2.6。图2.6选择 ACL Project,点击“Finish”,如图2.7。图2.7此时成功创建了一个空的工程,如图2.8。图2.8点击“Tools”->“Start SSH session”,选择远程环境,启动远程终端窗口。如图2.9。图2.9点击“Tools”->“Deployment”->“Configuration”,按图2.10所示,配置远端映射路径。依次点击“OK”完成配置。图2.10快捷键Ctrl+Alt+Shift+S 打开Project Structure 页面,如图2.11所示,点击“SDKs”,点击加号,点击“Add Python SDC...”。图2.11点击“SSH Interpreter”,自动识别远程 Python 环境信息,点击“OK”,如图2.12所示。图2.12点击“Project”,选择创建的 SDK,点击“OK”,如图2.13所示。图2.13点击“Modules”->“Dependence”,选择创建的 SDK,点击“OK”,如图2.14所示。图2.14点击“Tools”-> “Deployment”->“Automatic Upload”。 选择远程服务器,可自动上传修改并保存的文件。 如图2.15所示。图2.15至此 MindStudio 开发环境搭建完成。三、模型获取3.1 获取源码及数据集a.在本地终端中通过 git 命令获取源码,参考命令如下:git clone -b release/2.5 https://github.com/PaddlePaddle/PaddleOCR.git cd PaddleOCR git reset --hard a40f64a70b8d290b74557a41d869c0f9ce4959d5 cd .. b.获取原始数据集 CDAR 2015 数据集包含1000张训练图像和500张测试图像。参考PaddleOCR数据集数据处理方式,ICDAR 2015 数据集可以点击链接进行下载,首次下载需注册。注册完成登陆后,下载图3.1中红色框标出的部分。图3.1在PaddleOCR文件夹下创建如下路径: train_data/icdar2015/text_localization 并将下载好的数据集 ch4_test_images.zip 解压后放在以上路径下,并获取标签文件test_icdar2015_label.txt 如图3.2所示。图3.2c.改模型配置文件 配置不使用 gpu 和以及确认Eval中数据集路径,如图3.3,图3.4。图3.3图3.4图3.53.2安装依赖通过 pip 命令在环境中安装依赖。先执行cd PaddleOCR 命令将目录转到requirement.txt所在文件夹,然后执行命令如下([--user]为可选参数,普通用户需要添加使用):pip3 install -r requirements.txt --user 如图3.6所示:图3.6通过以上步骤,成功获取SAST_ResNet50_vd模型的源代码框架,以及配置成完全运行依赖环境。四、数据预处理4.1添加数据预处理脚本在工程中添加数据预处理脚本,该脚本主要对图片进行归一化操作并转成二进制文件保存如图4.1所示。图4.14.2 设置可执行命令。如图4.2所示,点击下拉按钮,选择“Edit Configurations...”,图4.2如图4.3所示,点击加号,选择“Ascend App”。图4.3如图4.4所示,输入命令名称,选择可执行脚本,点击“OK”。图4.4如图4.5所示,添加如下命令参数,点击“OK”。 --config=PaddleOCR/configs/det/det_r50_vd_east.yml --opt=bin_data=./icdar2015_bin--config:模型配置文件;--opt:bin文件保存路径。图4.5点击执行按钮,进行数据预处理,如图4.6。图4.6通过以上步骤,完成了数据预处理的工作,生成的预处理数据保存在 icdar2015_bin 目录下。五、模型转换5.1 转 onnx 模型获取推理权重文件,权重链接为:cid:link_2 下载之后上传到远程服务器上,并通过PaddleOCR提供的tools/export_model.py 文件转为推理模型,输入命令参数如下: -c ../configs/det/det_r50_vd_sast_icdar15.yml -o Global.pretrained_model=../det_r50_vd_sast_icdar15_v2.0_train/best_accuracy Global.save_inference_dir=../inference/det_r50_sast推理模型存到inference目录下,并上传到远程服务器,如图5.1所示。图5.1在远程终端执行转 onnx 命令,并将生成的 onnx 模型拉取到本地,如图5.2 所示,参考命令如下:paddle2onnx --model_dir PaddleOCR/inference/det_r50_sast --model_filename inference.pdmodel --params_filename inference.pdiparams --save_file PaddleOCR/SAST_ResNet50_vd.onnx --opset_version 11 --enable_onnx_checker True --input_shape_dict="{'x':[1,3,896,1536]}"图5.2通过以上步骤,成功生成并获取 onnx 模型:SAST_ResNet50_vd.onnx5.2 转 om 模型下面使用 MindStudio 的模型转换功能将 onnx 模型转成 om 模型。如5.3图所示,点击“Model Converter”按钮。 图5.3在弹出的 Model Converter 窗口中选择 Model File,点击“OK”,如图5.4。图5.4自动解析模型中,如图5.5。图5.5解析完成后,设置模型名称、soc 版本、om 模型生成目录、通讯模型的 Input Format、Shape、Type 信息,点击“Next”,如图5.6。图5.6当前页签上参数的检查,图5.7。图5.7检查完成后点击“Next”,图5.8。图5.8检视生成的 atc 命令,确认无误后点击“Finish”,图5.9图5.9模型转换成功后,如图5.10所示。图5.10通过以上步骤,使用 MindStudio 的模型转换功能成功将 onnx 模型转成 om模型:SAST_ResNet50_vd_bs1.om。六、模型推理6.1 获取推理工具我们使用 ais-infer 工具进行推理,ais-infer 工具获取及使用方式请查看ais_infer 推理工具使用文档,链接:cid:link_3 a.在本地终端命令中通过 git 获取推理工具代码,命令如下:git clone https://gitee.com/ascend/tools.gitb.将tools\ais-bench_workload\tool\ais_infer 目录下的文件复制到当前 SAST_ResNet50_vd 目录下, 并上传到远程服务器,如图6.1所示。图6.1c.编译并安装 aclruntime 包,如图6.2所示,命令如下,cd ais_infer/backend/ pip3 wheel ./ pip3 install aclruntime-0.0.1-cp37-cp37m-linux_x86_64.whl(如果安装提示已经安装了相同版本的whl,请执行命令请添加参数"--force-reinstall")图6.2通过以上步骤,成功获取 ais_infer 工具,并安装了 aclruntime。6.2 进行模型推理a.创建 results 目录用来保存推理结果,并上传到远程服务器,如图6.3。图6.3b.添加 ais_infer 的可执行命令: --model=../inference/SAST_ResNet50_vd_bs1.om --input=../icdar2015_bin --output=../results/--model:om模型路径;--input:bin文件路径;--output:推理结果保存路径。 点击“OK”,如图6.4所示。图6.4c.执行 ais_infer 命令,完成后在远程服务器上生成推理结果,如图6.5。图6.5d.须将远程生成的结果 load 到本地,否则在执行其他命令进行同步的时候 会删除,如图6.6。图6.6通过以上步骤成功获取了推理结果并保存在了results 目录下。七、模型精度验证7.1 数据后处理a.添加数据后处理脚本,对results文件夹中的预测结果进行精度测试,如图7.1。图7.1b.添加后处理命令:--config=configs/det/det_r50_vd_sast_icdar15.yml --opt=results=results/2022_10_29-09_41_14--config:模型配置文件。--opt:推理结果路径。 点击“OK”,如图7.2图7.2c.执行后处理命令,如7.3。图7.3d. 后处理执行完成后,打印的推理结果如图7.4.图7.47.2精度验证比对通过对比om 推理的后处理推理结果与pth权重精度(开源仓精度)下降不超过1%,说明模型推理精度满足要求。 pth权重精度:后处理推理结果:八、性能测试由于精度验证使用的是源码提供的样例图片,需要使用 ais_infer 工具的纯推理功能进行性能测试。 a.创建性能测试命令:--model=../SAST_ResNet50_vd_bs1.om --loop=50 --batchsize=1--model:om模型路径;--loop:推理次数;--batchsize:om模型的batch。 如图8.1所示。图8.1b.执行性能测试命令,如图8.2所示。图8.2c. 性能测试结果如图8.3所示,为 19.969fps。图8.3九、总结本文主要介绍使用 MindStudio 全流程开发工具链,将 PaddlePaddle 模型转成 om 模型,并在昇腾环境上进行推理的端到端流程。在使用 MindStudio 过程中也遇到过很多问题和不懂的地方,除了参考官方指导文档外,帮助更多的还是开发者社区,如下图所示,推荐大家多看些经验分享,写的很详细也很有帮助。 MindStudio 社区链接为: cid:link_4十、FAQ进行模型转换时,在选择Model File时,出现以下错误:本onnx模型较大,在进行模型转换时需要扩大内存, Help > Change Memory Settings >修改内存大小 改为2048。
-
运行samples/python/level2_simple_inference/2_object_detection/YOLOV3_coco_detection_picture/src/object_detect.py报错报错内容:Traceback (most recent call last):File "object_detect.py", line 127, inmain()File "object_detect.py", line 100, in mainacl_resource.init()File "/root/ky/samples/python/common/acllite/acllite_resource.py", line 83, in initutils.check_ret("acl.rt.set_device", ret)File "/root/ky/samples/python/common/acllite/acllite_utils.py", line 17, in check_retraise Exception("{} failed ret_int={}"Exception: acl.rt.set_device failed ret_int=507033Python版本3.8.2安装各软件如下:A300-3010-npu-driver_5.1.rc2_linux-aarch64.runA300-3010-npu-firmware_5.1.rc2.runAscend-cann-toolkit_6.0.0.alpha002_linux-aarch64.runAscend-cann-nnrt_6.0.0.alpha002_linux-aarch64.runAscend-cann-nnae_6.0.0.alpha002_linux-aarch64.run在/usr/local/Ascend/driver路径下输入 cat version.info:Version=22.0.2ascendhal_version=6.10.16aicpu_version=1.0tdt_version=1.0log_version=1.0prof_version=2.0dvppkernels_version=1.1tsfw_version=1.0Innerversion=V100R001C82SPC002B220package_version=5.1.rc2npu-smi info+------------------------------------------------------------------------------------------------+ | npu-smi 22.0.2 Version: 22.0.2 | +-----------------------+-----------------+------------------------------------------------------+ | NPU Name | Health | Power(W) Temp(C) Hugepages-Usage(page) | | Chip Device | Bus-Id | AICore(%) Memory-Usage(MB) | +=======================+=================+======================================================+ | 16 310 | OK | 12.8 56 0 / 970 | | 0 0 | 0000:03:00.0 | 0 619 / 7764 | +-----------------------+-----------------+------------------------------------------------------+ | 16 310 | OK | 12.8 55 0 / 970 | | 1 1 | 0000:04:00.0 | 0 635 / 7764 | +-----------------------+-----------------+------------------------------------------------------+ | 16 310 | OK | 12.8 55 0 / 970 | | 2 2 | 0000:05:00.0 | 0 635 / 7764 | +-----------------------+-----------------+------------------------------------------------------+ | 16 310 | OK | 12.8 53 0 / 970 | | 3 3 | 0000:06:00.0 | 0 635 / 7764 | +=======================+=================+======================================================+
-
这个问题该怎么解决啊,求求大神解惑
-
昇腾案例助手,提供海量的问题分析思路和解决办法当Atlas 800-3010 执行lspci –vvv后,dmesg打印异常信息怎么办?报错原因理不清?理清原因不知如何解决?如何避免不再出现类似报错?别担心,昇腾案例查询助手来帮您!01 通过昇腾社区首页导航栏-文档,进入昇腾文档中心-文档指引页面点击昇腾案例助手,进入昇腾案例查询助手聚合页。02 涵盖AI加速卡、CANN、MindX DL、MindX Edge等产品大类,为您提供海量问题分析思路与解决办法03 支持通过报错关键字快速搜索查询04 根据案例是否有帮助可以对案例进行评分进入案例详情页,点亮星星05 意见反馈详情页右下角点击进入“建议反馈”页面,提交您的使用意见和建议
推荐直播
-
0代码智能构建AI Agent——华为云AI原生应用引擎的架构与实践
2024/11/13 周三 16:30-18:00
苏秦 华为云aPaaS DTSE技术布道师
大模型及生成式AI对应用和软件产业带来了哪些影响?从企业场景及应用开发视角,面向AI原生应用需要什么样的工具及平台能力?企业要如何选好、用好、管好大模型,使能AI原生应用快速创新?本期直播,华为云aPaaS DTSE技术布道师苏秦将基于华为云自身实践出发,深入浅出地介绍华为云AI原生应用引擎,通过分钟级智能生成Agent应用的方式帮助企业完成从传统应用到智能应用的竞争力转型,使能千行万业智能应用创新。
去报名 -
TinyEngine低代码引擎系列第2讲——向下扎根,向上生长,TinyEngine灵活构建个性化低代码平台
2024/11/14 周四 16:00-18:00
王老师 华为云前端开发工程师,TinyEngine开源负责人
王老师将从TinyEngine 的灵活定制能力出发,带大家了解隐藏在低代码背后的潜在挑战及突破思路,通过实践及运用,帮助大家贴近面向未来低代码产品。
即将直播 -
华为云AI入门课:AI发展趋势与华为愿景
2024/11/18 周一 18:20-20:20
Alex 华为云学堂技术讲师
本期直播旨在帮助开发者熟悉理解AI技术概念,AI发展趋势,AI实用化前景,了解熟悉未来主要技术栈,当前发展瓶颈等行业化知识。帮助开发者在AI领域快速构建知识体系,构建职业竞争力。
即将直播
热门标签