行排序数据到列排序数据的最快转换

时间:2012-02-01 17:49:16

标签: c++ c performance memory opencv

我有一个来自openCV的IplImage,它以行排序格式存储数据;

图像数据存储在一维数组char *数据中;位置x,y处的元素由

给出
elem(x,y) = data[y*width + x] // see note at end

我想尽可能快地将此图像转换为第二种图像格式,该格式以列排序格式存储其数据;

elem(x,y) = data[x*height + y]

显然,进行此转换的一种方法是通过double for循环逐个元素。

有更快的方法吗?


注意对于openCV afficionados,elem(x,y)的实际位置由data + y*widthstep + x*sizeof(element)给出,但这给出了一般的想法,对于char数据sizeof(element)= 1,我们可以使widthstep = width ,所以公式是准确的

3 个答案:

答案 0 :(得分:4)

它被称为“矩阵换位” 优化方法尝试最小化缓存未命中数,交换小块 具有一个或几个缓存槽的大小。对于多级缓存,这将变得困难。 start reading here

this one is a bit more advanced

BTW网址处理“到位”换位。创建转置副本将是不同的(它使用两倍的缓存槽,呃!)

答案 1 :(得分:0)

假设您需要一个新的数组,其中所有元素都已移动,您在算法速度上管理的最快速度是元素数量的O(N)(即宽度*高度)。

对于实际花费的时间,可以生成多个线程,其中每个线程复制一些元素。如果你真的有很多这样的话,这当然是值得的。

如果线程已经创建并且他们接受队列中的任务,或者其他什么,那么如果您要处理大量这些图像,这将是最有效的。

在你的个别“循环”中,你可以避免多次进行相同的乘法,当然,指针算法可能比随机访问快一点。

答案 2 :(得分:0)

你有点回答自己,但没有代码。我想你需要......:

typedef struct
{
    unsigned char r;
    unsigned char g;
    unsigned char b;
}somePixelFormat;

#define HEIGHT 2
#define WIDTH  4

// let's say this is original image width=4 height=2 expresed as one dimentional
// array of structs that adhere to your pixel format
somePixelFormat src[ WIDTH * HEIGHT ] = 
{
    {0,0,0}, {1,1,1}, {2,2,2}, {3,3,3},
    {4,4,4}, {5,5,5}, {6,6,6}, {7,7,7}
};

somePixelFormat dst[ WIDTH * HEIGHT ];

void printImage( void *img, int width, int height, int pixelByteCount )
{
    for ( int row = 0; row < height; row++ )
    {
        for ( int col = 0; col < width; col++ )
        {
            printf( "(%02d,%02d,%02d) ", ((somePixelFormat*)img + width * row + col)->r,
                                         ((somePixelFormat*)img + width * row + col)->g,
                                         ((somePixelFormat*)img + width * row + col)->b );
        }

        printf ( "\n" );
    }
    printf("\n\n");
}

void flip( void *dstImg, void *srcImg, int srcWidth, int srcHeight, int pixelByteCount )
{
    for ( int row = 0; row < srcHeight; row++ )
    {
        for ( int col = 0; col < srcWidth; col++ )
        {
            *((somePixelFormat*)dstImg + srcHeight * col + row) = *((somePixelFormat*)srcImg + srcWidth * row + col);
        }
    }
}

int main()
{
    printImage( src, 4, 2, sizeof(somePixelFormat) );
    flip( dst, src, 4, 2, sizeof(somePixelFormat) );
    printImage( dst, 2, 4, sizeof(somePixelFormat) );

    getchar();
    return 0;
}

这是示例输出:

(00,00,00) (01,01,01) (02,02,02) (03,03,03) 
(04,04,04) (05,05,05) (06,06,06) (07,07,07) 


(00,00,00) (04,04,04) 
(01,01,01) (05,05,05) 
(02,02,02) (06,06,06) 
(03,03,03) (07,07,07)