我正在使用OpenCV从大图像获取小矩形ROI,并将ROI保存到文件中。有时,ROI超出了图像的范围。我需要一种方法来使生成的Mat显示边界内大图像的一部分,而其余部分则显示为黑色。
为了帮助说明,请提供一个图像,该图像是一个区域的地图。我知道某人在地图上的位置,并希望将地图的500x500像素部分放在中心位置。但是,当用户到达地图边缘时,此500x500部分的一部分将需要“远离地图”。所以我想用黑色填充它。
最好,OpenCV可以通过用黑色填充(如当您使用旋转图像时那样warpAffine
)来妥善处理超限的ROI(例如,负的左上角值),但事实并非如此。关于如何实现这一目标的任何建议?
所有其他答案对我来说似乎有点太复杂了。简单地:
// Create rect representing the image
auto image_rect = cv::Rect({}, image.size());
// Find intersection, i.e. valid crop region
auto intersection = image_rect & roi;
// Move intersection to the result coordinate space
auto inter_roi = intersection - roi.tl();
// Create black image and copy intersection
cv::Mat crop = cv::Mat::zeros(roi.size(), image.type());
image(intersection).copyTo(crop(inter_roi));
Run Code Online (Sandbox Code Playgroud)
图片供参考:
我发现做到这一点的最佳方法是获得边界内的 ROI 部分,然后计算 ROI 的每一侧(顶部/底部/左侧/右侧)有多少超出边界,然后使用该copyMakeBorder
函数在每一侧填充那么多黑色边框。效果很好。现在看起来像这样:
Mat getPaddedROI(const Mat &input, int top_left_x, int top_left_y, int width, int height, Scalar paddingColor) {
int bottom_right_x = top_left_x + width;
int bottom_right_y = top_left_y + height;
Mat output;
if (top_left_x < 0 || top_left_y < 0 || bottom_right_x > input.cols || bottom_right_y > input.rows) {
// border padding will be required
int border_left = 0, border_right = 0, border_top = 0, border_bottom = 0;
if (top_left_x < 0) {
width = width + top_left_x;
border_left = -1 * top_left_x;
top_left_x = 0;
}
if (top_left_y < 0) {
height = height + top_left_y;
border_top = -1 * top_left_y;
top_left_y = 0;
}
if (bottom_right_x > input.cols) {
width = width - (bottom_right_x - input.cols);
border_right = bottom_right_x - input.cols;
}
if (bottom_right_y > input.rows) {
height = height - (bottom_right_y - input.rows);
border_bottom = bottom_right_y - input.rows;
}
Rect R(top_left_x, top_left_y, width, height);
copyMakeBorder(input(R), output, border_top, border_bottom, border_left, border_right, BORDER_CONSTANT, paddingColor);
}
else {
// no border padding required
Rect R(top_left_x, top_left_y, width, height);
output = input(R);
}
return output;
}
Run Code Online (Sandbox Code Playgroud)
而且您可以轻松地制作您喜欢的任何颜色的填充,这很好。