1、创建项目相关的目录结构
?1.1 一个目录和两个文件
? ?首先需要创建一个文件夹 mask 用于模型结构的输出,文件夹下创建 __init__.py 、 module.py 文件用于保存具体的模型导出信息。当然文件夹的名字可自定义,其实就相当于 python 中的包的定义,相关的其余导出模型也放在此文件夹下,方便脚本的模型调用。
?1.2 module 文件信息
??此脚本文件中需要编写具体的模型信息。
??首先需要导入相关的依赖库,除了自己模型需要的包之外,还需要导入以下两个必须的包,用于模型的打包输出:
??其次需要填写模型的相关信息,在倒完包就可以写入,各参数见名之意:
-
@moduleinfo(
name="mask",
version="1.0.0",
summary="This is a PaddleHub Module. Just for test.",
author="beordie",
author_email="",
type="mask",
)
??最后将需要打包输出的模型代码进行封装,然后将对象全局化申明,以便后面的模型使用:
-
class MaskPredict:
def __init__(self, in_path = 'img', out_path = 'demo'):
self.maskNet = load_model('/home/aistudio/work/mask_detector.model')
self.in_path = in_path
self.out_path = out_path
def Iou(self, bbox1, bbox2):
area1 = (bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1])
area2 = (bbox2[2] - bbox2[0]) * (bbox2[3] - bbox2[1])
w = min(bbox1[3], bbox2[3]) - max(bbox1[1], bbox2[1])
h = min(bbox1[2], bbox2[2]) - max(bbox1[0], bbox2[0])
if w <= 0 or h <= 0:
return 0
area_mid = w * h
return area_mid / (area1 + area2 - area_mid)
def GetFace(self):
files = os.listdir(self.in_path)
face_detector = hub.Module(name="pyramidbox_lite_server")
for i in range(len(files)):
faces = []
preds = []
img = cv2.imread(self.in_path + '/%d.jpg' % i)
result = face_detector.face_detection(images=[img])
img = img_to_array(img)
data = result[0]['data']
bbox_upgrade = []
index = []
for j in range(len(data)):
left, right = int(data[j]['left']), int(data[j]['right'])
top, bottom = int(data[j]['top']), int(data[j]['bottom'])
bbox = (left, top, right, bottom)
if right > 1600 and bottom > 1600:
for k in range(len(bbox_buffer)):
if Iou(bbox, bbox_buffer[k]) > 0.1 and k not in index:
index.append(k)
break
bbox_upgrade.append((left, top, right, bottom))
else:
preds.append([left, top, right, bottom])
faces.append(img[top:bottom, left:right])
bbox_buffer = bbox_upgrade.copy()
if len(faces) > 0:
count = 0
for face in faces:
face = cv2.cvtColor(face, cv2.COLOR_BGR2RGB)
face = cv2.resize(face, (224, 224))
face = img_to_array(face)
face = preprocess_input(face)
face = np.expand_dims(face, axis=0)
(mask, withoutMask) = self.maskNet.predict(face)[0]
lable = "Mask" if mask > withoutMask else "No Mask"
color = (0, 255, 0) if lable == "Mask" else (0, 0, 255)
lable = "{}:{:.2f}%".format(lable, max(mask, withoutMask) * 100)
cv2.putText(img, lable, (preds[count][0], preds[count][1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.45, color,
2)
cv2.rectangle(img, (preds[count][0], preds[count][1]), (preds[count][2], preds[count][3]), color, 2)
count += 1
cv2.imwrite(self.out_path + '/%d.jpg' % i, img)
print('正在进行{}张图的处理'.format(i))
mask = MaskPredict()
??这样就完成简单的模型的导出准备工作,当然如果需要其他的功能,还需要在进行参数的编写。
?1.3 命令行调用和服务部署
????如果希望 Module 可以支持命令行调用(动态的指定需要的参数解析),则需要提供一个经过 runnable 修饰的接口(即一个用 @runnable 进行修饰的方法),接口负责解析传入参数并进行模型的预测,将结果返回。如果不需要提供命令行功能,则可以不实现该接口,PaddleHub 在用命令行执行时,会自动发现该 Module 不支持命令行方式,并给出相应的提示。
-
配置解析参数
self.parser = argparse.ArgumentParser(
description="Run the mnist_predict module.",
prog='hub run mnist_predict',
usage='%(prog)s',
add_help=True)
self.parser.add_argument('--img', type=str, default=None, help="img to predict")
-
@runnable
def runnable(self, argvs):
args = self.parser.parse_args(argvs)
self.in_path = args['img']
return self.GetFace()
????如果希望 Module 可以支持 PaddleHub Serving 部署预测服务,则需要提供一个经过 serving 修饰的接口,接口负责解析传入数据并进行预测,将结果返回。如果不需要提供 PaddleHub Serving 部署预测服务,则可以不需要加上serving修饰。
2、模型的安装使用
????在 module.py 中编写好代码后,就可以通过 hub install 文件名 的方式来安装模型了,当然需要 cd 到父级目录下,不然报一堆 XXXX 怀疑人生。
????之后便可以向普通的模型一样进行导出使用了。
|