我正在用 C++ 编写一个程序,从一组投影的 2D 图像中重建一个 3D 对象,其中计算最密集的部分涉及通过双线性插值放大和移动每个图像。我目前有两个功能可以完成这项任务;“blnSetup”在循环外定义了一些参数,然后“双线性”在循环内逐点应用插值:
(注意:'I' 是一个包含有序图像数据行的一维数组)
//Pre-definition structure (in header)
struct blnData{
float* X;
float* Y;
int* I;
float X0;
float Y0;
float delX;
float delY;
};
//Pre-definition function (outside the FOR loop)
extern inline blnData blnSetup(float* X, float* Y, int* I)
{
blnData bln;
//Create pointers to X, Y, and I vectors
bln.X = X;
bln.Y = Y;
bln.I = I;
//Store offset and step values for X and Y
bln.X0 = X[0];
bln.delX = X[1] - X[0];
bln.Y0 = Y[0];
bln.delY = Y[1] - Y[0];
return bln;
}
//Main interpolation function (inside the FOR loop)
extern inline float bilinear(float x, float y, blnData bln)
{
float Ixy;
//Return -1 if the target point is outside the image matrix
if (x < bln.X[0] || x > bln.X[-1] || y < bln.Y[0] || y > bln.Y[-1])
Ixy = 0;
//Otherwise, apply bilinear interpolation
else
{
//Define known image width
int W = 200;
//Find nearest indices for interpolation
int i = floor((x - bln.X0) / bln.delX);
int j = floor((y - bln.Y0) / bln.delY);
//Interpolate I at (xi, yj)
Ixy = 1 / ((bln.X[i + 1] - bln.X[i])*(bln.Y[j + 1] - bln.Y[j])) *
(
bln.I[W*j + i] * (bln.X[i + 1] - x) * (bln.Y[j + 1] - y) +
bln.I[W*j + i + 1] * (x - bln.X[i]) * (bln.Y[j + 1] - y) +
bln.I[W*(j + 1) + i] * (bln.X[i + 1] - x) * (y - bln.Y[j]) +
bln.I[W*(j + 1) + i + 1] * (x - bln.X[i]) * (y - bln.Y[j])
);
}
return Ixy;
}
编辑:函数调用如下。“flat.imgdata”是一个包含输入图像数据的 std::vector,“proj.imgdata”是一个包含转换后图像的 std::vector。
int Xs = flat.dim[0];
int Ys = flat.dim[1];
int* Iarr = flat.imgdata.data();
float II, x, y;
bln = blnSetup(X, Y, Iarr);
for (int j = 0; j < flat.imgdata.size(); j++)
{
x = 1.2*X[j % Xs];
y = 1.2*Y[j / Xs];
II = bilinear(x, y, bln);
proj.imgdata[j] = (int)II;
}
自从我开始优化以来,通过在插值函数中从 std::vectors 切换到 C 数组,我已经能够将计算时间减少约 50 倍(!),并通过清理冗余计算/类型转换/等再减少 2 倍左右,但是假设 O(n) 和 n 是处理像素的总数,完整的重建(~7e10 像素)仍然需要 40 分钟左右——比我的目标 <5 分钟长一个数量级。
根据 Visual Studio 的性能分析器,插值函数调用 ("II = bilinear(x, y, bln);") 毫无疑问仍然是我计算负载的主要部分。我还没有找到任何用于快速多重插值的线性代数方法,所以我的问题是:这基本上和我的代码一样快,除了对任务应用更多或更快的 CPU 吗?或者是否有不同的方法可以加快速度?
PS 我现在也只用 C++ 编码了大约一个月,所以请随时指出我可能犯的任何初学者错误。