OpenCV图像裁剪:使用&运算符在OpenCV图像裁剪时进行边界检查

给定ROI的图像裁剪

假设需要按照既定的ROI对图像进行取窗裁剪,用cv::Rect给定ROI区域,裁剪可以按照如下方式:

cpp 复制代码
cv::Mat image = cv::imread("/path/to/image.jpg");
cv::Rect roi = cv::Rect(x, y, width, height);
cv::Mat crop = image(roi);

限制边界

如果roi的坐标超出了图像的合法区域,会引发运行时错误,导致程序崩溃。此时一般要提前进行边界检查和规范,比如这样:

cpp 复制代码
if(roi.x<0) roi.x=0;
if(roi.y<0) roi.y=0;
if(roi.x+roi.width >= image.cols) roi.width = image.cols-roi.x;
if(roi.y+roi.height >= image.rows) roi.heigth = image.rows-roi.y;

这样写代码,看上去不太直观,而且有些冗长,更谈不上优雅或者可读性。

或者这样:

cpp 复制代码
int w = image.cols;
int h = image.rows;

int x0 = std::max<int>(0, roi.tl().x);
int y0 = std::max<int>(0, roi.tl().y);
int x1 = std::min<int>(w, roi.br().x);
int y1 = std::min<int>(h, roi.br().y);

roi = cv::Rect(cv::Point(x0, y0), cv::Point(x1, y1));

稍微增加了些可读性,特别是如果习惯于使用stl的max/min函数进行边界检查。但是仍然冗长,不够优雅。冗长有什么坏处?一般来讲,冗长的代码不易于维护,可读性不会太强。另外以上面这段实现为例,由于反复使用同一变量,仅仅为了对其不同的成员做类似的操作,非常容易导致低级错误。

Operator & : Get Intersection of cv::Rect

这个运算符&比较直观。在C/C++语法中,&属于位运算,是按位与的功能。cv::Rect类型重载了它,可以想象它的功能就是取矩形的相交区域。所以要对图像ROI的cv::Rect进行边界限制,那么将ROI和表示图像区域的Bounding Box求相交区域即可。代码实现如下:

cpp 复制代码
cv::Rect bbox(0, 0, mat.cols, mat.rows);
cv::Rect roi = roi & bbox; // that's all

这样基本上就一句话完成了边界限制。

What's More: verify if rect is inside image

进一步说,如果要检查一个rect是否在图像区域内,不用Operator的话,一般按照以下思路实现:

cpp 复制代码
bool rectIsInside(const cv::Rect& rect, const cv::Mat& image)
{
    return (
        rect.x>=0 && 
        rect.y>=0 && 
        rect.x + rect.width < m.cols && 
        rect.x + rect.width < m.rows) ;
}

但是如果使用了&运算符,life will be much easier.

cpp 复制代码
bool rectIsInside(const cv::Rect& rect, const cv::Mat& image)
{
    cv::Rect bbox(0, 0, image.cols, image.rows);
    return (rect & bbox) == rect; // elegent and efficient
}

简洁、优雅、可读性强的实现方式。

相关推荐
2301_7875528732 分钟前
console-chat-gpt开源程序是用于 AI Chat API 的 Python CLI
人工智能·python·gpt·开源·自动化
虾球xz33 分钟前
游戏引擎学习第268天:合并调试链表与分组
c++·学习·链表·游戏引擎
layneyao37 分钟前
AI与自然语言处理(NLP):从BERT到GPT的演进
人工智能·自然语言处理·bert
fpcc1 小时前
跟我学c++高级篇——模板元编程之十三处理逻辑
c++
jndingxin2 小时前
OpenCV 的 CUDA 模块中用于将多个单通道的 GpuMat 图像合并成一个多通道的图像 函数cv::cuda::merge
人工智能·opencv·计算机视觉
格林威2 小时前
Baumer工业相机堡盟工业相机的工业视觉中为什么偏爱“黑白相机”
开发语言·c++·人工智能·数码相机·计算机视觉
灬0灬灬0灬2 小时前
深度学习---常用优化器
人工智能·深度学习
Dream it possible!3 小时前
LeetCode 热题 100_只出现一次的数字(96_136_简单_C++)(哈希表;哈希集合;排序+遍历;位运算)
c++·leetcode·位运算·哈希表·哈希集合
_Itachi__3 小时前
Model.eval() 与 torch.no_grad() PyTorch 中的区别与应用
人工智能·pytorch·python
白光白光3 小时前
大语言模型训练的两个阶段
人工智能·机器学习·语言模型