C++中修改cv::Mat内cv::Rect指定ROI区域并做线性变换
OpenCV局部ROI区域线性变换实现方案
OpenCV中cv::Mat用cv::Rect提取的ROI默认是原矩阵的浅拷贝,和原矩阵共享对应区域的内存,对ROI的修改会直接同步到原图像,不需要额外执行赋值回写操作。
具体实现代码
首先修正你代码里的参数类型问题:你的图像是CV_64FC1(双精度浮点单通道)类型,线性变换系数不能用int定义,否则int a=0.1会被截断为0,导致计算结果完全错误。
方法1:运算符重载直接实现(逻辑和你预期完全一致)
cv::Mat img = cv::Mat::zeros(msg->height, msg->width, CV_64FC1); cv::Rect rect(100, 100, 20, 50); // 先裁剪ROI到合法范围,避免越界崩溃 rect &= cv::Rect(0, 0, img.cols, img.rows); double a = 0.1; double b = 20; // 提取ROI(浅拷贝,和原图共享内存) cv::Mat roi = img(rect); // 直接对ROI做线性变换,修改会自动同步到原图对应位置 roi = roi * a + b;
方法2:原生API原地运算(性能更优,无临时矩阵开销)
不需要额外定义ROI变量,直接在原矩阵对应区域原地执行线性变换:
cv::Mat img = cv::Mat::zeros(msg->height, msg->width, CV_64FC1); cv::Rect rect(100, 100, 20, 50); rect &= cv::Rect(0, 0, img.cols, img.rows); double a = 0.1; double b = 20; // convertTo参数:目标矩阵,目标类型,缩放系数a,偏移量b,等价于*a +b img(rect).convertTo(img(rect), CV_64FC1, a, b);
注意事项
- 不要对提取的ROI调用
.clone()或者.copyTo()生成深拷贝,否则修改ROI不会影响原图像,还需要额外执行拷贝操作才能回写结果,带来不必要的性能开销。 - 运算前建议用
rect &= cv::Rect(0, 0, img.cols, img.rows)裁剪ROI范围,避免ROI超出图像边界触发内存访问错误。 - 所有参与运算的系数、变量类型要和矩阵的数据类型匹配,
CV_64FC1对应double类型,CV_32FC1对应float类型,避免隐式类型转换导致的精度丢失或计算错误。
内容的提问来源于stack exchange,提问作者Jerry
相关产品推荐
相关产品推荐

