本篇內(nèi)容主要講解“PyQt如何利用飛槳進行預測”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“PyQt如何利用飛槳進行預測”吧!
成都創(chuàng)新互聯(lián)公司服務項目包括華安網(wǎng)站建設、華安網(wǎng)站制作、華安網(wǎng)頁制作以及華安網(wǎng)絡營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網(wǎng)行業(yè)的解決方案,華安網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務的客戶以成都為中心已經(jīng)輻射到華安省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!
介紹模型的保存和加載,目的是更好地了解飛槳預測過程。本文主要介紹模型保存函數(shù):fluid.io.save_params;fluid.io.save_inference_model和模型加載函數(shù) ;fluid.io.save_params ;fluid.io.load_inference_model。
1)fluid.io.save_params
fluid.io.save_params:從字面意思來理解,表示保存參數(shù)。而該函數(shù)的主要目的也確實是保存訓練過程中生成的各個節(jié)點之間的參數(shù)(權重、偏置等),使用fluid.io.save_params進行模型的保存,其保存的內(nèi)容如下圖所示:
2)fluid.io.save_inference_model
fluid.io.save_inference_model:從字面上理解,表示保存可進行后續(xù)預測的模型。而該函數(shù)的主要目的也確實是保存可進行預測的模型。即調(diào)用save_inference_model函數(shù),可在save_params所保存的參數(shù)基礎上融合網(wǎng)絡結構生成的可進行預測的模型。這一點類似于tensorflow將訓練出來的ckpt文件固化成pb文件。從我們git中下載的PaddleDetection代碼,在PaddleDetection-release/tools/export_model中就是利用save_inference_model導出結合后的模型。
利用export_model.py保存下來的文件如下所示:生成了兩個文件,__model__和__params__文件,其中__model__表示網(wǎng)絡結構,__params__表示訓過程產(chǎn)生的參數(shù)。
1) fluid.io.load_params
fluid.io.load_params:根據(jù)上文得知,該函數(shù)表示加載訓練過程中的參數(shù)進行預測,如果要加載參數(shù)進行預測,則需要將網(wǎng)絡結構也加載進來,PaddleDetection給出的官方預測示例就是利用該方式進行預測。
2) fluid.io.load_inference_model
fluid.io.load_inference_model:根據(jù)上文得知,該函數(shù)表示加載參數(shù)和網(wǎng)絡結構的融合體進行預測。作者在如下的內(nèi)容中就是使用該方式進行預測。
1) 備注一
前面生成的模型文件中,__model__文件包含了NMS部分(這一點和tensorflow的pb文件不同,pb文件是沒有NMS節(jié)點的)。關于__model__文件,我們可以使用Netron進行展開。Netron使用地址https://lutzroeder.github.io/netron/。打開以后可看到網(wǎng)絡結構,在最下端發(fā)現(xiàn)有NMS節(jié)點。
2) 備注二
除了上述談到的模型加載和保存的方式,還有另外一組即fluid.io.save_persistables和fluid.io.load_persistables。
PaddleDetection里面已經(jīng)有了相應的預測代碼infer.py,該代碼利用paddle的reader機制進行圖像的預測,同時該代碼使用的加載模型的方式是fluid.io.load_params。作者個人為了能配合后續(xù)在qt下運行檢測,使用fluid.io.load_inference_model作為模型的加載方式,從paddle的AI Studio上截取一部分代碼重新構造了預測代碼。本段預測代碼加載的模型是yolov3(主干網(wǎng)絡MobileNet)訓練出來的模型。
作者構造自身的預測代碼思路如下圖所示:
代碼如下:
說明:
1. 該代碼由于使用參數(shù)和網(wǎng)絡結構融合的模型,因此對于其他庫的依賴比較少,只需要將飛槳導入即可,
2. 該代碼由于使用的模型文件是《__model__和__params__》,因此在使用load_inference__model時候,必須在該函數(shù)的參數(shù)中指明這兩個名字。
3. 該代碼中需要著重注意一下一點:由于預測加載的模型是使用yolov3訓練出來的模型,因此在進行預測時要考慮圖像歸一化的操作,數(shù)據(jù)歸一化的操作來源訓練該模型的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, :]},備注:此時送入網(wǎng)絡進行預測的圖像大小是原圖的尺寸大小。 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)
1. 首先通過步驟1配置好的PyQt中QT Designer,創(chuàng)建兩個Button對象,分別為“打開相機”、“開始檢測”,然后創(chuàng)建兩個Label對象,分別用于顯示相機原圖和顯示檢測后圖像。
2. 創(chuàng)建多線程檢測機制,分別給兩個Button設置不同的槽函數(shù),分別用于觸發(fā)相機拍照和調(diào)用檢測函數(shù)。運行infe_video.py可得到如下結果。由于作者使用的是黑白相機拍攝電腦屏幕上百度搜索出來的橘子照片,檢測效果質(zhì)量不高。
到此,相信大家對“PyQt如何利用飛槳進行預測”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!