opencv探索之路(十二):感兴趣区域ROI和logo添加技术
在图像处理领域,有一个非常重要的名词ROI。
什么是ROI?
它的英文全称是Region Of Interest,对应的中文解释就是感兴趣区域。
感兴趣区域,就是我们从图像中选择一个图像区域,这个区域就是图像分析所关注的焦点。我们圈定这个区域,那么我们要处理的图像就从大图像变为一个小图像区域了,这样以便进行进一步处理,可以大大减小处理时间。
定义ROI区域有两种方法:
第一种,指定矩形的坐标,并且规定好他的长宽。
Mat img = imread("1.jpg");
Mat roi = img(Rect(500, 200, 100, 300));//Rect四个形参分别是:x坐标,y坐标,长,高;注意(x,y)指的是矩形的左上角点
第二种,指定感兴趣的行或列的范围。
Mat img = imread("1.jpg");
Mat roi = img(Range(250, 250 + 100), Range(200, 200 + 100));//Range两个形参分别是:起始行或列,起始行或列+偏移量
简单看一下ROI区域的使用方法,下面的程序定义了ROI,并且我用绿框标记出来。
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat srcImage = imread("lol0.jpg");
if (!srcImage.data)
{
cout << "读取原始图失败!" << endl;
return -1;
}
rectangle(srcImage, Rect(0, 0, 600, 200), Scalar(0, 255, 0),2); //将感兴趣区域框出来
imshow("ROI", srcImage);
waitKey();
return 0;
}
绿框位置就是我们选的感兴趣区域。
有时候我们不仅想把ROI标记出来,还想把ROI提取出来,成为一幅单独图片,那我们代码可以这么写:
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
//导入图像
Mat img1 = imread("lol0.jpg", 1);
Mat img2(img1.rows, img1.cols, CV_8UC3);
//设置感兴趣区域,拷贝
img1(Rect(500, 31, 200, 250)).copyTo(img2);
//当然也可以这样
//Mat roi = img1(Rect(0,0,100,100));
//imshow("roi",roi);
//显示
imshow("img1", img1);
imshow("img2", img2);
waitKey(0);
}
这样子,ROI就被提取出来了。
现在开始说怎么为图像加上LOGO。
现在我想在一幅好看的图像上在给定的一个位置上加上下面这个酷炫的LOGO,有什么方法吗?
有两种方法。
方法一:
先定义好ROI区域(也就是你要在哪里加这个LOGO),然后进行线性叠加,使用addWeigthed函数。
这里有必要介绍一下线性混合操作。
线性混合操作是一种典型的二元(两个输入)的像素操作,它的理论公式如下:
我们通过在范围0到1之间改变alpha值,来对两幅图像(如上述公式中的fa和f3)进行画面迭代效果。OpenCV的相关操作如下:
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat srcImage = imread("lol.jpg");
if (!srcImage.data)
{
cout << "读取原始图失败!" << endl;
return -1;
}
namedWindow("srcImage", WINDOW_NORMAL);// 注意这个宏,使用WINDOW_NORMAL可以允许用户自由伸缩窗口大小
imshow("srcImage", srcImage);
Mat logo = imread("dota2.jpg");
if (!logo.data)
{
cout << "读取原始logo图失败!" << endl;
return -1;
}
Mat imageROI = srcImage(Rect(28, 41, logo.cols, logo.rows)); //从原图中抠出矩形区域,Rect第一二参数表示矩形左上角定点的坐标,用于定位,后两个参数表示举行的宽和高
imshow("ROI", imageROI);
addWeighted(imageROI, 0.2, logo, 0.8, 0., imageROI);//dst = src1[I]*alpha+ src2[I]*beta + gamma;第一第四个参数就是各自权重,第5个参数就是公式中的偏执因子gamma。
namedWindow("原图加logo", WINDOW_NORMAL);
imshow("原图加logo", srcImage);
waitKey();
return 0;
}
效果如下,可以看出,我们的logo变得模糊了,也可以认为我们logo跟原图水乳交融在一起了,我们可以不断调整上面addWeighted()的参数,来获得自己喜欢的效果。
方法二:
定义ROI区域,使用copyTo实现直接拷贝覆盖
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat srcImage = imread("lol.jpg");
if (!srcImage.data)
{
cout << "读取原始图失败!" << endl;
return -1;
}
namedWindow("srcImage", WINDOW_NORMAL);// 注意这个宏,使用WINDOW_NORMAL可以允许用户自由伸缩窗口大小
imshow("srcImage", srcImage);
Mat logo = imread("dota2.jpg");
Mat mask = imread("dota2.jpg",0); // 加载掩模(必须是灰度图)
if (!logo.data)
{
cout << "读取原始logo图失败!" << endl;
return -1;
}
Mat imageROI = srcImage(Rect(28, 41, logo.cols, logo.rows)); //从原图中抠出矩形区域,Rect第一二参数表示矩形左上角定点的坐标,用于定位,后两个参数表示举行的宽和高
imshow("ROI", imageROI);
logo.copyTo(imageROI,mask);//注意两个参数,一个是ROI,一个是掩模
namedWindow("原图加logo", WINDOW_NORMAL);
imshow("原图加logo", srcImage);
waitKey();
return 0;
}
从效果看出,logo被原汁原味地拷贝到原图上了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?