opencv笔记2:图像ROI


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;

}
时间: 2024-08-31 15:06:10

opencv笔记2:图像ROI的相关文章

opencv笔记6:角点检测

time:2015年10月09日 星期五 23时11分58秒 # opencv笔记6:角点检测 update:从角点检测,学习图像的特征,这是后续图像跟踪.图像匹配的基础. 角点检测是什么鬼?前面一篇学习笔记是各种模板操作,是图像增强技术. 那么我节写来应该继续找下有没有别的图像增强技术. 但是,我对增强还不是特别理解.图像增强:划定ROI区域,然后想方设法将感兴趣的特征有选择的突出.注意,这可是不去考虑图像质量下降的原因的.图像恢复:针对图像降质的原因,设法去补偿降质因素,从而使改善后的图像尽

【OpenCV】访问图像中每个像素的值 (I)

最近要做的东西要对每个像素值进行处理,所以上网搜... 居然发现搜出来的好文章都是一个人写的,而且还是一个妹子..于是收藏之...按时间顺序发! 转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/7557063 !!此篇是基于IplImage* (C接口或者说2.1之前版本的接口,新的Mat的访问方式请参考博文: <访问Mat图像中每个像素的值>) IplImage是OpenCV中CxCore部分基础的数据结构,用来表示图像,其中

opencv笔记3:trackbar简单使用

time:2015年 10月 03日 星期六 13:54:17 CST # opencv笔记3:trackbar简单使用 当需要测试某变量的一系列取值取值会产生什么结果时,适合用trackbar.看起来就是debug的一种技术手段了. 主要是使用createTrackbar函数.具体讲,是把trackbar放到一个窗口中,并为trackbar设定回调函数,步骤还是有点繁琐的: 定义图像 定义窗口 定义回调函数 创建trackbar 回调函数初始化 善后工作 其中回调函数参数规定为(int, vo

opencv笔记5:频域和空域的一点理解

time:2015年10月06日 星期二 12时14分51秒 # opencv笔记5:频域和空域的一点理解 空间域和频率域 傅立叶变换是f(t)乘以正弦项的展开,正弦项的频率由u(其实是miu)的值决定.因为积分后左边剩下的为一变量是频率,所以我们说傅立叶变换域是频率域. (<数字图像处理>冈萨雷斯,中文第三版P128) 当变量t用于说明图像时,我们一般将变量t的域称为空间域. 按<图像处理>(章毓晋)的理解,首先是认同模板操作的,然后借助卷积定理,将模板操作转化为傅立叶的乘积,也

opencv笔记1:opencv的基本模块,以及环境搭建

opencv笔记1:opencv的基本模块,以及环境搭建 安装系统 使用fedora22-workstation-x86_64 安装opencv sudo dnf install opencv-devel 安装cmake sudo dnf install cmake 查看opencv的基本模块 cd /usr/include/opencv2/ vim opencv_modules.hpp 内容如下: #define HAVE_OPENCV_CALIB3D #define HAVE_OPENCV_

opencv笔记4:模板运算和常见滤波操作

time:2015年10月04日 星期日 00时00分27秒 # opencv笔记4:模板运算和常见滤波操作 这一篇主要是学习模板运算,了解各种模板运算的运算过程和分类,理论方面主要参考<图像工程--图像处理>(章毓晋)一书第3章,空域增强:模板操作.同时也有个疑问:此书第四章,频域图像增强,讲了低通滤波和高通滤波,然而这些东西和模板运算中的平滑.锐化操作有什么区别?... 以下是正文: 模板运算 首先我们把所有图像看作矩阵. 模板一般是nxn(n通常是3.5.7.9等很小的奇数)的矩阵.模板

无法解析的外部符号-opencv简单的图像程序,总是出现下面的错误,解决不了!

问题描述 opencv简单的图像程序,总是出现下面的错误,解决不了! opencv简单的图像程序,总是出现下面的错误,解决不了啊!vs2013,vs2010都一样!!!谢谢各位帮帮我!! 我被折磨好几天了!!都重装几次了!!快哭了!!网上也没找到准确的解决方法!!! 谢谢大神们帮助!!没有C币... 解决方案 你的opencv环境配置过没?建议按教程配置下 解决方案二: 需要添加lib库文件http://blog.csdn.net/zyxlinux888/article/details/8048

opencv怎样实现图像投影

问题描述 opencv怎样实现图像投影 就是知道x,y转化后的坐标x'y'要怎么将图像上的点进行转换,是要用矩阵吗,这方面的知识欠缺,求问各位大神! 解决方案 http://blog.csdn.net/superdont/article/details/24959481 解决方案二: http://blog.sina.com.cn/s/blog_6b556c2f0102v2q3.html 解决方案三: OpenCV实现图像在水平方向上投影[OpenCV]图像的投影校正opencv实现图像旋转 解

kinect开发-如何用opencv读取kinect图像进行处理

问题描述 如何用opencv读取kinect图像进行处理 如何用opencv读取kinect图像进行处理,,即如何将opencv与kinect联系起来,图像格式需要转化或者别的什么吗? 解决方案 http://blog.csdn.net/yongshengsilingsa/article/details/37935975