1、定义层结构
因为不知道如果同名可不可以覆盖掉原来的层,所以我同名试试,证明可以覆盖
第78行用于读取参数
83行用于创建整个层
87行是定义输出数据的结构
102层是层的具体方法,在基类Layer中是一个纯虚函数,一定要重定义
121层我也不知道干啥的,但是在基类Layer中是一个纯虚函数,一定要重定义
如果基类中的纯虚函数没有在派生类中全部被重新定义,那么派生类会是以一个抽象类,抽象类不能实例化。
129行是后面的CV_DNN_REGISTER_LAYER_CLASS的头文件,没有的话,会报错
134行是对新层permute的声明,没有的话,层就不会在编译的时候被加载
2、参数输入
原来的层参数都叫order,但是这样,我不知道怎么读取,所以就干脆写成了四个参数
然后读出来就是这样的
发现,输入的参数可以少于目标的四个,就是需要几个输入几个,然后红色的框子里面的就是没有输入的情况下的默认值,也是最小值,就是如果你输入参数是-1之类的,他就直接给你改成0了。
3、输出数据格式
在这个函数里面定义,输入参数不理解可以参考这个链接https://blog.csdn.net/Diana_Z/article/details/98613363
在写这个过程的时候遇到一个坑
开始打算使用-1作为空白维度的标识,但是调试的时候发现,-1会自动变成1,没有输入也会自动变成1
然后尝试将正常维度里面的1使用10来代替,-1或者没有输入变成了0
最后干脆将正常维度从10开始,正常维度0参数10,正常维度1参数11,类推
上面这个问题找到参数位置了,在参数读取部分
遇到第二个坑,
我重写这个参数的目的根源是想要让lstm可以读3维甚至二维的矩阵,当前我的矩阵没有设置卷积,数据直接就lstm层。
然后,我发现blob的数据读取自动就是B*C*H*W的
所以这里我需要的可能不是重写一个permute层,而是重写一个降维层。
不过在降维层之前,因为2维3维的转置总是有的,所以还是有用的吧。
static cv::Ptr<cv::dnn::Layer> create(cv::dnn::LayerParams& params)
{
return cv::Ptr<cv::dnn::Layer>(new PermuteLayer(params));
}
virtual bool getMemoryShapes(const std::vector<std::vector<int> > &inputs,
const int requiredOutputs,
std::vector<std::vector<int> > &outputs,
std::vector<std::vector<int> > &internals) const CV_OVERRIDE
{
CV_UNUSED(requiredOutputs); CV_UNUSED(internals);
cout << "start PermuteLayer getMemoryShapes" << endl;
//将四个输入放入数组
std::vector<int> order(4);
order[0] = order1;
order[1] = order2;
order[2] = order3;
order[3] = order4;
//第一次循环,计算维度,恢复维度下标
int dim = 0;
for (int i = 0; i < 4; i++) {
if (order[i] <10) {
break;
}
else {
dim++;
order[i] = order[i] % 10;
}
}
//第二次循环,将input的size都放在数组里面去
std::vector<int> newShape;
for (int i = 0; i < dim; i++) {
newShape.push_back(inputs[0][i]);
}
//第三次循环,将input中的数字按照order的顺序放入output
std::vector<int> outShape;
for (int i = 0; i < dim; i++) {
outShape.push_back(newShape[order[i]]);
}
outputs.assign(1, outShape);
return false;
}
4、计算过程
virtual void forward(std::vector<cv::Mat*> &inputs, std::vector<cv::Mat> &outputs, std::vector<cv::Mat> &internals) CV_OVERRIDE
{
CV_UNUSED(internals);
cout << "start PermuteLayer forward1" << endl;
cv::Mat& inp = *inputs[0];
cv::Mat& out = outputs[0];
if (order3 == -1) {
vector<int> sq(2);
int H = inp.size[0];
int W = inp.size[1];
for (int i = 0; i < H; i++) {
sq.push_back(i);
for (int j = 0; j < W; j++) {
sq.push_back(j);
cout << sq[order1] << " " << sq[order2] << endl;
out.at<float>[sq[order1]][sq[order2]] = inp.at<float>[i][j];
sq.pop_back();
}
sq.pop_back();
}
}
if (order4 == -1) {
vector<int> sq(2);
int H = inp.size[0];
int W = inp.size[1];
int C = inp.size[2];
for (int k = 0; k < C; k++) {
sq.push_back(k);
for (int i = 0; i < H; i++) {
sq.push_back(i);
for (int j = 0; j < W; j++) {
sq.push_back(j);
out.at<float>[sq[order1]][sq[order2]][sq[order3]] = inp.at<float>[k][i][j];
sq.pop_back();
}
sq.pop_back();
}
sq.pop_back();
}
}
if (order4 > 0) {
vector<int> sq(2);
int H = inp.size[0];
int W = inp.size[1];
int C = inp.size[2];
int B = inp.size[3];
for (int l = 0; l < B; l++) {
sq.push_back(l);
for (int k = 0; k < C; k++) {
sq.push_back(k);
for (int i = 0; i < H; i++) {
sq.push_back(i);
for (int j = 0; j < W; j++) {
sq.push_back(j);
out.at<float>[sq[order1]][sq[order2]][sq[order3]][sq[order4]] = inp.at<float>[l][k][i][j];
sq.pop_back();
}
sq.pop_back();
}
sq.pop_back();
}
sq.pop_back();
}
}
}