目前我正在学习C ++,我一直在努力为学习目的创建一个简单的图像处理库。
我的一个功能是侵蚀图像。作为输入,它有两个2d数组,并返回另一个2d数组。所有这些数组都是可变大小的。让我们举例说明我想要实现的目标。
int image[5][5] =
{
{'0', '0', '0', '0','0'},
{'0', '1', '1', '1','0'},
{'0', '0', '1', '0','0'},
{'0', '1', '1', '1','0'},
{'0', '0', '1', '0','0'},
};
int kernel[3][3] =
{
{'0', '1', '0'},
{'1', '1', '1'},
{'0', '1', '0'},
};
然后我想把它们传递给我的函数(这不会编译,但它可以作为我想要的一个例子)。
int** erode(int image[][], int kernel[][]);
到目前为止,我已经阅读了很多相关内容。我读过的只是列可以是可变长度的,但行不能。所以我应该将其更改为以下内容:
int** erode(int image[][5], int kernel[][3]);
但这并不是我想要的,因为好吧,图像可以是10 * 10,内核可以是5 * 5。所以这在这种情况下也不是最佳的。
然后我读到的是创建一个类,它在内部将图像存储为1d数组并使其看起来像2d数组。我也读过有关使用Boost.MultiArray
类来执行此操作的信息。但我对此也不太满意。因为那时我强迫使用它的人也使用这些类。而且我认为这对于看似非常简单的事情(至少在C#中)会产生很多复杂性。
说实话,我无法想象没有更简单的方法可以做到这一点。最好我只说使用标准C++11
库中的类/方法。 您如何解决这个问题?
蒂莫
答案 0 :(得分:4)
看看你是否可以使用模板,例如:
template<int N>
void f(int (&arr)[N][N]);
如果数组有编译时限。 但实际上你应该考虑提升,犰狳或者电视
答案 1 :(得分:3)
我会将数组作为指针传递,并传递另一个定义数组大小的参数。
int** erode(int* image, size_t imageSize, int* kernel, size_t kernelSize);
数组只是内存中的连续变量列表,而image[5][5]
等数组变量只指向数组的第一个元素。将已显示的数组传递给您将使用的函数。
int** ret = errode(image, 5, kernel, 3);
使用它时要小心,因为它很容易导致分段错误,但正确使用时会很好。这也假设数组是方形的,为了克服这个限制,只需传入另一个描述数组其他维度的参数。
<强>更新强>
我看到Anycorn发布了一个非常好的解决方案。他是一个更安全的解决方案,但是需要你在编译时知道数组的大小。如果是这种情况,我会建议你使用他所说的。
答案 2 :(得分:2)
您撰写的关于内部存储1D阵列的内容基本上是最佳解决方案。使用二维阵列通常很危险,很容易导致错误。如果您不想创建整个班级,请考虑:
const int SizeX = 10, SizeY = 10;
int Array[SizeX*SizeY];
inline int& Get (int x, int y) { return Array[SizeX*y+x]; }
当然,这是一个非常简单的例子,但通常会解决很多错误。
struct MyOwnArray
{
int SizeX, int SizeY;
int* Data;
inline int& Get (int x, int y) { return Data[SizeX*y+x]; }
}
上面的代码允许您以方便的方式传递对此结构的引用。它只有6行代码!
当然,上面的代码需要更多的代码;例如,用于分配内存。但是,如果您仔细编写所有这些部件,那么使用它将非常安全,并且它应该受到良好的保护以防止错误。
答案 3 :(得分:2)
返回2D矢量不那么复杂。
#include <vector>
#include <iostream>
using namespace std;
typedef std::vector<std::vector< int> > vector2D;
int image[5][5] =
{
{0, 0, 0, 0, 0},
{0, 1, 1, 1, 0},
{0, 0, 1, 0, 0},
{0, 1, 1, 1, 0},
{0, 0, 1, 0, 0},
};
int kernel[5][5] =
{
{0, 0, 0, 0, 0},
{0, 1, 1, 1, 0},
{0, 0, 1, 0, 0},
{0, 1, 1, 1, 0},
{0, 0, 1, 0, 0},
};
vector2D erode(int image[5][5], int kernel[5][5])
{
vector2D image_process_data ;
//create 2D vector array
image_process_data.resize(5);
for(int i = 0; i < 5; i++)
{
image_process_data[i].resize(5);
}
//perform calculations
for (int ix = 0; ix < 5; ix++)
{
for (int iy = 0; iy < 5; iy++)
{
image_process_data[ix][iy] = image[ix][iy] + kernel[ix][iy];
}
}
//return the 2D array
return image_process_data;
}
int main( )
{
vector2D new_image;
new_image = erode(image, kernel);
//display new_image
for (int ix = 0; ix < 5; ix++)
{
for (int iy = 0; iy < 5; iy++)
{
cout<<new_image[ix][iy]<<" ";
}
cout<<"\n";
}
return 0;
}
如何设置2D矢量数组:
#include <vector>
#include <iostream>
using std namespace;
#define HEIGHT 5
#define WIDTH 3
int main() {
vector<vector<double> > array2D;
// Set up sizes. (HEIGHT x WIDTH)
array2D.resize(HEIGHT);
for (int i = 0; i < HEIGHT; ++i)
array2D[i].resize(WIDTH);
// Put some values in
array2D[1][2] = 6.0;
array2D[3][1] = 5.5;
return 0;
}