opencv笔记2:图像ROI

简介: time:2015年 10月 03日 星期六 12:03:45 CST# opencv笔记2:图像ROIROIROI意思是Region Of Interests,感兴趣区域,是一个图中的一个子区域。

time:2015年 10月 03日 星期六 12:03:45 CST

# 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;

}
目录
相关文章
|
2月前
|
监控 API 计算机视觉
OpenCV这么简单为啥不学——1.3、图像缩放resize函数
OpenCV这么简单为啥不学——1.3、图像缩放resize函数
39 0
|
3月前
|
存储 新制造 开发工具
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为Mat图像格式(C++)
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为Mat图像格式(C++)
41 2
|
3月前
|
监控 算法 开发工具
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现获取图像并对图像进行边缘检测(C#)
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现获取图像并对图像进行边缘检测(C#)
41 1
|
3月前
|
存储 监控 开发工具
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为AVI视频格式(C#)
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为AVI视频格式(C#)
25 0
|
3月前
|
存储 监控 开发工具
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为AVI视频格式(C++)
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为AVI视频格式(C++)
33 0
|
3月前
|
存储 新制造 开发工具
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为Mat图像格式(C#)
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为Mat图像格式(C#)
29 0
|
1月前
|
计算机视觉
OpenCV(三十):图像膨胀
OpenCV(三十):图像膨胀
20 0
|
1月前
|
计算机视觉
OpenCV(二十九):图像腐蚀
OpenCV(二十九):图像腐蚀
24 0
|
1月前
|
计算机视觉
OpenCV(二十七):图像距离变换
OpenCV(二十七):图像距离变换
20 0
|
1月前
|
计算机视觉 Python
OpenCV 4基础篇| OpenCV图像的拆分和合并
OpenCV 4基础篇| OpenCV图像的拆分和合并