OpenCV中如何将连续cv::Mat拷贝到非连续存储的cv::Mat
解决方案
完全不需要手写双层逐像素循环,OpenCV原生API已经内置了不同步长Mat的适配逻辑,执行效率比手写循环更高,代码也更简洁,推荐两种实现方式:
- 最优方案:直接将透视变换结果输出到绑定GPU内存的Mat,省略中间拷贝环节
无需单独创建连续存储的中间MatwarpImg,提前初始化好绑定GPU内存、行步长为512的目标Mat,直接将其作为cv::warpPerspective的输出参数即可。OpenCV所有原生图像处理函数都支持非连续步长的Mat作为输出,内部会自动处理行对齐逻辑,执行完成后结果直接存在GPU可读取的内存中,不需要额外拷贝操作。
示例代码:// 初始化绑定GPU内存的目标Mat,参数和你创建输入frame的逻辑保持一致 cv::Mat gpu_bound_mat(frame_height, frame_width, CV_8UC3, gpu_memory_pointer, frame_step); // 透视变换结果直接写入GPU绑定内存 cv::warpPerspective(frame, gpu_bound_mat, M, cv::Size(112, 112), cv::INTER_LINEAR); - 兼容方案:如果必须从已生成的连续存储
warpImg拷贝数据到GPU绑定内存,直接调用copyTo接口即可cv::Mat::copyTo在拷贝时会自动识别源、目标Mat的步长差异,仅拷贝每行的有效像素区域,自动跳过目标Mat每行尾部的对齐填充字节,内部做了SIMD指令优化,性能远高于手写的逐像素遍历。
仅需一行代码即可替换你写的双层循环:// frame为绑定GPU内存、步长512的非连续Mat warpImg.copyTo(frame);
注意事项:禁止使用
clone()、整块memcpy等假设内存连续的拷贝方式,这类操作不会读取Mat的步长参数,要么造成内存越界,要么错误覆盖每行尾部的填充内存,引发数据异常。所有OpenCV原生API和copyTo、convertTo等拷贝接口都会自动适配非连续内存,是最安全可靠的选择。
内容的提问来源于stack exchange,提问作者Scarlet Zhou
相关产品推荐
相关产品推荐

