【opencv学习笔记】第五篇:访问图像中像素的三种方式、ROI区域图像叠加和图像混合
1. 访问图像中像素的三种方式
任何图像处理算法,都是从操作每个像素开始的。在OpenCV中,提供了三种访问每个像素的方法。
- 方法1:指针访问:C操作符[]
- 方法2:迭代器iterator
- 方法3:动态地址计算
三种访问速度的比较:指针访问 > 迭代器访问 > 动态地址
。指针访问速度最快。需要注意的是,OpenCV中的彩色图像不是以RGB的顺序存放的,而是BGR
。
方法1:指针访问
通过调用函数 Mat::ptr(i) 来得到第i行的首地址地址,然后在行内访问像素;ptr是一个模板函数
,它返回第i行的首地址。注意uchar与Vec3b的区别,uchar需要乘以一个通道数
。
void test01()
{//指针的访问for (int i = 0; i < Row; i++){for (int j = 0; j < Col; j++){Scr.ptr<Vec3b>(i)[j][0] = 0;//Scr.ptr<uchar>(i)(3*j) = 0; //注意uchar与Vec3b的区别,uchar需要乘以一个通道数}}
}
方法2:迭代器操作像素
这种方式与STL库的用法类似,创建一个Mat::Iterator对象it,通过it=Mat::begin()迭代器访问首地址,递增迭代器直到it==Mat::end()结束迭代;
void test02()
{//迭代器访问,访问的是每一个像素点Mat_<Vec3b>::iterator it = Scr.begin<Vec3b>();while (it != Scr.end<Vec3b>()){//(*it)[0] = 0;//蓝色通道置零;BGR存储(*it)[1] = 0; //绿色通道置零;//(*it)[2] = 0;//红色通道置零;it++;}
}
方法3:动态地址计算
这种方法是最慢的一种方法,但是比较好理解,使用at函数来得到像素,Mat::at(i,j)为一个像素点的像素值数组,是一个大小为3的数组。从0到2存放了BGR三种颜色的灰度值。
void test03()
{//动态访问,访问的是每一个像素点,最慢也是最直接易理解的访问方式for (int i = 0; i < Row; i++){for (int j = 0; j < Col; j++){Scr.at<Vec3b>(i, j)[2] = 0;}}
}
整体代码示例
#include <opencv2/opencv.hpp>
#include <iostream>using namespace std;
using namespace cv;Mat Scr;
int Row;
int Col;void test01()
{//指针的访问for (int i = 0; i < Row; i++){for (int j = 0; j < Col; j++){Scr.ptr<Vec3b>(i)[j][0] = 0;}}
}
void test02()
{//迭代器访问,访问的是每一个像素点Mat_<Vec3b>::iterator it = Scr.begin<Vec3b>();while (it != Scr.end<Vec3b>()){//(*it)[0] = 0;//蓝色通道置零;BGR存储(*it)[1] = 0; //绿色通道置零;//(*it)[2] = 0;//红色通道置零;it++;}
}
void test03()
{//动态访问,访问的是每一个像素点,最慢也是最直接易理解的访问方式for (int i = 0; i < Row; i++){for (int j = 0; j < Col; j++){Scr.at<Vec3b>(i, j)[2] = 0;}}
}int main()
{Scr = imread("/home/liqiang/Data/vision/classic/lena.jpg");if (Scr.empty()){printf("%s\n", "读入图片失败;");return 1;}imshow("原始图像", Scr);Row = Scr.rows; //获取行数目;Col = Scr.cols; //获取列数目;int Channel = Scr.channels(); //获取通道数目;test01();//指针访问test02();//迭代器访问test03();//动态访问imshow("改变后的图像", Scr);waitKey(0);return 1;
}
输出:
2. 感兴趣区域ROI和图像叠加
2.1 感兴趣区域ROI
在图像处理领域,常常需要设置感兴趣区域(ROI,region of interest)来专注或者简化工作过程。即从图像中圈定一个区域,以便进行进一步处理。使用ROI指定想读入的目标,可以减少处理时间,增加精度,给图像处理带来不小的便利。
定义ROI区域有两种方式:
- 方法1:使用矩形区域的Rect,指定矩形的左上角坐标(构造函数的前两个参数)和矩形的长宽(构造函数的后两个参数)就可以定义一个矩形区域。
Mat = image;//载入的图片
Mat imageROI = image(Rect(500, 250, logo.cols, logo.rows));//左上角,width,height
- 方法2:指定感兴趣区域
行和列的范围
(Range),Range表示从起始索引到终止(不包含)索引的一段连续序列。
imageROI = image(Range(250, 250 + logoImage.rows), Range(200, 200 + logoImage.cols));
注意两种形式,行和列的顺序不同
。
2.2 图像叠加
下面使用ROI实现图像的叠加操作,实际上就是copy操作。原书采用的掩模的形式,实际上不需要,可以直接拷贝。
#include <opencv2/opencv.hpp>
#include <iostream>using namespace std;
using namespace cv;int main()
{//【1】读入图像Mat srcImage1 = imread("/home/liqiang/Data/vision/classic/lena.jpg");//512*512Mat logoImage = imread("/home/liqiang/Data/vision/classic/WindowsLogo.jpg");//240*320if (!srcImage1.data){printf("读取srcImage1错误~! \n");return false;}if (!logoImage.data){printf("读取logoImage错误~! \n");return false;}//【2】定义一个Mat类型并给其设定ROI区域Mat imageROI = srcImage1(Rect(0, srcImage1.rows-logoImage.rows, logoImage.cols, logoImage.rows));//左下角//【3】加载掩模(必须是灰度图)Mat mask;cvtColor(logoImage, mask, COLOR_RGB2GRAY);//用转换函数转换成灰度图//【4】将掩膜拷贝到ROI//logoImage.copyTo(imageROI, mask);logoImage.copyTo(imageROI);//不用掩膜,直接拷贝//【5】显示结果namedWindow("<1>利用ROI实现图像叠加示例窗口");imshow("<1>利用ROI实现图像叠加示例窗口", srcImage1);waitKey(0);return true;
}
输出效果:
3. 图像混合(线性混合)
线性混合操作是一种典型的二元(两个输入)的像素操作,它的理论公式如下:
g(x)=(1−a)f1(x)+af2(x)g(x) = (1-a)f_1(x)+af_2(x) g(x)=(1−a)f1(x)+af2(x)
可以通过alpha在0-1之间的变化,来对两幅图像或者两段视频产生时间上的画面叠化(cross-dissolve)
效果,类似于幻灯片和电影制作中的那样,也就是幻灯片翻页或者电影情节过渡
时的效果。
实现方面,主要运用了Opencv中的addWeighted函数来实现。它的函数原型如下:
addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype = -1);
- src1和src2分别表示两幅图像
- alpha和beta分别表示两幅图像的权重
- dst表示输出图像
- gamma加载到dst的权重
- dtype表示图像深度,即src1.depth()
dst = src1 * alpha + src2 * beta + gamma
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{Mat src1 = imread("/home/liqiang/Data/vision/classic/LinuxLogo.jpg");Mat src2 = imread("/home/liqiang/Data/vision/classic/WindowsLogo.jpg");Mat dst;double alpha = 0.6;addWeighted(src1, alpha, src2, 1 - alpha, 0.0, dst);imshow("dst", dst);waitKey(0);return 0;
}
输出效果:
还可以结合感兴趣区域和线性混合来实现部分混合,这里就不介绍了,实现起来应该不难。
【opencv学习笔记】第五篇:访问图像中像素的三种方式、ROI区域图像叠加和图像混合相关推荐
- OpenCV精进之路(零):访问图像中像素的三种方法
访问像素的三种方法 指针访问:最快 迭代器iterator:较慢,非常安全,指针访问可能出现越界问题 动态地址计算:更慢,通过at()实现.适用于访问具体某个第i行,j列的像素,而不适用遍历像素 这里 ...
- OpenCV学习笔记(五十六)——InputArray和OutputArray的那些事core OpenCV学习笔记(五十七)——在同一窗口显示多幅图片 OpenCV学习笔记(五十八)——读《Mast
OpenCV学习笔记(五十六)--InputArray和OutputArray的那些事core 看过OpenCV源代码的朋友,肯定都知道很多函数的接口都是InputArray或者OutputArray ...
- OpenCV学习笔记(五十一)——imge stitching图像拼接stitching OpenCV学习笔记(五十二)——号外:OpenCV 2.4.1 又出来了。。。。。 OpenCV学习笔记(五
OpenCV学习笔记(五十一)--imge stitching图像拼接stitching stitching是OpenCV2.4.0一个新模块,功能是实现图像拼接,所有的相关函数都被封装在Stitch ...
- Android学习笔记第五篇--网络连接与云服务(一)
Android学习笔记第五篇–网络连接与云服务 第一章.无线连接设备 除了能够在云端通讯,Android的无线API也允许在同一局域网内的设备通讯,**甚至没有连接网络,而是物理具体相近,也可以相 ...
- OpenCV学习笔记(五):线性滤波-方框、均值、高斯:boxFilter(),blur(),GaussianBlur()
OpenCV学习笔记(五):线性滤波-方框.均值.高斯:boxFilter(),blur(),GaussianBlur() 线性滤波:即多个信号之和的响应和它们各自响应之和相等. 参考: https: ...
- OpenCV学习笔记(六):非线性滤波-中值、双边:medianBlur(),bilateralFilter()
OpenCV学习笔记(六):非线性滤波-中值.双边:medianBlur(),bilateralFilter() 1.中值滤波(Median filter) 是一种典型的非线性滤波技术,基本思想是用像 ...
- OpenCV学习笔记(五):Mat结构
在之前的OpenCV学习笔记(一)用到的几种显示图像的方法中其中一种就是Mat.Mat结构在OpenCV 2.0后才得到广泛应用,相对于OpenCV1.0时代中的IplImage,它有个好处就是不用再 ...
- OpenCV学习笔记(五十四)——概述FaceRecognizer人脸识别类contrib
在最新版的2.4.2中,文档的更新也是一大亮点,refrence manual扩充了200多页的内容,添加了contrib部分的文档.contrib就是指OpenCV中新添加的模块,但又不是很稳定,可 ...
- 数字图像处理学习笔记(七)——用Pycharm及MATLAB实现三种图像内插法(最近邻内插法、双线性内插法、双三次内插法)
数字图像处理(Digital Image Processing)是通过计算机对图像进行去除噪声.增强.复原.分割.提取特征等处理的方法和技术.本专栏将以学习笔记形式对数字图像处理的重点基础知识进行总结 ...
最新文章
- Supervisor使用详解
- 基于VUE只是作为模版引擎的前后端分离
- flutter打开第三方应用
- python解zuobiaoxi方程_吴恩达《Machine Learning》精炼笔记 2:梯度下降与正规方程
- Haiku OS 的黎明
- .NET - Diving into System Programming - Part 2[转贴]
- 【零基础学Java】—throw关键字(四十六)
- java对象描述开车_java面向对象
- 快速在多个word文件里面检索到关键字
- 详解KubeEdge边缘网络项目EdgeMesh
- WIN7 安装使用远程服务器管理工具-如DHCP、AD域、HyperV、远程桌面
- 京剧戏曲电脑主题 +唯美爱心win7主题 +刺猥和苹果卡通主题
- 编写一个 SQL 查询来实现分数排名
- Pandas DataFrame: groupby agg的使用
- element 时间转时间戳
- 深度剖析channel
- 2014年开年计划 - 不积跬步无以至千里
- 【实战】(香港城市大学,微软亚洲研究院)让老照片重现光彩(一):Bringing Old Photos Back to Life
- 对于穷竭搜索算法优化的思考,以一群蚂蚁在竿子上爬行为例
- 前端最全面试指南,从简历到谈薪