Caffe2 - C++ API
A deep learning, cross platform ML framework
GLNormPlanarYUV.cc
1 
2 #include "../core/GLFilter.h"
3 #include "../core/GLImage.h"
4 #include "../core/ImageAllocator.h"
5 
6 #include "caffe2/core/operator.h"
7 #include "caffe2/core/timer.h"
8 #include <iostream>
9 #include <vector>
10 
11 class GLNormPlanarYUV : public GLFilter {
12  public:
13  const float* mean;
14  const float* std;
15 
16  binding* inputData;
17  binding* outputSize;
18  binding* mean_data;
19  binding* std_data;
20 
21  GLNormPlanarYUV(const float* _mean, const float* _std)
22  : GLFilter("GLNormPlanarYUV",
23  vertex_shader,
24  fragment_shader,
25  std::vector<binding*>({BINDING(inputData),
26  BINDING(outputSize),
27  BINDING(mean_data),
28  BINDING(std_data)}), // input bindings
29  {/* no uniform blocks */},
30  {/* no attributes */},
31  {}),
32  mean(_mean),
33  std(_std) {}
34 
35  template <typename T>
36  void normalize(const GLImageVector<T>& input_images, const GLImageVector<T>& output_images);
37 
38  static const char* fragment_shader;
39 };
40 
41 // MARK: GLSL
42 
43 const char* GLNormPlanarYUV::fragment_shader = R"GLSL(#version 300 es
44 
45 precision mediump float;
46 precision mediump int;
47 
48 in highp vec2 v_texCoord;
49 
50 uniform ivec2 outputSize;
51 uniform vec4 mean_data;
52 uniform vec4 std_data;
53 
54 TEXTURE_INPUT(inputData);
55 TEXTURE_OUTPUT(0, outputData);
56 
57 void main() {
58  ivec2 texelCoord = ivec2(v_texCoord * vec2(outputSize));
59  vec4 value = TEXTURE_LOAD(inputData, texelCoord);
60  outputData = TEXTURE_STORE((value - mean_data) / std_data);
61 }
62 
63 )GLSL";
64 
65 template <class T>
66 void GLNormPlanarYUV::normalize(const GLImageVector<T>& input_images,
67  const GLImageVector<T>& output_images) {
68  int num_images = input_images.size();
69  for (int i = 0; i < num_images; i++) {
70  GLImage<T>* input_image = input_images[i];
71  GLImage<T>* output_image = output_images[i];
72  int input_slices = input_image->slices;
73  int output_slices = output_image->slices;
74 
75  for (int is = 0; is < input_slices; is++) {
76 
77  std::vector<texture_attachment> input_attachments({{input_image->textures[is], inputData}});
78 
79  run(input_attachments,
80  {output_image->textures.begin() + is, output_image->textures.begin() + is + 1},
81  [&]() {
82  glUniform2i(outputSize->location, output_image->width, output_image->height);
83  glUniform4f(mean_data->location, mean[0], mean[1], mean[2], 0.0);
84  glUniform4f(std_data->location, std[0], std[1], std[2], 1.0);
85  },
86  output_image->width,
87  output_image->height);
88  }
89  }
90 }
91 
92 namespace caffe2 {
93 template <typename T>
94 class GLNormPlanarYUVOp final : public Operator<CPUContext>, ImageAllocator<T> {
95  public:
96  GLNormPlanarYUVOp(const OperatorDef& operator_def, Workspace* ws)
97  : Operator<CPUContext>(operator_def, ws),
98  order_(StringToStorageOrder(OperatorBase::GetSingleArgument<string>("order", "NCHW"))) {
99  OPERATOR_NEEDS_FEATURE(this->order_ == StorageOrder::NCHW, "OpenGL only supports NCHW order.");
100  }
101 
102  bool RunOnDevice() override {
103  const GLImageVector<T>& input = Inputs()[0]->template Get<GLImageVector<T>>();
104  const int num_images = input.size();
105  const int input_channels = input.channels();
106  const int input_width = input.width();
107  const int input_height = input.height();
108 
109  const int output_channels = input_channels;
110  const int output_width = input_width;
111  const int output_height = input_height;
112 
113  int is_last = OperatorBase::GetSingleArgument<int>("is_last", 0);
114 
116  num_images, output_width, output_height, output_channels, is_last);
117 
118  const auto& M = Input(1); // mean
119  const auto& S = Input(2); // standard deviation
120  CAFFE_ENFORCE(input_channels == M.dim(1));
121  CAFFE_ENFORCE(input_channels == S.dim(1));
122 
123  if (!_normPlanarYUV) {
124  _normPlanarYUV.reset(new GLNormPlanarYUV(M.template data<float>(), S.template data<float>()));
125  }
126 
127  _normPlanarYUV->normalize(input, *output);
128 
129  Outputs()[0]->Reset(output);
130 
131  return true;
132  }
133 
134  private:
135  StorageOrder order_;
136  std::unique_ptr<GLNormPlanarYUV> _normPlanarYUV;
137 };
138 
139 REGISTER_CPU_OPERATOR(OpenGLNormalizePlanarYUV, GLNormPlanarYUVOp<float16_t>);
140 OPERATOR_SCHEMA(OpenGLNormalizePlanarYUV).NumInputs(3).NumOutputs(1);
141 
142 } // namespace caffe2
Definition: types.h:72
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
Definition: workspace.h:47
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...