DCT 中的图像分割
Image Dividing in C for DCT
谁能告诉我们如何将图像分成 8X8 块?
我可以读取图像,但不能将其分成 8x8 子矩阵用于 DCT。
int main()
{
FILE *image_raw;
unsigned char **matriz_image;
int i, j;
int rows=1080, colums=1920;
matriz_image = (unsigned char **) malloc (rows*sizeof(unsigned char *));
//i create dinamic colums
for(i=0; i<rows; i++)
{
matriz_image[i] = (unsigned char *) malloc (colums*sizeof(unsigned char ));
}
//i open image raw
image_raw = fopen("imag.dat", "r+b");
//i copy values to matriz_image
for (i = 0; i < rows; ++i)
{
fread(matriz_image[i], sizeof(unsigned char ), colums, image_raw);
}
for(i=0; i<rows; i++)
{
for(j=0; j<colums; j++)
{
// printf("%i ",*(*(matriz_image+i)+j));
printf("%i ",matriz_image[i][j]);
}
printf("\n");
}
你可以这样做:
void dct(unsigned char **m, int baserow, int basecol)
{
for (int row = baserow, endrow = baserow + 8; row < endrow; ++row)
for (int col = basecol, endcol = basecol + 8; col < endcol; ++col)
; // operate on m[row][col]
}
int do_dcts(unsigned char **m, int num_rows, int num_cols)
{
if (num_rows <= 0 || num_rows % 8 || num_cols <= 0 || num_cols % 8)
return -1;
for (int row = 0; row < num_rows; row += 8)
for (int col = 0; col < num_cols; col += 8)
dct(m, row, col);
return 0;
}
通过使用两级指针实现二维数组,您正在浪费 space 并恶化您的内存局部性。最好进行一次分配,然后像这样适当地偏移到数组中:
int main()
{
FILE *image_raw;
unsigned char *matriz_image;
int i, j;
int rows=1080, colums=1920;
matriz_image = malloc(rows*colums*sizeof(unsigned char));
...
如果您可以使行和列常量或具有 VLA,那么您可以:
unsigned char (*m)[colums] = (unsigned char (*)[colums]) matriz_image;
m[5][2] = 2; // double indexed access without extra pointers + allocs
同样,您可以将 m 类型的指向您矩阵的指针传递给您的函数以对其进行操作。
如果你不能使行和列成为编译时常量并且你没有 VLA,那么你可以编写 helper fcns 来为你做指针运算:
inline unsigned char *get_row(unsigned char *m, int numcols, int row)
{
return &m[row * num_cols];
}
inline unsigned char *get_elem(unsigned char *m, int numcols, int row, int col)
{
return &m[row * num_cols + col];
}
...
*get_elem(m, colums, 5, 2) = 2; // double indexing not as nice but good memory usage
如果您确实需要快速执行这些操作,那么在读入图像时,您可以重新组织它以将 8x8 字节块连续放置在内存中以获得最佳缓存性能:
// organize m like m[rows * colums / 64][8][8]; so first index is an 8x8 block #
for (int k = 0; k < rows / 8; ++k) // read all rows in chunks of 8
for (int i = 0; i < 8; ++i) // read 8 rows
for (int j = 0; j < colums / 8; ++j) // read 1 row in 8 byte chunks
fread(&m[k * 8 * colums + i * 8 + j * 64], 1, 8, image_raw);
...
typedef unsigned char (*block_ptr)[8];
inline block_ptr get_block(unsigned char *m, int num_cols, int block_num)
{
return (block_ptr) &m[block_num * 64];
}
inline block_ptr get_block2(unsigned char *m, int num_cols, int row, int col)
{
if (row % 8 || col % 8)
return NULL;
return (block_ptr) &m[row * num_cols + col * 8];
}
...
for (int k = 0; k < rows * colums / 64; ++k)
{
block_ptr block = get_block(m, num_colums, k);
for (int i = 0; i < 8; ++i)
for (int j = 0; j < 8; ++j)
; // operate on block[i][j];
}
谁能告诉我们如何将图像分成 8X8 块?
我可以读取图像,但不能将其分成 8x8 子矩阵用于 DCT。
int main()
{
FILE *image_raw;
unsigned char **matriz_image;
int i, j;
int rows=1080, colums=1920;
matriz_image = (unsigned char **) malloc (rows*sizeof(unsigned char *));
//i create dinamic colums
for(i=0; i<rows; i++)
{
matriz_image[i] = (unsigned char *) malloc (colums*sizeof(unsigned char ));
}
//i open image raw
image_raw = fopen("imag.dat", "r+b");
//i copy values to matriz_image
for (i = 0; i < rows; ++i)
{
fread(matriz_image[i], sizeof(unsigned char ), colums, image_raw);
}
for(i=0; i<rows; i++)
{
for(j=0; j<colums; j++)
{
// printf("%i ",*(*(matriz_image+i)+j));
printf("%i ",matriz_image[i][j]);
}
printf("\n");
}
你可以这样做:
void dct(unsigned char **m, int baserow, int basecol)
{
for (int row = baserow, endrow = baserow + 8; row < endrow; ++row)
for (int col = basecol, endcol = basecol + 8; col < endcol; ++col)
; // operate on m[row][col]
}
int do_dcts(unsigned char **m, int num_rows, int num_cols)
{
if (num_rows <= 0 || num_rows % 8 || num_cols <= 0 || num_cols % 8)
return -1;
for (int row = 0; row < num_rows; row += 8)
for (int col = 0; col < num_cols; col += 8)
dct(m, row, col);
return 0;
}
通过使用两级指针实现二维数组,您正在浪费 space 并恶化您的内存局部性。最好进行一次分配,然后像这样适当地偏移到数组中:
int main()
{
FILE *image_raw;
unsigned char *matriz_image;
int i, j;
int rows=1080, colums=1920;
matriz_image = malloc(rows*colums*sizeof(unsigned char));
...
如果您可以使行和列常量或具有 VLA,那么您可以:
unsigned char (*m)[colums] = (unsigned char (*)[colums]) matriz_image;
m[5][2] = 2; // double indexed access without extra pointers + allocs
同样,您可以将 m 类型的指向您矩阵的指针传递给您的函数以对其进行操作。
如果你不能使行和列成为编译时常量并且你没有 VLA,那么你可以编写 helper fcns 来为你做指针运算:
inline unsigned char *get_row(unsigned char *m, int numcols, int row)
{
return &m[row * num_cols];
}
inline unsigned char *get_elem(unsigned char *m, int numcols, int row, int col)
{
return &m[row * num_cols + col];
}
...
*get_elem(m, colums, 5, 2) = 2; // double indexing not as nice but good memory usage
如果您确实需要快速执行这些操作,那么在读入图像时,您可以重新组织它以将 8x8 字节块连续放置在内存中以获得最佳缓存性能:
// organize m like m[rows * colums / 64][8][8]; so first index is an 8x8 block #
for (int k = 0; k < rows / 8; ++k) // read all rows in chunks of 8
for (int i = 0; i < 8; ++i) // read 8 rows
for (int j = 0; j < colums / 8; ++j) // read 1 row in 8 byte chunks
fread(&m[k * 8 * colums + i * 8 + j * 64], 1, 8, image_raw);
...
typedef unsigned char (*block_ptr)[8];
inline block_ptr get_block(unsigned char *m, int num_cols, int block_num)
{
return (block_ptr) &m[block_num * 64];
}
inline block_ptr get_block2(unsigned char *m, int num_cols, int row, int col)
{
if (row % 8 || col % 8)
return NULL;
return (block_ptr) &m[row * num_cols + col * 8];
}
...
for (int k = 0; k < rows * colums / 64; ++k)
{
block_ptr block = get_block(m, num_colums, k);
for (int i = 0; i < 8; ++i)
for (int j = 0; j < 8; ++j)
; // operate on block[i][j];
}