我需要预处理一个ML模型的输入到正确的形状。为了做到这一点,我需要从ncnn在C++中转换一个张量。API不提供transpose,所以我尝试实现自己的转置函数。
输入张量具有形状(1, 640, 640, 3) (对于batch、x、y和color),我需要将其重塑为形状(1, 3, 640, 640)。
如何正确有效地转换张量?
ncnn:Mat& preprocess(const cv::Mat& rgba) {
int width = rgba.cols;
int height = rgba.rows;
// Build a tensor from the image input
ncnn::Mat in = ncnn::Mat::from_pixels(rgba.data, ncnn::Mat::PIXEL_RGBA2RGB, width, height);
// Set the current shape of the tesnor
in = in.reshape(1, 640, 640, 3);
// Normalize
const float norm_vals[3] = {1 / 255.f, 1 / 255.f, 1 / 255.f};
in.substract_mean_normalize(0, norm_vals);
// Prepare the transposed matrix
ncnn::Mat transposed = new ncnn::Mat(in.w, in.c, in.h, in.d, sizeof(float));
ncnn::Mat shape = transposed->shape();
// Transpose
for (int i = 0; i < in.w; i++) {
for (int j = 0; j < in.h; j++) {
for (int k = 0; k < in.d; k++) {
for (int l = 0; l > in.c; l++) {
int fromIndex = ???;
int toIndex = ???;
transposed[toIndex] = in[fromIndex];
}
}
}
}
return transposed;
}发布于 2022-06-08 21:38:00
我只讨论索引计算,而不是我不熟悉的ncnn。
你设置
fromIndex = i*A + j*B + k*C + l*D;
toIndex = i*E + j*F + k*G + l*H; 根据源和目标布局计算A B C D E F G H。多么?
让我们先看一个简单的2D转位。将hw布局矩阵转换为wh布局矩阵(最慢的变化维数优先):
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
int fromIndex = i * w + j * 1;
// ^ ^
// | |
// i<h j<w <---- hw layout
int toIndex = j * h + i * 1;
// ^ ^
// | |
// j<w i<h <---- wh layout
}
} 因此,在计算fromIndex时,从源布局(hw)开始,删除第一个字母(h),剩下的(w)是与i一起的系数,然后删除下一个字母(w),剩下的(1)是与j一起的系数。不难看出,相同的模式在任意数量的维度中都是有效的。例如,如果源布局为dchw,则
fromIndex = i * (c*h*w) + j * (h*w) + k * (w) + l * (1);
// ^ ^ ^ ^
// | | | |
// i<d j<c k<h l<w <---- dchw那toIndex呢?同样的事情,但重新排列字母从最慢的变化到变化最快的目标布局。例如,如果您的目标布局是hwcd,那么顺序将是k l j i (因为I是在源布局和目标布局中范围都超过[0..d]的索引,等等)。所以
toIndex = k * (w*c*d) + l * (c*d) + j * (d) + i * (1);
// ^ ^ ^ ^
// | | | |
// k<h l<w j<c i<d <---- hwcd我不是故意用你的布局的。做几次自己的计算。你想培养一些关于这件事的直觉。
https://stackoverflow.com/questions/72550479
复制相似问题