opencv笔记2:图像ROI
opencv笔记2:图像ROI
ROI
ROI意思是Region Of Interests,感兴趣区域,是一个图中的一个子区域。
OpenCV中定义的ROI是矩形的。
ROI的用处包括而不限于:提取出ROI区域做进一步处理(比如人脸识别、车牌识别);将另一张图片贴放到ROI区域。
这里以第二种用处为例,将一个logo图像添加到一张大图上指定的ROI区域。
图像贴放
粗略想想,包括这四个步骤
- 定义大图和小图
- 在大图上定义ROI区域
- 小图贴放到ROI区域
- 显示新的大图
这里在fedora22下使用dnf(yum)安装了opencv3.0,如下代码可以运行良好
#include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { //【1】定义大图和小图 //【2】在大图上定义ROI区域 //【3】小图贴放到ROI区域 //【4】显示新的大图 //【1】定义大图和小图 Mat srcImage = imread("/home/chris/workspace/clion/dota_pa.jpg"); Mat logoImage = imread("/home/chris/workspace/clion/dota_ss.png"); if(!srcImage.data){ cerr << "读取srcImage错误!" << endl; exit; } if(!logoImage.data){ cerr << "读取logoImage错误!" << endl; exit; } //【2】在大图上定义ROI区域 Mat imageROI = srcImage(Rect(20, 25, logoImage.cols, logoImage.rows)); //【3】小图贴放到ROI区域 logoImage.copyTo(imageROI); //【4】显示新的大图 imshow("利用ROI实现图像叠加示例窗口", srcImage); waitKey(0); destroyAllWindows(); return 0; }
这里copyTo()
函数中只用到一个参数,浅墨的教程上有第二个参数:图像掩模(mask),我尝试了下,发现不用mask也没关系,mask的定义也不一定要是灰度图(即imread第二个参数设定为0)。对此,我表示不理解,反正能用就好了。
图像线性混合
直接把logo图替换掉ROI区域的做法通常不是很好,如果能把两者各按一定比例进行混合就显得更好些,这需要用到图像混合技术。
图像线性混合,其实就是不同图片(这里以两张图为例),各自按照一定比例系数进行相加,没什么神奇的地方:
result = alpha*src1 + beta*src2 + gamma
使用函数addWeighted(src1, alpha, src2, beta, gamma, dstImage, dtype=-1)
这里dtype参数,是输出阵列的可选深度,有默认值-1。;当两个输入数组具有相同的深度时,这个参数设置为-1(默认值),即等同于src1.depth()。
OK,粗略想下线性混合的步骤:
- 定义两幅图像
- 定义权重和偏置量等参数
- 按参数做图像混合
- 显示结果
上代码:
#include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { //【1】定义两幅图像 //【2】定义权重和偏置量等参数 //【3】按参数做图像混合 //【4】显示结果 //【1】定义两幅图像 Mat srcImage1 = imread("/home/chris/workspace/clion/mogu.jpg"); Mat srcImage2 = imread("/home/chris/workspace/clion/rain.jpg"); //【2】定义权重和偏置量等参数 double alpha = 0.5; //第一幅图的权重 double beta = 1- alpha; //第二幅图的权重 double gamma = 0.0; //偏置量 //【3】按参数做图像混合 Mat dstImage; //目标图像,存放结果 addWeighted(srcImage1, alpha, srcImage2, beta, gamma, dstImage); //【4】显示结果 imshow("线性混合结果", dstImage); waitKey(0); destroyAllWindows(); return 0; }
好吧,其实这东西很简单。应用到ROI区域,对应的代码为:
#include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { //【1】定义两幅图像 //【2】定义ROI区域 //【3】定义权重和偏置量等参数 //【4】按参数做图像混合 //【5】显示结果 //【1】定义两幅图像 Mat srcImage1 = imread("/home/chris/workspace/clion/dota_pa.jpg"); Mat srcImage2 = imread("/home/chris/workspace/clion/dota_ss.png"); //【2】定义ROI区域 Mat imageROI = srcImage1(Rect(20, 25, srcImage2.cols, srcImage2.rows)); //【3】定义权重和偏置量等参数 double alpha = 0.5; //第一幅图的权重 double beta = 1- alpha; //第二幅图的权重 double gamma = 0.0; //偏置量 //【4】按参数做图像混合 addWeighted(imageROI, alpha, srcImage2, beta, gamma, imageROI); //【5】显示结果 imshow("线性混合结果", srcImage1); waitKey(0); destroyAllWindows(); return 0; }
多通道的分离和混合
既然前面把图像混合讲到了,那么按照通道进行混合也就可以做了!比如要把看起来是白色的logo图,和指定背景图上ROI区域混合,并且希望logo图显示为红色。这就需要ROI图本身为红色通道,logo图读取为灰度图像(保证都是单通道),然后混合,这之后由于ROI区域就是原图中的一个通道上的一个区域,原图像的红色通道变化了,现在把三个通道重新合并回去,就能够得到想要的效果图了。
粗略想下,步骤为:
- 定义义两幅图像
- 分离通道
- 在通道图上定义ROI区域
- 定义权重和偏置量等参数
- 按参数做图像混合
- 合并通道
- 显示结果
对应的代码为:
#include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { //义两幅图像 //【2】分离通道 //【3】在通道图上定义ROI区域 //【4】定义权重和偏置量等参数 //【5】按参数做图像混合 //【6】合并通道 //【7】显示结果 //【1】定义两幅图像 Mat srcImage = imread("/home/chris/workspace/clion/dota_pa.jpg"); Mat logoImage = imread("/home/chris/workspace/clion/dota_logo.jpg", 0); //【2】分离通道 vector<Mat> channels; split(srcImage, channels); //【3】在通道图上定义ROI区域 Mat redChannelImage = channels.at(2); Mat imageROI = redChannelImage(Rect(50, 25, logoImage.cols, logoImage.rows)); //【4】定义权重和偏置量等参数 double alpha = 1.0; double beta = 0.5; double gamma = 0.0; //【5】按参数做图像混合 addWeighted(imageROI, alpha, logoImage, beta, gamma, imageROI); //【6】合并通道 merge(channels, srcImage); //【7】显示结果 imshow("0通道", srcImage); waitKey(0); destroyAllWindows(); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
2014-10-04 ld 脚本浅析-LD手册粗糙翻译