in lib/Processor.cpp [888:985]
void DepthVideoProcessor::gridXformSplit(const Params& params) {
// Validate compatibility of old and new xform types.
if (params.depthXformDesc.depthType != DepthXformType::Grid) {
throw std::runtime_error("Transform type must be a grid type.");
}
DepthStream& ds = video_->depthStream(params.depthStream);
const XformDescriptor prevDesc = ds.depthXformDesc();
if (prevDesc.depthType != DepthXformType::Global &&
prevDesc.depthType != DepthXformType::Grid) {
throw std::runtime_error("Can only split global or grid type transforms.");
}
if (params.depthXformDesc.valueXform != prevDesc.valueXform) {
throw std::runtime_error(
"Old and new transforms must use same value transform.");
}
if (prevDesc.depthType != DepthXformType::Global && (
prevDesc.gridSize.x() > params.depthXformDesc.gridSize.x() ||
prevDesc.gridSize.y() > params.depthXformDesc.gridSize.y())) {
throw std::runtime_error(
"New transform must have at least the same number"
" of rows and columns as the old transform.");
}
// Create a copy of the current transforms
std::vector<std::unique_ptr<Xform>> prevXforms;
for (int frame = 0; frame < video_->numFrames(); ++frame) {
prevXforms.push_back(ds.frame(frame).depthXform().clone());
}
ds.resetDepthXforms(params.depthXformDesc);
for (int frame = 0; frame < video_->numFrames(); ++frame) {
const std::vector<double*>& prevParamBlocks =
prevXforms[frame]->paramBlocks();
const std::vector<int>& prevParamBlockSizes =
prevXforms[frame]->paramBlockSizes();
const DepthXform& newXform = ds.frame(frame).depthXform();
const std::vector<double*>& newParamBlocks = newXform.paramBlocks();
const std::vector<int>& newParamBlockSizes = newXform.paramBlockSizes();
for (int row = 0; row < params.depthXformDesc.gridSize.y(); ++row) {
for (int col = 0; col < params.depthXformDesc.gridSize.x(); ++col) {
const int idx = col + row * params.depthXformDesc.gridSize.x();
const int N = newParamBlockSizes[idx];
if (prevDesc.depthType == DepthXformType::Global) {
assert(prevParamBlocks.size() == 1);
assert(prevParamBlockSizes[0] == N);
memcpy(newParamBlocks[idx], prevParamBlocks[0], N * sizeof(double));
} else if (prevDesc.depthType == DepthXformType::Grid) {
const int prevRows = prevDesc.gridSize.y();
const int prevCols = prevDesc.gridSize.x();
assert(prevRows >= 2);
assert(prevCols >= 2);
const int newRows = params.depthXformDesc.gridSize.y();
const int newCols = params.depthXformDesc.gridSize.x();
const double maxx = std::nextafter(prevCols - 1, 0.0);
const double maxy = std::nextafter(prevRows - 1, 0.0);
const double sx = std::min(
col / double(newCols - 1) * (prevCols - 1), maxx);
const double sy = std::min(
row / double(newRows - 1) * (prevRows - 1), maxy);
const int ix = static_cast<int>(sx);
const int iy = static_cast<int>(sy);
assert(ix >= 0 && ix < newCols - 1);
assert(iy >= 0 && iy < newRows - 1);
const double rx = sx - ix;
const double ry = sy - iy;
double* b0 = prevParamBlocks[ix + iy * prevCols];
double* b1 = prevParamBlocks[(ix + 1) + iy * prevCols];
double* b2 = prevParamBlocks[ix + (iy + 1) * prevCols];
double* b3 = prevParamBlocks[(ix + 1) + (iy + 1) * prevCols];
const double w0 = (1.f - rx) * (1.f - ry);
const double w1 = rx * (1.f - ry);
const double w2 = (1.f - rx) * ry;
const double w3 = rx * ry;
for (int i = 0; i < N; ++i) {
newParamBlocks[idx][i] =
b0[i] * w0 + b1[i] * w1 + b2[i] * w2 + b3[i] * w3;
}
} else {
throw std::runtime_error("Unsupported transform type.");
}
}
}
}
}