问题:
在opencv4nodejs中设置矩阵区域的最快方法是什么?
问题:
我将源图像覆盖到更大的目标图像中,其尺寸仅为数千。
在 Python 中,我将获取/设置匹配大小的区域:
destination[y:y+h, x:x+w] = source[:,:]
但我不确定如何在 Javascript 中执行此操作。
我尝试了一些方法,但即使是最快的方法也非常慢。
例如,我有:
- source_mat 列:2929,行:2049
- dest_mat 列:3000,行:6000
- offset_x:150, offset_y:150
将矩阵转换为数组,循环行和列,设置 dest 像素大约需要 12 秒
let debug_overlay_start = new Date().valueOf();
let source_pixels = source_mat.getDataAsArray();
for (let row_index = 0, l_1 = source_pixels.length; row_index < l_1; row_index++) {
if(row_index + offset_y < 0) continue;
if(row_index + offset_y >= dest_mat.rows) continue;
let this_col = source_pixels[row_index];
for (let col_index = 0, l_2 = this_col.length; col_index < l_2; col_index++) {
if(col_index + offset_x < 0) continue;
if(col_index + offset_x >= dest_mat.cols) continue;
dest_mat.set(row_index + offset_y, col_index + offset_x, source_pixels[row_index][col_index]);
}
}
let debug_overlay_end = new Date().valueOf();
console.log(`overlay method took ${((debug_overlay_end - debug_overlay_start)/1000).toFixed(2)}`); // overlay method took 11.63
return dest_mat;
将两者都转换为数组,循环遍历行,拼接 cols 需要 82 秒:
let debug_overlay_end = new Date().valueOf();
let source_pixels = source_mat.getDataAsArray();
let new_dest_mat = dest_mat.getDataAsArray();
for (let row_index = 0, l_1 = source_pixels.length; row_index < l_1; row_index++) {
if(row_index + offset_y < 0) continue;
if(row_index + offset_y >= dest_mat.rows) continue;
let this_col = source_pixels[row_index]; // entire column of source pixels
new_dest_mat[row_index + offset_y].splice(offset_x, this_col.length, ...this_col);
}
let debug_overlay_end = new Date().valueOf();
console.log(`overlay method took ${((debug_overlay_end - debug_overlay_start)/1000).toFixed(2)}`); // 82 seconds
return new cv.Mat(new_dest_mat, dest_mat.type);
替换区域根本不起作用,抛出一个生命周期错误,没有额外的日志记录:
let debug_overlay_end = new Date().valueOf();
let area_to_replace = dest_mat.getRegion(new cv.Rect(x, y, source_mat.cols, source_mat.rows));
area_to_replace = source_mat.getRegion(new cv.Rect(0, 0, source_mat.cols, source_mat.rows)); // lifecycle error
console.log(`overlay method took ${((debug_overlay_end - debug_overlay_start)/1000).toFixed(2)}`);
return dest_mat;
使用setAt()
andatRaw()
是迄今为止最快的 8 秒:
let debug_overlay_start = new Date().valueOf();
for(let row_index = 0, row_length = source_mat.rows; row_index < row_length; row_index++){
if(row_index + offset_y < 0) continue;
if(row_index + offset_y >= dest_mat.rows) continue;
for(let col_index = 0, col_length = source_mat.cols; col_index < col_length; col_index++){
if(col_index + offset_x < 0) continue;
if(col_index + offset_x >= dest_mat.cols) continue;
dest_mat.set(row_index + offset_y, col_index + offset_x, source_mat.atRaw(row_index, col_index));
}
}
let debug_overlay_end = new Date().valueOf();
console.log(`overlay method took ${((debug_overlay_end - debug_overlay_start)/1000).toFixed(2)}`); // 8.09
return dest_mat;
我查看了文档,很惊讶地发现这不是一个常见的用例。节点/电子环境是否会减慢原本快速的操作?