本篇内容主要讲解“PyQt如何利用飞桨进行预测”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PyQt如何利用飞桨进行预测”吧!
通过飞桨保存模型和加载模型
介绍模型的保存和加载,目的是更好地了解飞桨预测过程。本文主要介绍模型保存函数:fluid.io.save_params;fluid.io.save_inference_model和模型加载函数 ;fluid.io.save_params ;fluid.io.load_inference_model。
1. 模型的保存
1)fluid.io.save_params
fluid.io.save_params:从字面意思来理解,表示保存参数。而该函数的主要目的也确实是保存训练过程中生成的各个节点之间的参数(权重、偏置等),使用fluid.io.save_params进行模型的保存,其保存的内容如下图所示:
2)fluid.io.save_inference_model
fluid.io.save_inference_model:从字面上理解,表示保存可进行后续预测的模型。而该函数的主要目的也确实是保存可进行预测的模型。即调用save_inference_model函数,可在save_params所保存的参数基础上融合网络结构生成的可进行预测的模型。这一点类似于tensorflow将训练出来的ckpt文件固化成pb文件。从我们git中下载的PaddleDetection代码,在PaddleDetection-release/tools/export_model中就是利用save_inference_model导出结合后的模型。
利用export_model.py保存下来的文件如下所示:生成了两个文件,__model__和__params__文件,其中__model__表示网络结构,__params__表示训过程产生的参数。
2. 模型的加载
1) fluid.io.load_params
fluid.io.load_params:根据上文得知,该函数表示加载训练过程中的参数进行预测,如果要加载参数进行预测,则需要将网络结构也加载进来,PaddleDetection给出的官方预测示例就是利用该方式进行预测。
2) fluid.io.load_inference_model
fluid.io.load_inference_model:根据上文得知,该函数表示加载参数和网络结构的融合体进行预测。作者在如下的内容中就是使用该方式进行预测。
3. 备注
1) 备注一
前面生成的模型文件中,__model__文件包含了NMS部分(这一点和tensorflow的pb文件不同,pb文件是没有NMS节点的)。关于__model__文件,我们可以使用Netron进行展开。Netron使用地址https://lutzroeder.github.io/netron/。打开以后可看到网络结构,在最下端发现有NMS节点。
2) 备注二
除了上述谈到的模型加载和保存的方式,还有另外一组即fluid.io.save_persistables和fluid.io.load_persistables。
如何利用飞桨进行预测?
PaddleDetection里面已经有了相应的预测代码infer.py,该代码利用paddle的reader机制进行图像的预测,同时该代码使用的加载模型的方式是fluid.io.load_params。作者个人为了能配合后续在qt下运行检测,使用fluid.io.load_inference_model作为模型的加载方式,从paddle的AI Studio上截取一部分代码重新构造了预测代码。本段预测代码加载的模型是yolov3(主干网络MobileNet)训练出来的模型。
作者构造自身的预测代码思路如下图所示:
代码如下:
说明:
1. 该代码由于使用参数和网络结构融合的模型,因此对于其他库的依赖比较少,只需要将飞桨导入即可,
2. 该代码由于使用的模型文件是《__model__和__params__》,因此在使用load_inference__model时候,必须在该函数的参数中指明这两个名字。
3. 该代码中需要着重注意一下一点:由于预测加载的模型是使用yolov3训练出来的模型,因此在进行预测时要考虑图像归一化的操作,数据归一化的操作来源训练该模型的config文件,输入图像大小需要和export model时设置的图像大小保持一致
import numpy as np import time import paddle.fluid as fluid from PIL import Image from PIL import ImageDraw train_parameters = { "label_dict": {0:"apple",1:"banana",2:"orange"}, "use_gpu": True, "input_size": [3, 608, 608], # 原版的边长大小为608,为了提高训练速度和预测速度,此处压缩为448 } target_size = train_parameters['input_size'] anchors = train_parameters['anchors'] anchor_mask = train_parameters['anchor_mask'] label_dict = train_parameters['label_dict'] print(label_dict[1]) # class_dim = train_parameters['class_dim'] # print("label_dict:{} class dim:{}".format(label_dict, class_dim)) place = fluid.CUDAPlace(0) if train_parameters['use_gpu'] else fluid.CPUPlace() exe = fluid.Executor(place) path="C://Users//zhili//Desktop//2"#_mobilenet_v1 [inference_program, feed_target_names, fetch_targets] = fluid.io.load_inference_model(dirname=path, executor=exe,model_filename='__model__', params_filename='__params__') class inference(): def __init__(self): print("8888888888") def draw_bbox_image(self,img, boxes, labels,scores, save_name): """ 给图片画上外接矩形框 :param img: :param boxes: :param save_name: :param labels :return: """ draw = ImageDraw.Draw(img) for box, label,score in zip(boxes, labels,scores): print(box, label, score) if(score >0.9): xmin, ymin, xmax, ymax = box[0], box[1], box[2], box[3] draw.rectangle((xmin, ymin, xmax, ymax), 3, 'red') draw.text((xmin, ymin), label_dict[label], (255, 255, 0)) img.save(save_name) def resize_img(self,img, target_size):#将图片resize到target_size """ 保持比例的缩放图片 :param img: :param target_size: :return: """ img = img.resize(target_size[1:], Image.BILINEAR) return img def read_image(self,img_path): origin = Image.open(img_path) img = self.resize_img(origin, target_size) resized_img = img.copy() if img.mode != 'RGB': img = img.convert('RGB') img = np.array(img).astype('float32').transpose((2, 0, 1)) # HWC to CHW 让矩阵进行方向的转置 img = img / 255.0 img[0, :, :] -= 0.485 img[1, :, :] -= 0.456 img[2, :, :] -= 0.406 img[0, :, :] /=0.229 img[1, :, :] /=0.224 img[2, :, :] /=0.225 img = img[np.newaxis, :] return origin, img, resized_img def infer(self,image_path): """ 预测,将结果保存到一副新的图片中 :param image_path: :return: """ origin, tensor_img, resized_img = self.read_image(image_path) input_w, input_h = origin.size[0], origin.size[1] image_shape = np.array([input_h, input_w], dtype='int32') t1 = time.time() batch_outputs = exe.run(inference_program, feed={feed_target_names[0]: tensor_img, feed_target_names[1]: image_shape[np.newaxis, :]},备注:此时送入网络进行预测的图像大小是原图的尺寸大小。 fetch_list=fetch_targets, return_numpy=False) period = time.time() - t1 print("predict cost time:{0}".format("%2.2f sec" % period)) bboxes = np.array(batch_outputs[0]) if bboxes.shape[1] != 6: print("No object found in {}".format(image_path)) return labels = bboxes[:, 0].astype('int32') scores = bboxes[:, 1].astype('float32') boxes = bboxes[:, 2:].astype('float32') last_dot_index = image_path.rfind('.') out_path = image_path[:last_dot_index] out_path += '-result.jpg' self.draw_bbox_image(origin, boxes, labels,scores, out_path) if __name__ == '__main__': image_path= "C://Users//zhili//Desktop//123//2.jpg" a=inference() a.infer(image_path)
PyQt5检测效果
1. 首先通过步骤1配置好的PyQt中QT Designer,创建两个Button对象,分别为“打开相机”、“开始检测”,然后创建两个Label对象,分别用于显示相机原图和显示检测后图像。
2. 创建多线程检测机制,分别给两个Button设置不同的槽函数,分别用于触发相机拍照和调用检测函数。运行infe_video.py可得到如下结果。由于作者使用的是黑白相机拍摄电脑屏幕上百度搜索出来的橘子照片,检测效果质量不高。
到此,相信大家对“PyQt如何利用飞桨进行预测”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/223556.html