reader_op.cpp 5.1 KB
Newer Older
W
wangguibao 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Copyright (c) 2019 PaddlePaddle Authors. 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.

W
serving  
wangguibao 已提交
15
#include "op/reader_op.h"
W
wangguibao 已提交
16
#include <algorithm>
W
serving  
wangguibao 已提交
17 18 19 20 21 22 23 24 25 26 27
#include "framework/memory.h"

namespace baidu {
namespace paddle_serving {
namespace serving {

using baidu::paddle_serving::predictor::MempoolWrapper;
using baidu::paddle_serving::predictor::format::XImageReqInstance;
using baidu::paddle_serving::predictor::image_classification::Request;

int ReaderOp::inference() {
W
wangguibao 已提交
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
  const Request* req = dynamic_cast<const Request*>(get_request_message());
  LOG(INFO) << "Receive request in dense service:" << req->ShortDebugString();

  ReaderOutput* res = mutable_data<ReaderOutput>();
  if (!res) {
    LOG(ERROR) << "Failed get op tls reader object output";
    return -1;
  }

  TensorVector* in = &res->tensors;
  uint32_t sample_size = req->instances_size();
  if (sample_size <= 0) {
    LOG(WARNING) << "No instances need to inference!";
    return -1;
  }

  // TODO(xxx) pmeans/scales/isize/enable_crop should be configurable.
  float pmean[3] = {0.485 * 255, 0.456 * 255, 0.406 * 255};
  float scale[3] = {1 / (0.229 * 255), 1 / (0.224 * 255), 1 / (0.225 * 255)};
  size_t iresize[] = {244, 244};  // row, column
  bool enable_crop = true;

  cv::Size resize;
  resize.height = iresize[0];
  resize.width = iresize[1];

  for (uint32_t si = 0; si < sample_size; si++) {
    // parse image object from x-image
    const XImageReqInstance& ins = req->instances(si);
    // read dense image from request bytes
    const char* binary = ins.image_binary().c_str();
    size_t length = ins.image_length();
    if (length == 0) {
      LOG(ERROR) << "Empty image, length is 0";
      return -1;
W
serving  
wangguibao 已提交
63 64
    }

W
wangguibao 已提交
65 66 67 68 69 70 71
    _image_vec_tmp.clear();
    _image_vec_tmp.assign(binary, binary + length);
    _image_8u_tmp = cv::imdecode(cv::Mat(_image_vec_tmp),
                                 CV_LOAD_IMAGE_COLOR /*1*/);  // in B/G/R order.
    if (_image_8u_tmp.data == NULL) {
      LOG(ERROR) << "Image decode failed!";
      return -1;
W
serving  
wangguibao 已提交
72 73
    }

W
wangguibao 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    // accumulate length
    const int HH = _image_8u_tmp.rows;
    const int WW = _image_8u_tmp.cols;
    const int CC = _image_8u_tmp.channels();

    // resize/crop
    if (_image_8u_tmp.cols != resize.width ||
        _image_8u_tmp.rows != resize.height) {
      int short_egde = std::min<int>(_image_8u_tmp.cols, _image_8u_tmp.rows);
      int yy = static_cast<int>((_image_8u_tmp.rows - short_egde) / 2);
      int xx = static_cast<int>((_image_8u_tmp.cols - short_egde) / 2);
      _image_8u_tmp =
          cv::Mat(_image_8u_tmp, cv::Rect(xx, yy, short_egde, short_egde));
      if (_image_8u_tmp.cols != resize.width ||
          _image_8u_tmp.rows != resize.height) {
        cv::Mat resize_image;
        cv::resize(_image_8u_tmp, resize_image, resize);
        _image_8u_tmp = resize_image;
      }

      LOG(INFO) << "Succ crop one image[CHW=" << _image_8u_tmp.channels()
                << ", " << _image_8u_tmp.cols << ", " << _image_8u_tmp.rows
                << "]"
                << " from image[CHW=" << CC << ", " << HH << ", " << WW << "]";
    }
W
serving  
wangguibao 已提交
99

W
wangguibao 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
    // BGR->RGB transformer
    cv::cvtColor(_image_8u_tmp, _image_8u_rgb, CV_BGR2RGB);

    const int H = _image_8u_rgb.rows;
    const int W = _image_8u_rgb.cols;
    const int C = _image_8u_rgb.channels();
    size_t dense_capacity = H * W * C;

    paddle::PaddleTensor in_tensor;
    in_tensor.name = "tensor";
    in_tensor.dtype = paddle::FLOAT32;

    // shape assignment
    in_tensor.shape.push_back(1);  // batch_size

    // accoreding to training stage, the instance shape should be
    // in order of C-W-H.
    in_tensor.shape.push_back(C);
    in_tensor.shape.push_back(W);
    in_tensor.shape.push_back(H);

    LOG(INFO) << "Succ read one image, C: " << C << ", W: " << W
              << ", H: " << H;

    // tls resource assignment
    size_t len = dense_capacity * sizeof(float);
    float* data =
        reinterpret_cast<float*>(MempoolWrapper::instance().malloc(len));
    if (data == NULL) {
      LOG(ERROR) << "Failed create temp float array, "
                 << "size=" << dense_capacity;
      return -1;
    }
W
serving  
wangguibao 已提交
133

W
wangguibao 已提交
134 135 136 137 138 139 140
    for (int h = 0; h < H; h++) {
      // p points to a new line
      unsigned char* p = _image_8u_rgb.ptr<unsigned char>(h);
      for (int w = 0; w < W; w++) {
        for (int c = 0; c < C; c++) {
          // HWC(row,column,channel) -> CWH
          data[W * H * c + W * h + w] = (p[C * w + c] - pmean[c]) * scale[c];
W
serving  
wangguibao 已提交
141
        }
W
wangguibao 已提交
142 143
      }
    }
W
serving  
wangguibao 已提交
144

W
wangguibao 已提交
145 146
    paddle::PaddleBuf pbuf(data, len);
    in_tensor.data = pbuf;
W
serving  
wangguibao 已提交
147

W
wangguibao 已提交
148 149
    in->push_back(in_tensor);
  }
W
serving  
wangguibao 已提交
150

W
wangguibao 已提交
151
  return 0;
W
serving  
wangguibao 已提交
152 153 154 155
}

DEFINE_OP(ReaderOp);

W
wangguibao 已提交
156 157 158
}  // namespace serving
}  // namespace paddle_serving
}  // namespace baidu