reader_op.cpp 5.3 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
wangguibao 已提交
15
#include "demo-serving/op/reader_op.h"
W
wangguibao 已提交
16
#include <algorithm>
W
wangguibao 已提交
17
#include "predictor/framework/memory.h"
W
serving  
wangguibao 已提交
18 19 20 21 22 23 24 25 26 27

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
  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];

W
Wang Guibao 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
  paddle::PaddleTensor in_tensor;
  in_tensor.name = "tensor";
  in_tensor.dtype = paddle::FLOAT32;
  // shape assignment
  in_tensor.shape.push_back(sample_size);  // batch_size
  in_tensor.shape.push_back(3);
  in_tensor.shape.push_back(resize.width);
  in_tensor.shape.push_back(resize.height);

  // tls resource assignment
  size_t dense_capacity = 3 * resize.width * resize.height;
  size_t len = dense_capacity * sizeof(float) * sample_size;
  float* data =
      reinterpret_cast<float*>(MempoolWrapper::instance().malloc(len));
  if (data == NULL) {
    LOG(ERROR) << "Failed create temp float array, "
               << "size=" << dense_capacity * sample_size * sizeof(float);
    return -1;
  }

W
wangguibao 已提交
74 75 76 77 78 79 80 81 82
  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 已提交
83 84
    }

W
wangguibao 已提交
85 86 87 88 89 90 91
    _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 已提交
92 93
    }

W
wangguibao 已提交
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
    // 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 已提交
119

W
wangguibao 已提交
120 121 122 123 124 125
    // 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();
W
Wang Guibao 已提交
126 127 128 129
    if (H != resize.height || W != resize.width || C != 3) {
      LOG(ERROR) << "Image " << si << " has incompitable size";
      return -1;
    }
W
wangguibao 已提交
130 131 132 133

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

W
Wang Guibao 已提交
134
    float* data_ptr = data + dense_capacity * si;
W
wangguibao 已提交
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
W
Wang Guibao 已提交
141 142
          data_ptr[W * H * c + W * h + w] =
              (p[C * w + c] - pmean[c]) * scale[c];
W
serving  
wangguibao 已提交
143
        }
W
wangguibao 已提交
144 145 146
      }
    }
  }
W
Wang Guibao 已提交
147 148 149 150
  paddle::PaddleBuf pbuf(data, len);
  in_tensor.data = pbuf;

  in->push_back(in_tensor);
W
serving  
wangguibao 已提交
151

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

DEFINE_OP(ReaderOp);

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