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

Fastest Conversion of Row-Ordered data to Column-Ordered data

本文关键字:数据 序数 转换      更新时间:2023-10-16

我有一个来自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 affecionados,elem(x,y)的实际位置由data + y*widthstep + x*sizeof(element)给出,但这给出了一般的想法,对于char数据sizeof(element)=1,我们可以使widthstep=width,因此公式是精确的

它被称为"矩阵换位"最佳方法试图最大限度地减少缓存未命中的数量,交换小瓦片具有一个或几个高速缓存槽的大小。对于多级缓存,这将变得困难。从这里开始阅读

这是一个更先进的

顺便说一句,url处理的是"就地"换位。创建转置副本会有所不同(它使用的缓存插槽是原来的两倍,duh!)

假设您需要一个移动了所有元素的新数组,那么在算法速度方面,您能管理的最快值是元素数量的O(N)(即宽度*高度)。

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

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

当然,在你的单个"循环"中,你可以避免多次进行相同的乘法运算,指针运算可能比随机存取快一点。

您已经回答了自己的问题,但没有代码。我想你需要之类的东西

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("nn");
}
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)