跳转到内容
新建笔记

OpenCV ROI:区域裁剪、坐标顺序与边界检查

cv::Mat(rows, cols, type) 的参数是“行数、列数”;cv::Rect(x,y,width,height) 的参数是“左上角横坐标、纵坐标、宽、高”。图像左上角为原点,x 沿列增加,y 沿行增加。

区域对应半开范围:

x≤c<x+w,y≤r<y+h.x\le c<x+w,\qquad y\le r<y+h.

因此有效区域应满足 x,y≥0x,y\ge0、w,h>0w,h>0、x+w≤colsx+w\le cols、y+h≤rowsy+h\le rows。image(rect) 产生共享原数据的子矩阵头,独立副本需要 clone()。Mat 区域与复制接口

#include <opencv2/core.hpp>
#include <iostream>
int main() {
cv::Mat image(480, 640, CV_8UC3, cv::Scalar::all(0));
cv::Rect requested(100, 200, 100, 200);
cv::Rect bounds(0, 0, image.cols, image.rows);
if (requested.width <= 0 || requested.height <= 0 ||
(requested & bounds) != requested) {
std::cerr << "ROI is outside the image\n";
return 1;
}
cv::Mat roi = image(requested);
cv::Mat independent = roi.clone();
roi.setTo(cv::Scalar(255, 0, 0));
std::cout << image.at<cv::Vec3b>(200, 100) << '\n';
std::cout << independent.at<cv::Vec3b>(0, 0) << '\n';
}

这会把原图中对应区域改为蓝色,而先前复制的 independent 保持黑色。若业务需要“超出边界时自动裁剪”,可取与 bounds 的交集,但必须明确这是改变区域尺寸的另一种策略,不能静默替代要求完整区域的逻辑。

38 × 8400 张量为什么不能直接用旧区域

跳转到“38 × 8400 张量为什么不能直接用旧区域”

旧记录建立了 38 行、8400 列的矩阵,却使用 Rect(20,1000,17,400)。y=1000 已超过 38 行,区域无效。

如果确实要在未转置的矩阵中选取第 20 至 36 行、第 1000 至 1399 列,应写:

cv::Mat tensor(38, 8400, CV_32F, cv::Scalar(0));
cv::Mat block = tensor(cv::Range(20, 37), cv::Range(1000, 1400));
// 等价区域:cv::Rect(1000, 20, 400, 17)

这里的数值只演示行列换算,不代表某个检测模型的输出定义。读取神经网络输出时,应先确认每一维的语义,再决定是否转置以及如何索引。

原始 ROI 示例中,修改区域使图像局部变蓝