关于华为云的ModelArts模型customize_service

发布于 2022-09-13 00:39:41 字数 7801 浏览 23 评论 0

纯萌新,不懂就问
老师说修改customize_service可以提高map
但是个人完全无从下手

# Copyright 2019 ModelArts Authors from Huawei Cloud. All Rights Reserved.
# https://www.huaweicloud.com/product/modelarts.html
#
# 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.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import numpy as np
from PIL import Image
import json

from model_service.tfserving_model_service import TfServingBaseService

current_dir = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(current_dir, 'index'), 'r') as f:
  index_map = json.loads(f.read())
class_names = index_map['labels_list']
image_shape = index_map['image_shape']

net_h = int(image_shape[0])
net_w = int(image_shape[1])

class_num = len(class_names)

stride_list = [8, 16, 32]
anchors_1 = np.array([[10, 13], [16, 30], [33, 23]]) / stride_list[0]
anchors_2 = np.array([[30, 61], [62, 45], [59, 119]]) / stride_list[1]
anchors_3 = np.array([[116, 90], [156, 198], [373, 326]]) / stride_list[2]
anchor_list = [anchors_1, anchors_2, anchors_3]

conf_threshold = 0.3
iou_threshold = 0.4

colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (0, 255, 255), (255, 0, 255), (255, 255, 0)]


def preprocess(image):
  img_w, img_h = image.size

  scale = min(float(net_w) / float(img_w), float(net_h) / float(img_h))
  new_w = int(img_w * scale)
  new_h = int(img_h * scale)

  shift_x = (net_w - new_w) // 2
  shift_y = (net_h - new_h) // 2
  shift_x_ratio = (net_w - new_w) / 2.0 / net_w
  shift_y_ratio = (net_h - new_h) / 2.0 / net_h

  image_ = image.resize((new_w, new_h))

  new_image = np.zeros((net_h, net_w, 3), np.float32)
  new_image.fill(128)

  new_image[shift_y: new_h + shift_y, shift_x: new_w + shift_x, :] = np.array(image_)

  new_image /= 255.

  return new_image, img_w, img_h, new_w, new_h, shift_x_ratio, shift_y_ratio


def overlap(x1, x2, x3, x4):
  left = max(x1, x3)
  right = min(x2, x4)
  return right - left


def cal_iou(box, truth):
  w = overlap(box[0], box[2], truth[0], truth[2])
  h = overlap(box[1], box[3], truth[1], truth[3])
  if w <= 0 or h <= 0:
    return 0
  inter_area = w * h
  union_area = (box[2] - box[0]) * (box[3] - box[1]) + (truth[2] - truth[0]) * (
  truth[3] - truth[1]) - inter_area
  return inter_area * 1.0 / union_area


def apply_nms(all_boxes, thres):
  res = []

  for cls in range(class_num):
    cls_bboxes = all_boxes[cls]
    sorted_boxes = sorted(cls_bboxes, key=lambda d: d[5])[::-1]

    p = dict()
    for i in range(len(sorted_boxes)):
      if i in p:
        continue

      truth = sorted_boxes[i]
      for j in range(i + 1, len(sorted_boxes)):
        if j in p:
          continue
        box = sorted_boxes[j]
        iou = cal_iou(box, truth)
        if iou >= thres:
          p[j] = 1

    for i in range(len(sorted_boxes)):
      if i not in p:
        res.append(sorted_boxes[i])
  return res


def decode_bbox(conv_output, anchors, img_w, img_h, x_scale, y_scale, shift_x_ratio, shift_y_ratio):
  def _sigmoid(x):
    return min(1,max(0,x))
  h, w, _ = conv_output.shape
  pred = conv_output.reshape((h * w, 3, 5 + class_num))

  pred[..., 4:] = _sigmoid(pred[..., 4:])
  pred[..., 0] = (_sigmoid(pred[..., 0]) + np.tile(range(w), (3, h)).transpose((1, 0))) / w
  pred[..., 1] = (_sigmoid(pred[..., 1]) + np.tile(np.repeat(range(h), w), (3, 1)).transpose(
    (1, 0))) / h
  pred[..., 2] = np.exp(pred[..., 2]) * anchors[:, 0:1].transpose((1, 0)) / w
  pred[..., 3] = np.exp(pred[..., 3]) * anchors[:, 1:2].transpose((1, 0)) / h

  bbox = np.zeros((h * w, 3, 4))
  bbox[..., 0] = np.maximum((pred[..., 0] - pred[..., 2] / 2.0 - shift_x_ratio) * x_scale * img_w,
                            0)  # x_min
  bbox[..., 1] = np.maximum((pred[..., 1] - pred[..., 3] / 2.0 - shift_y_ratio) * y_scale * img_h,
                            0)  # y_min
  bbox[..., 2] = np.minimum((pred[..., 0] + pred[..., 2] / 2.0 - shift_x_ratio) * x_scale * img_w,
                            img_w)  # x_max
  bbox[..., 3] = np.minimum((pred[..., 1] + pred[..., 3] / 2.0 - shift_y_ratio) * y_scale * img_h,
                            img_h)  # y_max

  pred[..., :4] = bbox
  pred = pred.reshape((-1, 5 + class_num))
  pred[:, 4] = pred[:, 4] * pred[:, 5:].max(1)
  pred = pred[pred[:, 4] >= conf_threshold]
  pred[:, 5] = np.argmax(pred[:, 5:], axis=-1)

  all_boxes = [[] for ix in range(class_num)]
  for ix in range(pred.shape[0]):
    box = [int(pred[ix, iy]) for iy in range(4)]
    box.append(int(pred[ix, 5]))
    box.append(pred[ix, 4])
    
    
    
    
    all_boxes[box[4] - 1].append(box)

  return all_boxes


def get_result(model_outputs, img_w, img_h, new_w, new_h, shift_x_ratio, shift_y_ratio):
  num_channel = 3 * (class_num + 5)
  x_scale = net_w / float(new_w)
  y_scale = net_h / float(new_h)
  all_boxes = [[] for ix in range(class_num)]
  for ix in range(3):
    pred = model_outputs[2 - ix].reshape(
      (net_h // stride_list[ix], net_w // stride_list[ix], num_channel))
    anchors = anchor_list[ix]
    boxes = decode_bbox(pred, anchors, img_w, img_h, x_scale, y_scale, shift_x_ratio, shift_y_ratio)
    all_boxes = [all_boxes[iy] + boxes[iy] for iy in range(class_num)]

  res = apply_nms(all_boxes, iou_threshold)

  return res


class Yolov3Service(TfServingBaseService):
  def __init__(self, model_name, model_path):
    super(Yolov3Service, self).__init__(model_name, model_path)

  def _preprocess(self, data):
    self.input_width = int(image_shape[0])
    self.input_height = int(image_shape[1])
    preprocessed_data = {}
    for k, v in data.items():
      for file_name, file_content in v.items():
        input_rgb = Image.open(file_content)

        img_preprocess, self.img_w, self.img_h, self.new_w, self.new_h, \
        self.shift_x_ratio, self.shift_y_ratio = preprocess(input_rgb)
        image = img_preprocess[np.newaxis, :, :, :]
        preprocessed_data[k] = image
    return preprocessed_data

  def _postprocess(self, data):
    result_return = dict()
    #for k, v in data.items():
    res = get_result([data['feat_1'], data['feat_2'], data['feat_3']], self.img_w, self.img_h,
                     self.new_w, self.new_h, self.shift_x_ratio, self.shift_y_ratio)
    if not res:
      result_return['detection_classes'] = []
      result_return['detection_boxes'] = []
      result_return['detection_scores'] = []
      return result_return
    else:
      new_res = np.array(res)
      picked_boxes = new_res[:, 0:4]
      picked_boxes = picked_boxes[:, [1, 0, 3, 2]]
      picked_classes = self.convert_labels(new_res[:, 4])
      picked_score = new_res[:, 5]
      result_return['detection_classes'] = picked_classes
      result_return['detection_boxes'] = picked_boxes.tolist()
      result_return['detection_scores'] = picked_score.tolist()
      return result_return

  def convert_labels(self, label_list):
    """
        class_names = ['person', 'face']
        :param label_list: [1., 1., 1., 1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.]
        :return: 
        """
    if isinstance(label_list, np.ndarray):
      label_list = label_list.tolist()
    label_names = [class_names[int(index)] for index in label_list]
    return label_names

  def ping(self):
    return

  def signature(self):
    pass

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文