Blame view

3rdparty/opencv-4.5.4/modules/dnn/src/layers/flow_warp_layer.cpp 4.24 KB
f4334277   Hu Chunming   提交3rdparty
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
63
64
65
66
67
68
69
70
71
72
73
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  // This file is part of OpenCV project.
  // It is subject to the license terms in the LICENSE file found in the top-level directory
  // of this distribution and at http://opencv.org/license.html.
  
  // Copyright (C) 2020, Intel Corporation, all rights reserved.
  // Third party copyrights are property of their respective owners.
  
  #include "../precomp.hpp"
  #include "layers_common.hpp"
  
  
  namespace cv { namespace dnn {
  
  class FlowWarpLayerImpl CV_FINAL : public FlowWarpLayer
  {
  public:
      FlowWarpLayerImpl(const LayerParams& params)
      {
          setParamsFrom(params);
          String fill_string = toLowerCase(params.get<String>("FillParameter", "ZERO"));
          if (fill_string != "zero")
              CV_Error(Error::StsNotImplemented, "Only zero filling supported.");
          fill_value = 0;
      }
  
      virtual bool getMemoryShapes(const std::vector<MatShape> &inputs,
                                   const int requiredOutputs,
                                   std::vector<MatShape> &outputs,
                                   std::vector<MatShape> &internals) const CV_OVERRIDE
      {
          CV_Assert(inputs.size() == 2);
          CV_Assert_N(inputs[0][0] == inputs[1][0], inputs[1][1] == 2,
                      inputs[0][2] == inputs[1][2], inputs[0][3] == inputs[1][3]);
  
          outputs.assign(1, inputs[0]);
          return false;
      }
  
      void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
      {
          CV_TRACE_FUNCTION();
          CV_TRACE_ARG_VALUE(name, "name", name.c_str());
  
          std::vector<Mat> inputs, outputs;
          inputs_arr.getMatVector(inputs);
          outputs_arr.getMatVector(outputs);
  
          const int out_n = outputs[0].size[0];
          const int out_c = outputs[0].size[1];
          const int out_h = outputs[0].size[2];
          const int out_w = outputs[0].size[3];
  
          const int area = out_w * out_h;
          const int total = area * out_c;
  
          const float* image_data = inputs[0].ptr<float>();
          const float* flow_data  = inputs[1].ptr<float>();
          float* out_data = outputs[0].ptr<float>();
  
          for (int n = 0; n < out_n; n++)
          {
              int off = total * n;
              for (int x = 0; x < out_w; x++)
              {
                  for (int y = 0; y < out_h; y++)
                  {
                      int idx = 2 * area * n + y * out_w + x;
                      float fx = flow_data[idx];
                      float fy = flow_data[idx + area];
  
                      float x2 = x + fx;
                      float y2 = y + fy;
  
                      if (x2 >= 0 && y2 >= 0 && x2 < out_w && y2 < out_h)
                      {
                          int ix2_L = x2;
                          float alpha = x2 - ix2_L;
  
                          int iy2_T = y2;
                          float beta = y2 - iy2_T;
  
                          int ix2_R = std::min(ix2_L + 1, out_w - 1);
                          int iy2_B = std::min(iy2_T + 1, out_h - 1);
  
                          for (int c = 0; c < out_c; c++)
                          {
                              float TL = image_data[off + c * area + iy2_T * out_w + ix2_L];
                              float TR = image_data[off + c * area + iy2_T * out_w + ix2_R];
                              float BL = image_data[off + c * area + iy2_B * out_w + ix2_L];
                              float BR = image_data[off + c * area + iy2_B * out_w + ix2_R];
  
                              out_data[off + c * area + y * out_w + x] = (1 - alpha) * (1 - beta) * TL +
                                                                         (1 - alpha) * beta       * BL +
                                                                          alpha      * (1 - beta) * TR +
                                                                          alpha      * beta       * BR;
                          }
                      }
                      else
                      {
                          for (int c = 0; c < out_c; c++)
                              out_data[off + c * area + y * out_w + x] = fill_value;
                      }
                  }
              }
          }
      }
  
  private:
      float fill_value;
  };
  
  Ptr<FlowWarpLayer> FlowWarpLayer::create(const LayerParams& params)
  {
      return Ptr<FlowWarpLayer>(new FlowWarpLayerImpl(params));
  }
  
  }}  // namespace cv::dnn