【问题标题】:Initialize 3D lookup table (LUT) via preprocessor?通过预处理器初始化 3D 查找表(LUT)?
【发布时间】:2016-11-06 12:38:37
【问题描述】:

我正在使用查找表在颜色空间和编码变体之间转换原始像素数据。这是我的 LUT 的定义:

typedef struct
{
    unsigned char data[3];
} rgb;

rgb LUTYUVTORGB[256][256][256];

它是这样初始化的:

// loop through all possible values
for (int in_1 = 0; in_1 < 256; in_1++) {
    for (int in_2 = 0; in_2 < 256; in_2++) {
        for (int in_3 = 0; in_3 < 256; in_3++) {

            int out_1, out_2, out_3;

            // LUT YUV -> RGB
            // convert to rgb (http://softpixel.com/~cwright/programming/colorspace/yuv/)
            out_1 = (int)(in_1 + 1.4075 * (in_3 - 128));
            out_2 = (int)(in_1 - 0.3455 * (in_2 - 128) - (0.7169 * (in_3 - 128)));
            out_3 = (int)(in_1 + 1.7790 * (in_2 - 128));

            // clamp values
            if (out_1 < 0) { out_1 = 0; } else if (out_1 > 255) { out_1 = 255; }
            if (out_2 < 0) { out_2 = 0; } else if (out_2 > 255) { out_2 = 255; }
            if (out_3 < 0) { out_3 = 0; } else if (out_3 > 255) { out_3 = 255; }

            // set values in LUT
            LUTYUVTORGB[in_1][in_2][in_3].data[0] = (unsigned char)out_1;
            LUTYUVTORGB[in_1][in_2][in_3].data[1] = (unsigned char)out_2;
            LUTYUVTORGB[in_1][in_2][in_3].data[2] = (unsigned char)out_3;
        }
    }
}

然后应用 LUT 将原始像素数据复制到 QImage():

for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
        xpos = (y*w + x); // don't calculate 3 times
        buff[x * 3 + 0] = psImage->comps[0].data[xpos];
        buff[x * 3 + 1] = psImage->comps[1].data[xpos];
        buff[x * 3 + 2] = psImage->comps[2].data[xpos];
    }
    memcpy(image.scanLine(y), buff, bytes_per_line);
}

LUT 的值是静态的,每次程序启动时都必须初始化。有没有办法通过预处理器初始化它?还是建议将其保存在文件中?

编辑:转换用于时间要求严格的视频应用程序,其中每一帧都必须单独处理。

提前非常感谢!

【问题讨论】:

  • 为什么首先需要这么大的 (64MiB) 查找表?转换非常简单,您可以随时进行。
  • 我的建议是将其保存在具有某种结构的文件中。
  • @Leon 我应该提到转换用于时间关键的视频应用程序,其中每个帧都必须单独处理。
  • @Cherkesgiller Tural 你会建议什么结构?
  • 您确定会从如此大的 LUT 表中受益吗?它不适合缓存,因此性能不会太好。与每次简单计算值相比,您是否对其进行了测试?

标签: c++ qt image-processing c-preprocessor lookup-tables


【解决方案1】:

我已经为这个表创建了一维数组,保存和加载这样的数组很方便。我认为在运行时使用这个数组不会降低性能。但我没有测试它的性能差异。

#include <stdio.h>
#include <stdlib.h>

#define LUTSIZE 0x1000000

typedef struct
{
    unsigned char data[3];
} rgb;

rgb *LUT;

inline int LUT_index(int in_1, int in_2, int in_3) {
    return in_1 * 0x10000 + in_2 * 0x100 + in_3 * 0x1;
}

inline rgb LUT_value(int in_1, int in_2, int in_3) {
    return LUT[LUT_index(in_1,in_2,in_3)];
}

void save(rgb *LUT, char* fileName) {

    FILE* file = fopen(fileName,"wb");
    int index;

    for (int in_1 = 0; in_1 < 256; in_1++) {
        for (int in_2 = 0; in_2 < 256; in_2++) {
            for (int in_3 = 0; in_3 < 256; in_3++) {

                int out_1, out_2, out_3;

                // LUT YUV -> RGB
                // convert to rgb (http://softpixel.com/~cwright/programming/colorspace/yuv/)
                out_1 = (int)(in_1 + 1.4075 * (in_3 - 128));
                out_2 = (int)(in_1 - 0.3455 * (in_2 - 128) - (0.7169 * (in_3 - 128)));
                out_3 = (int)(in_1 + 1.7790 * (in_2 - 128));

                // clamp values
                if (out_1 < 0) { out_1 = 0; } else if (out_1 > 255) { out_1 = 255; }
                if (out_2 < 0) { out_2 = 0; } else if (out_2 > 255) { out_2 = 255; }
                if (out_3 < 0) { out_3 = 0; } else if (out_3 > 255) { out_3 = 255; }

                index = LUT_index(in_1,in_2,in_3);

                // set values in LUT
                LUT[index].data[0] = (unsigned char)out_1;
                LUT[index].data[1] = (unsigned char)out_2;
                LUT[index].data[2] = (unsigned char)out_3;
            }
        }
    }

    fwrite((void*)LUT, sizeof(rgb),LUTSIZE,file);
    fclose(file);
}

void read(rgb *LUT, char* fileName) {
    FILE* file = fopen(fileName, "rb");
    fread((void*)LUT,sizeof(rgb),LUTSIZE,file);
    fclose(file);
}

int main(int argc, char *argv[])
{
    LUT = (rgb*)malloc(LUTSIZE * sizeof(rgb));
    save(LUT, "LUT_data");
    rgb testValue = LUT_value(5,3,7);
    printf("%d %d %d\n", testValue.data[0], testValue.data[1], testValue.data[2]);

    read(LUT, "LUT_data");
    testValue = LUT_value(5,3,7);
    printf("%d %d %d\n", testValue.data[0], testValue.data[1], testValue.data[2]);

    free(LUT);
}      

【讨论】:

  • 一个多维数组在内存中已经是连续的了,你真的不需要重新设计它来使其“可序列化”。
  • 谢谢@ddriver,我已经测试了两个阵列的性能相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-09
  • 2016-09-13
  • 1970-01-01
  • 2016-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多