【进迭时空 K1 MUSE Pi Pro】基于OpenCL的FastDepth部署和扩展板设计

该项目通过OpenCL调用Muse Pi Pro的NPU进行FastDepth算法的部署,并设计扩展板用于LCD显示和电机驱动

【进迭时空 K1 MUSE Pi Pro】基于OpenCL的FastDepth部署和扩展板设计封面
Zerolinr2026-11-09 08:54:53Apache-2.0
4
Star

PCBA

设计文件

MusePiPro.zip7.24MB(0次下载)

生产BOM

源代码

详细介绍

【进迭时空 K1 MUSE Pi Pro】基于OpenCL的FastDepth部署和扩展板设计

一、扩展板设计

1. 接口

  • 12V电源输入接口

  • 5V电压输出接口

  • 电机三相输入接口

  • 硬件I2C接口

  • ST7789/LCD 驱动接口

  • USB转TTL接口

2. 原理图

3. PCB

4. 实物图

二、基于OpenCL的FastDepth部署

1. python环境搭建

首先安装虚拟环境容器

  • sudo apt-get install python3-virtualenv

之后运行命令创建虚拟环境,与主环境进行隔离,myenv可以换成任意名字

  • virtualenv myenv

运行虚拟环境激活脚本,进入虚拟环境

  • source myenv/bin/activate

升级pip版本

  • pip install --upgrade pip

设置pip安装源

这个项目需要用到onnx,onnxruntime,提取onnx模型参数,所以安装这几个库。如果安装opencv-python会直接安装python3.10版本的opencv-python,而python版本是3.12,会有兼容错误,这里用PIL库替代

  • pip install onnx

  • pip install onnxruntime

  • pip install pillow

2. c++环境搭建

项目需要用到opencv获取图像数据,以及cnpy库读取权重参数,所以克隆这两个库

对cnpy进行编译

  • cd cnpy

  • mkdir build

  • cd build

  • cmake .. -DCMAKE_ISNTALL_PREFIX=../install

  • make -j4

  • sudo make install

对opencv进行编译

  • cd opencv

  • mkdir build

  • cd build

  • cmake .. -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=Release -DOPENCV_EXTRA_MODULES_PATH = ../../opencv_contrib

  • make -j4

  • sudo make -install

3. ONNX参数提取

该项目选用fastdepth的onnx模型进行部署

创建一个python脚本处理onnx,主要做下面的三个步骤

  • 提取各个卷积层的权重参数

  • 各个卷积层参数的数量

  • 各个卷积层的padding,stride和kernel_shape

  • 各个层的输入和输出张量的维度大小

代码如下:

import onnx
from onnx import helper, numpy_helper
import onnxruntime as ort
import numpy as np

model_path = "/home/ray/Documents/i2c_lcd/fastestdepth.onnx"

WEIGHTS_CPP_PATH = "/home/ray/Documents/i2c_lcd/fastdepth/source/weights.cpp"
WEIGHTS_NPY_PATH = "/home/ray/Documents/i2c_lcd/fastdepth/npy/weights.npy"

if __name__ == "__main__":
  model = onnx.load(model_path)

#.................... 新建weights.cpp写入参数
  f = open(WEIGHTS_CPP_PATH, "w")
  f.write("#include \"network.hpp\"\n")
#....................

# 获取各个层的输出
  for node in model.graph.node:
    for o in node.output:
      model.graph.output.extend([onnx.ValueInfoProto(name=o)])

# 进行推理
  session = ort.InferenceSession(model.SerializePartialToString())
  inputs = session.get_inputs()
  outputs = session.get_outputs()
  outputs_shape = {}
  for i in range(len(outputs)):
    outputs_shape[outputs[i].name] = outputs[i].shape

  onnx_weights = {}
  for initializer in model.graph.initializer:
    onnx_weights[initializer.name] = numpy_helper.to_array(initializer)
  
  new_onnx_weights = []
  weight_names = onnx_weights.keys()
  parameters_num = 0
  nodes_num = 0

  weights = {}
  weights_pad_stride = {}
  cnt = 0
  for node in model.graph.node:
    name = node.name
    attr = node.attribute
    out = node.output[0]

    for ins in node.input:
      if ins in weight_names:
        new_name = ins
        nodes_num += 1
        flatten_weight = onnx_weights[ins].flatten()
        n = len(flatten_weight)
        if len(onnx_weights[ins].shape) == 4:
          d = {"pads": None, "strides": None}
          for a in attr:
            if a.name == "group":
              if a.i != onnx_weights[ins].shape[0]:
                new_name += "Conv"
              else:
                new_name += "DepthWise"
            elif a.name == "pads":
              d["pads"] = a.ints
            elif a.name == "strides":
              d["strides"] = a.ints
            elif a.name == "kernel_shape":
              d["kernel_shape"] = a.ints
            d["output_c"] = outputs_shape[out][1]
          weights_pad_stride[new_name] = d
        elif len(onnx_weights[ins].shape) == 1:
          new_name += "Bias"
        
        weights[new_name] = [parameters_num, n]

        parameters_num += n

        for w in flatten_weight:
          new_onnx_weights.append(w)

  f.write("\nvoid Network::init_weights(const std::string & npy_path)\n")
  f.write("{\n")
  f.write("  parameters_num = {};\n".format(parameters_num))
  f.write("  npz_array = cnpy::npy_load(npy_path);\n")
  f.write("  weights = npz_array.data<float>();\n\n")
  for w in weights:
    f.write("  pos[\"{}\"].start = {}; pos[\"{}\"].num = {};\n".format(w, weights[w][0], w, weights[w][1]))
  f.write("\n")

  for w in weights_pad_stride:
    f.write("  weights_param[\"{}\"].padding = {}; weights_param[\"{}\"].stride = {}; weights_param[\"{}\"].kernel_shape = {}; weights_param[\"{}\"].out_channel = {};".format(
      w, weights_pad_stride[w]["pads"][0], w, weights_pad_stride[w]["strides"][0],
      w, weights_pad_stride[w]["kernel_shape"][0], w, weights_pad_stride[w]["output_c"]
    ))
    f.write("\n")
  f.write("\n")

  np.save(WEIGHTS_NPY_PATH, new_onnx_weights)

  image = np.random.uniform(0, 1, size=(1, inputs[0].shape[1], inputs[0].shape[2], inputs[0].shape[3])).astype(np.float32)
  inference_outputs = session.run(None, {inputs[0].name: image})

  inference_outputs_names = [x.name for x in session.get_outputs()]
  inference_outputs_dict = dict()
  for i in range(len(inference_outputs_names)):
    key = inference_outputs_names[i]
    value = inference_outputs[i]
    inference_outputs_dict[key] = value

#................
    f.write("  inout_shape[\"{}\"][0] = {}; ".format(key, value.shape[0]))
    f.write("inout_shape[\"{}\"][1] = {};".format(key, value.shape[1]))
    f.write("inout_shape[\"{}\"][2] = {};".format(key, value.shape[2]))
    f.write("inout_shape[\"{}\"][3] = {};\n".format(key, value.shape[3]))
#................

  for x in session.get_inputs():
    f.write("  inout_shape[\"{}\"][0] = {}; ".format(x.name, x.shape[0]))
    f.write("inout_shape[\"{}\"][1] = {};".format(x.name, x.shape[1]))
    f.write("inout_shape[\"{}\"][2] = {};".format(x.name, x.shape[2]))
    f.write("inout_shape[\"{}\"][3] = {};\n".format(x.name, x.shape[3]))

  f.write("} \n")

执行上述代码后生成weights.cpp和weights.npy文件,其中weights.npy包含所有权重参数,weights.cpp记录各个参数获取的起始索引和数量、输入输出维度和卷积层的padding等参数

3. 基于OpenCL的算子开发

fastdepth主要包含5种算子操作

  • 二维卷积

  • 可分离卷积

  • ReLU激活

  • 张量相加

  • 上采样

核函数设计如下

  • 二维卷积

const char * kernel_conv2d = KERNEL(
__kernel void conv2d(
  __global const float * input,
  __global const float * weights,
  __global const float * bias,
  __global float * output,
  __private int kernel_chnlnum,
  __private int kernel_hw,
  __private int stride,
  __private int padding,
  __private int input_height,
  __private int input_width,
  __private float clip_min,
  __private float clip_max
)
{
  const int c = get_global_id(0);
  const int h = get_global_id(1);
  const int w = get_global_id(2);

  const int output_height = get_global_size(1);
  const int output_width = get_global_size(2);

  float sum = 0;
  int woffset = c * kernel_chnlnum * kernel_hw * kernel_hw;

  int hidx = kernel_hw / 2 - padding + h * stride;
  int widx = kernel_hw / 2 - padding + w * stride;

  for (int i = 0; i < kernel_chnlnum; i++)
  {
    for (int j = 0; j < kernel_hw; j++)
    {
      int input_hidx = hidx + j - kernel_hw / 2;
      if ((input_hidx < 0) || (input_hidx >= input_height))
      {
        continue;
      }
      for (int k = 0; k < kernel_hw; k++)
      {
        int input_widx = widx + k - kernel_hw / 2;
        if ((input_widx < 0) || (input_widx >= input_width))
        {
          continue;
        }

        float weight = weights[woffset + i * kernel_hw * kernel_hw + j * kernel_hw + k];
        float inp = input[i * input_height * input_width + input_hidx * input_width + input_widx];

        sum += weight * inp;
      }
    }
  }

  sum += bias[c];

  if (clip_min < clip_max)
  {
    if (sum < clip_min)
    {
      sum = clip_min;
    }
    else if (sum > clip_max)
    {
      sum = clip_max;
    }
  }

  output[c * output_width * output_height + h * output_width + w] = sum;
}
);
  • 可分离卷积

const char * kernel_depthwise_conv2d = KERNEL(
__kernel void depthwise_conv2d(
  __global const float * input,
  __global const float * weights,
  __global const float * bias,
  __global float * output,
  __private int kernel_hw,
  __private int stride,
  __private int padding,
  __private int input_height,
  __private int input_width,
  __private float clip_min,
  __private float clip_max
)
{
  const int c = get_global_id(0);
  const int h = get_global_id(1);
  const int w = get_global_id(2);

  const int output_height = get_global_size(1);
  const int output_width = get_global_size(2);

  float sum = 0;
  int woffset = c * kernel_hw * kernel_hw;
  int ioffset = c * input_height * input_width;

  int hidx = kernel_hw / 2 - padding + h * stride;
  int widx = kernel_hw / 2 - padding + w * stride;

  for (int j = 0; j < kernel_hw; j++)
  {
    int input_hidx = hidx + j - kernel_hw / 2;
    if ((input_hidx < 0) || (input_hidx >= input_height))
    {
      continue;
    }
    for (int k = 0; k < kernel_hw; k++)
    {
      int input_widx = widx + k - kernel_hw / 2;
      if ((input_widx < 0) || (input_widx >= input_width))
      {
        continue;
      }  
      float weight = weights[woffset + j * kernel_hw + k];
      float inp = input[ioffset + input_hidx * input_width + input_widx];  
      sum += weight * inp;
    }
  }

  sum += bias[c];

  if (clip_min < clip_max)
  {
    if (sum < clip_min)
    {
      sum = clip_min;
    }
    else if (sum > clip_max)
    {
      sum = clip_max;
    }
  }

  output[c * output_width * output_height + h * output_width + w] = sum;
}
);
  • 张量相加

const char * kernel_add = KERNEL(
__kernel void add(
  __global const float * input1,
  __global const float * input2,
  __global float * output
)
{
  const int c = get_global_id(0);
  const int h = get_global_id(1);
  const int w = get_global_id(2);

  const int h_size = get_global_size(1);
  const int w_size = get_global_size(2);

  const int tid = c * h_size * w_size + h * w_size + w;

  output[tid] = input1[tid] + input2[tid];
}
);
  • ReLU激活

const char * kernel_relu = KERNEL(
__kernel void relu(
  __global const float * input,
  __global float * output
)
{
  const int c = get_global_id(0);
  const int h = get_global_id(1);
  const int w = get_global_id(2);

  const int h_size = get_global_size(1);
  const int w_size = get_global_size(2);

  const int tid = c * h_size * w_size + h * w_size + w;

  if (input[tid] > 0)
  {
    output[tid] = input[tid];
  }
  else
  {
    output[tid] = 0.0;
  }
}
);
  • 上采样(nearest方法)

const char * kernel_upsample_nearest = KERNEL(
__kernel void upsample_nearest(
  __global const float * input,
  __global float * output,
  __private int input_height,
  __private int input_width,
  __private int h_factor,
  __private int w_factor
)
{
  const int c = get_global_id(0);
  const int h = get_global_id(1);
  const int w = get_global_id(2);

  const int h_size = get_global_size(1);
  const int w_size = get_global_size(2);

  const int in_h = h / h_factor;
  const int in_w = w / w_factor;

  const int out_idx = c * h_size * w_size + h * w_size + w;
  const int in_idx = c * input_height * input_width + in_h * input_width + in_w;

  output[out_idx] = input[in_idx];
}
);

4. FastDepth算法部署

在network.cpp里提供创建卷积层、可分离卷积层等的接口

  • 卷积层

void Network::depthwise_conv2d_layer(const std::string & input_name,
                            const std::string & output_name,
                            const std::string & weight_name,
                            const std::string & bias_name,
                            const char * kernel_name,
                            const float & clip_min,
                            const float & clip_max)
{
  cl_int errcode;

  if (cl_nodes.find(input_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[input_name] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * inout_shape[input_name][1] * inout_shape[input_name][2] * inout_shape[input_name][3], NULL, &errcode));
  }
  if (cl_nodes.find(weight_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[weight_name] = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, sizeof(float) * pos[weight_name].num, &weights[ pos[weight_name].start ], &errcode));
  }
  if (cl_nodes.find(bias_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[bias_name] = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, sizeof(float) * pos[bias_name].num, &weights[ pos[bias_name].start ], &errcode));
  }
  if (cl_nodes.find(output_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[output_name] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * inout_shape[output_name][1] * inout_shape[output_name][2] * inout_shape[output_name][3], NULL, &errcode));
  }

  if (cl_kernels.find(kernel_name) == cl_kernels.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_kernels[kernel_name] = clCreateKernel(cl_programs["depthwise_conv2d"], "depthwise_conv2d", &errcode));
  }

  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 0, sizeof(cl_mem), &cl_nodes[input_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 1, sizeof(cl_mem), &cl_nodes[weight_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 2, sizeof(cl_mem), &cl_nodes[bias_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 3, sizeof(cl_mem), &cl_nodes[output_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 4, sizeof(int), &weights_param[weight_name].kernel_shape));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 5, sizeof(int), &weights_param[weight_name].stride));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 6, sizeof(int), &weights_param[weight_name].padding));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 7, sizeof(int), &inout_shape[input_name][2]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 8, sizeof(int), &inout_shape[input_name][3]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 9, sizeof(float), &clip_min));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 10, sizeof(float), &clip_max));

  kernel_size[kernel_name][0] = inout_shape[output_name][1];
  kernel_size[kernel_name][1] = inout_shape[output_name][2];
  kernel_size[kernel_name][2] = inout_shape[output_name][3];
}
  • 可分离卷积层

void Network::depthwise_conv2d_layer(const std::string & input_name,
                            const std::string & output_name,
                            const std::string & weight_name,
                            const std::string & bias_name,
                            const char * kernel_name,
                            const float & clip_min,
                            const float & clip_max)
{
  cl_int errcode;

  if (cl_nodes.find(input_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[input_name] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * inout_shape[input_name][1] * inout_shape[input_name][2] * inout_shape[input_name][3], NULL, &errcode));
  }
  if (cl_nodes.find(weight_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[weight_name] = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, sizeof(float) * pos[weight_name].num, &weights[ pos[weight_name].start ], &errcode));
  }
  if (cl_nodes.find(bias_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[bias_name] = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, sizeof(float) * pos[bias_name].num, &weights[ pos[bias_name].start ], &errcode));
  }
  if (cl_nodes.find(output_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[output_name] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * inout_shape[output_name][1] * inout_shape[output_name][2] * inout_shape[output_name][3], NULL, &errcode));
  }

  if (cl_kernels.find(kernel_name) == cl_kernels.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_kernels[kernel_name] = clCreateKernel(cl_programs["depthwise_conv2d"], "depthwise_conv2d", &errcode));
  }

  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 0, sizeof(cl_mem), &cl_nodes[input_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 1, sizeof(cl_mem), &cl_nodes[weight_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 2, sizeof(cl_mem), &cl_nodes[bias_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 3, sizeof(cl_mem), &cl_nodes[output_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 4, sizeof(int), &weights_param[weight_name].kernel_shape));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 5, sizeof(int), &weights_param[weight_name].stride));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 6, sizeof(int), &weights_param[weight_name].padding));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 7, sizeof(int), &inout_shape[input_name][2]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 8, sizeof(int), &inout_shape[input_name][3]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 9, sizeof(float), &clip_min));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 10, sizeof(float), &clip_max));

  kernel_size[kernel_name][0] = inout_shape[output_name][1];
  kernel_size[kernel_name][1] = inout_shape[output_name][2];
  kernel_size[kernel_name][2] = inout_shape[output_name][3];
}
  • relu激活

void Network::relu_layer(const std::string & input_name,
                const std::string & output_name,
                const char * kernel_name)
{
  cl_int errcode;

  if (cl_nodes.find(input_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[input_name] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * inout_shape[input_name][1] * inout_shape[input_name][2] * inout_shape[input_name][3], NULL, &errcode));
  }
  if (cl_nodes.find(output_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[output_name] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * inout_shape[output_name][1] * inout_shape[output_name][2] * inout_shape[output_name][3], NULL, &errcode));
  }

  if (cl_kernels.find(kernel_name) == cl_kernels.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_kernels[kernel_name] = clCreateKernel(cl_programs["relu"], "relu", &errcode));
  }

  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 0, sizeof(cl_mem), &cl_nodes[input_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 1, sizeof(cl_mem), &cl_nodes[output_name]));

  kernel_size[kernel_name][0] = inout_shape[output_name][1];
  kernel_size[kernel_name][1] = inout_shape[output_name][2];
  kernel_size[kernel_name][2] = inout_shape[output_name][3];
}
  • 张量相加

void Network::add_layer(const std::string & input1_name,
               const std::string & input2_name,
               const std::string & output_name,
               const char * kernel_name)
{
  cl_int errcode;

  if (cl_nodes.find(input1_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[input1_name] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * inout_shape[input1_name][1] * inout_shape[input1_name][2] * inout_shape[input1_name][3], NULL, &errcode));
  }
  if (cl_nodes.find(input2_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[input2_name] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * inout_shape[input2_name][1] * inout_shape[input2_name][2] * inout_shape[input2_name][3], NULL, &errcode));
  }
  if (cl_nodes.find(output_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[output_name] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * inout_shape[output_name][1] * inout_shape[output_name][2] * inout_shape[output_name][3], NULL, &errcode));
  }

  if (cl_kernels.find(kernel_name) == cl_kernels.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_kernels[kernel_name] = clCreateKernel(cl_programs["add"], "add", &errcode));
  }

  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 0, sizeof(cl_mem), &cl_nodes[input1_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 1, sizeof(cl_mem), &cl_nodes[input2_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 2, sizeof(cl_mem), &cl_nodes[output_name]));

  kernel_size[kernel_name][0] = inout_shape[output_name][1];
  kernel_size[kernel_name][1] = inout_shape[output_name][2];
  kernel_size[kernel_name][2] = inout_shape[output_name][3];
}
  • 上采样层

void Network::upsample_nearest_layer(const std::string & input_name,
                            const std::string & output_name,
                            const char * kernel_name,
                            const int & h_factor,
                            const int & w_factor)
{
  cl_int errcode;

  if (cl_nodes.find(input_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[input_name] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * inout_shape[input_name][1] * inout_shape[input_name][2] * inout_shape[input_name][3], NULL, &errcode));
  }
  if (cl_nodes.find(output_name) == cl_nodes.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_nodes[output_name] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * inout_shape[output_name][1] * inout_shape[output_name][2] * inout_shape[output_name][3], NULL, &errcode));
  }

  if (cl_kernels.find(kernel_name) == cl_kernels.end())
  {
    CHECK_ERROR(errcode != CL_SUCCESS, errcode, cl_kernels[kernel_name] = clCreateKernel(cl_programs["upsample_nearest"], "upsample_nearest", &errcode));
  }

  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 0, sizeof(cl_mem), &cl_nodes[input_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 1, sizeof(cl_mem), &cl_nodes[output_name]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 2, sizeof(int), &inout_shape[input_name][2]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 3, sizeof(int), &inout_shape[input_name][3]));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 4, sizeof(int), &h_factor));
  CHECK_ERROR(errcode != CL_SUCCESS, errcode, errcode = clSetKernelArg(cl_kernels[kernel_name], 5, sizeof(int), &w_factor));

  kernel_size[kernel_name][0] = inout_shape[output_name][1];
  kernel_size[kernel_name][1] = inout_shape[output_name][2];
  kernel_size[kernel_name][2] = inout_shape[output_name][3];
}

main.cpp构建fastdpeth结构

int main(int argc, char ** argv)
{
  std::cout << "starting..." << std::endl;

  try
  {
    std::string save_npy_path;
    if (argc > 1)
    {
      save_npy_path = std::string(argv[1]);
    }

    Network net;
    net.init_weights("/home/ray/Documents/i2c_lcd/fastdepth/npy/weights.npy");
    net.init();

    net.init_input_layer("input", "data", "init_input");
    net.conv2d_layer("data", "231", "507Conv", "509Bias", "conv2d_507", 0, 6);
    net.depthwise_conv2d_layer("231", "234", "511DepthWise", "513Bias", "depthwise_conv2d_511", 0, 6);
    net.conv2d_layer("234", "237", "515Conv", "517Bias", "conv2d_515", 0, 6);
    net.depthwise_conv2d_layer("237", "240", "519DepthWise", "521Bias", "depthwise_conv2d_519", 0, 6);
    net.conv2d_layer("240", "243", "523Conv", "525Bias", "conv2d_523", 0, 6);
    net.depthwise_conv2d_layer("243", "246", "527DepthWise", "529Bias", "depthwise_conv2d_527", 0, 6);
    /*
      ..............
    */

    net.execute(save_npy_path);
    net.release();
  }
  catch(const std::exception & e)
  {
    std::cerr << e.what() << std::endl;
  }

  std::cout << "输入任意字符结束..." << std::endl;
  std::cin.get();

  return 0;
}

5. 效果展示

视差图生成效果

运行速度效果: