1

私は、Jetson TX2 (ARM プロセッサを搭載) で非常にパフォーマンスが重要な画像処理パイプラインに取り組んでいます。これには、一連の画像を読み取ってから、Darknetを介して深層学習ベースのオブジェクト検出を実行することが含まれます。C で記述された Darknet には、画像の保存方法に関する独自の表現があります。これは、OpenCV の IplImage または Python numpy 配列が画像を保存する方法とは異なります。

私のアプリケーションでは、Python を介して Darknet とやり取りする必要があります。したがって、現時点では、画像の「バッチ」(通常は 16 個) を numpy 配列に読み込んでから、ctypes を使用して連続配列として Darknet に渡しています。Darknet 内で、numpy 形式から Darknet の形式に移行するために、ピクセルの順序を再配置する必要があります。

入力配列は、列方向、行方向、チャネル方向、画像順に配置された 1 つの連続したブロックですが、Darknet 形式は、最初にチャネル、次に列、次に行で配置する必要があります。連続したブロックではなく、バッチ内の画像ごとに行。下の図は、違いを示しています。この例では、単一のixj画像を想定しています。(0,0)、(0,1) などは (行、列) を示し、上部の C0、C1、C2.. などは対応する行の列を示します。バッチの一部として複数の画像がある場合、入力形式はそれらを順番に順番に配置しますが、Darknet ではそれらを別々の行に配置する必要があることに注意してください。各行には 1 つの画像のみのデータが含まれます。

ここに画像の説明を入力

今のところ、入力配列を Darknet 形式に変換する C のコードは次のようになります。ここでは、すべてのチャネルのすべてのピクセルに繰り返しヒットし、別の場所に配置し、途中でピクセルを正規化します。

matrix ndarray_to_matrix(unsigned char* src, long* shape, long* strides)
{
int nb = shape[0];    // Batch size
int h = shape[1];     // Height of each image
int w = shape[2];     // Width of each image
int c = shape[3];     // No. of channels in each image
matrix X = make_matrix(nb, h*w*c);     // Output array format: 2D

int step_b = strides[0];
int step_h = strides[1];
int step_w = strides[2];
int step_c = strides[3];

int b, i, j, k;
int index1, index2 = 0;

for(b = 0; b < nb ; ++b) {
    for(i = 0; i < h; ++i) {
        for(k= 0; k < c; ++k) {
            for(j = 0; j < w; ++j) {
                index1 = k*w*h + i*w + j;
                index2 = step_b*b + step_h*i + step_w*j + step_c*k;
                X.vals[b][index1] = src[index2]/255.;
            }
        }
    }
}
return X;
}

Cでこの再配置と正規化を行うより効率的な方法はありますか?

  • 私は Jetson TX2 を使用しています。これには ARM プロセッサと NVIDIA GPU が含まれているため、NEON と CUDA だけでなく OpenMP にもアクセスできます。
  • 画像のサイズは固定されており、ハードコーディングできます。変更できるのはバッチ サイズのみです。
4

1 に答える 1