【问题标题】:How to send chunks of a big 2D array to function for processing如何将大二维数组的块发送到函数进行处理
【发布时间】:2017-06-15 23:34:34
【问题描述】:

我有一个使用 int 存储图像数据的二维数组。目前它是 800x640,但可以更改。我想将它传递给 8x8 块中的另一个函数进行处理。我实际上可以将数组的一个 8x8 块复制到一个临时变量中并将其发送到函数,然后将结果复制到另一个 800x640 数组中。

但是,如果我给它这个 800x640 数组中的起始 xy 坐标,我希望该函数能够直接访问 8x8 块(这会更快)。问题是使用 int** 不起作用。声明为 int[8][8] 的参数也不会编译。我该怎么办?现在我正在用 C++ 编写程序,但最终也必须用 C 编写。

【问题讨论】:

  • 如何声明主数组?为什么不传递初始指针和起始坐标?你是什​​么意思`int**不起作用?您是否尝试过先解决简单(一维)数组的问题?
  • 主数组是 int x[640][800]。需要将 8x8 块传递给另一个函数。声明为 int**y 和 int y[8][8] 的函数参数都不能编译。
  • int[][](二维数组)与int**不同。

标签: c arrays pointers


【解决方案1】:

您可以将指向原始图像的指针和其他参数传递给函数,并访问函数内8x8 区域的每个元素。

假设这是您的原始800x640 图片:

int img[640][800];

将你的功能声明为:

void work_on_roi(int* img, size_t img_width, size_t img_height, int roi_x, int roi_y, size_t roi_width, size_t roi_height)

ROI 代表感兴趣区域,这是图像处理领域中广泛使用的术语。在您的情况下,如果您想以 (10,20) 作为其左上角索引访问 roi,您可以使用以下参数调用此函数:

work_on_roi(img, 800, 640, 10, 20, 8, 8)

在这个函数中,访问 roi 中的 (i,j) 元素是:

(img + (roi_y + j) * img_width)[roi_x + i]

您可以使用roi_widthroi_height 参数来检查完整性:

// before accessing (i,j) element of roi
assert(i < roi_width);
assert(j < roi_height);
assert(roi_x + i < img_width);
assert(roi_y + j < img_height);

【讨论】:

    【解决方案2】:

    虽然您访问区域元素的方式不会根据您声明数组的方式而改变,但您将数组作为参数传递的方式将根据您是否有实际的二维数组或是否有pointer-to-pointer-to-type.

    如果声明类似于int array[X][Y]; 的真正数组(其中XY 是定义的常量),您可以将pointer to array of int [Y](例如(*array)[Y])作为参数传递给您的函数。

    如果数组将被转换为 pointer-to-pointer-to-type,当声明类似于 int **array;int (*array)[z]; 时,您在其中分配每个指针和块行或单个块,您只需传递一个pointer-to-pointer-to-type(例如int **array

    无论哪种情况,您都可以使用一个简单的函数来更改数组中的一个区域,该函数迭代您希望更改的元素。例如,对于您指定的二维数组的情况,您可以声明一个具有类似于以下逻辑的函数。 (您可以根据需要传递其他参数以实现所需的任何更改)

    enum { ROW = 10, COL = 10 };   /* constant definitions */
    ...
    void chgregion (int (*a)[COL], int xs, int ys, int xn, int yn)
    {
        int xlim = xs + xn,        /* xstart + xnumber_of_elements */
            ylim = ys + yn;        /* same for y */
    
        if (xlim > ROW) xlim = ROW;  /* protect array/block bounds */
        if (ylim > COL) ylim = COL;
    
        for (int i = xs; i < xlim; i++)
            for (int j = ys; j < ylim; j++)
                a[i][j] = 1;        /* change element as required */
    
    }
    

    在指向COL 元素数组的指针上方,连同xy 在数组中的起始位置以及区域中的元素数量一起传递,例如xnyn。进行了简单的检查以限制区域大小以保持在数组边界或内存块的边界内。如果您的数组实际上是一个指向类型的指针,只需传递 int **a 并将内存块的尺寸作为附加参数传递。

    你可以整理一个简单的测试如下:

    #include <stdio.h>
    
    enum { ROW = 10, COL = 10 };
    
    void chgregion (int (*a)[COL], int xs, int ys, int xn, int yn);
    void prna (int (*a)[COL]);
    
    int main (void) {
    
        int a[ROW][COL] = {{0}};
    
        prna (a);
        chgregion (a, 2, 2, 6, 6);
        putchar ('\n');
        prna (a);
    
        return 0;
    }
    
    void chgregion (int (*a)[COL], int xs, int ys, int xn, int yn)
    {
        int xlim = xs + xn,
            ylim = ys + yn;
    
        if (xlim > ROW) xlim = ROW;
        if (ylim > COL) ylim = COL;
    
        for (int i = xs; i < xlim; i++)
            for (int j = ys; j < ylim; j++)
                a[i][j] = 1;
    
    }
    
    void prna (int (*a)[COL])
    {
        for (int i = 0; i < ROW; i++) {
            for (int j = 0; j < COL; j++)
                printf ("%2d", a[i][j]);
            putchar ('\n');
        }
    }
    

    使用/输出示例

    $ ./bin/array2d_region
     0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0
    
     0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0
     0 0 1 1 1 1 1 1 0 0
     0 0 1 1 1 1 1 1 0 0
     0 0 1 1 1 1 1 1 0 0
     0 0 1 1 1 1 1 1 0 0
     0 0 1 1 1 1 1 1 0 0
     0 0 1 1 1 1 1 1 0 0
     0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0
    

    让我知道这是否是您的意图,或者您所做的是否在某些方面有所不同。如需进一步帮助,请发帖Minimal, Complete, and Verifiable example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多