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区域图像叠加和图像混合相关推荐

  1. OpenCV精进之路(零):访问图像中像素的三种方法

    访问像素的三种方法 指针访问:最快 迭代器iterator:较慢,非常安全,指针访问可能出现越界问题 动态地址计算:更慢,通过at()实现.适用于访问具体某个第i行,j列的像素,而不适用遍历像素 这里 ...

  2. OpenCV学习笔记(五十六)——InputArray和OutputArray的那些事core OpenCV学习笔记(五十七)——在同一窗口显示多幅图片 OpenCV学习笔记(五十八)——读《Mast

    OpenCV学习笔记(五十六)--InputArray和OutputArray的那些事core 看过OpenCV源代码的朋友,肯定都知道很多函数的接口都是InputArray或者OutputArray ...

  3. OpenCV学习笔记(五十一)——imge stitching图像拼接stitching OpenCV学习笔记(五十二)——号外:OpenCV 2.4.1 又出来了。。。。。 OpenCV学习笔记(五

    OpenCV学习笔记(五十一)--imge stitching图像拼接stitching stitching是OpenCV2.4.0一个新模块,功能是实现图像拼接,所有的相关函数都被封装在Stitch ...

  4. Android学习笔记第五篇--网络连接与云服务(一)

    Android学习笔记第五篇–网络连接与云服务 第一章.无线连接设备 ​ 除了能够在云端通讯,Android的无线API也允许在同一局域网内的设备通讯,**甚至没有连接网络,而是物理具体相近,也可以相 ...

  5. OpenCV学习笔记(五):线性滤波-方框、均值、高斯:boxFilter(),blur(),GaussianBlur()

    OpenCV学习笔记(五):线性滤波-方框.均值.高斯:boxFilter(),blur(),GaussianBlur() 线性滤波:即多个信号之和的响应和它们各自响应之和相等. 参考: https: ...

  6. OpenCV学习笔记(六):非线性滤波-中值、双边:medianBlur(),bilateralFilter()

    OpenCV学习笔记(六):非线性滤波-中值.双边:medianBlur(),bilateralFilter() 1.中值滤波(Median filter) 是一种典型的非线性滤波技术,基本思想是用像 ...

  7. OpenCV学习笔记(五):Mat结构

    在之前的OpenCV学习笔记(一)用到的几种显示图像的方法中其中一种就是Mat.Mat结构在OpenCV 2.0后才得到广泛应用,相对于OpenCV1.0时代中的IplImage,它有个好处就是不用再 ...

  8. OpenCV学习笔记(五十四)——概述FaceRecognizer人脸识别类contrib

    在最新版的2.4.2中,文档的更新也是一大亮点,refrence manual扩充了200多页的内容,添加了contrib部分的文档.contrib就是指OpenCV中新添加的模块,但又不是很稳定,可 ...

  9. 数字图像处理学习笔记(七)——用Pycharm及MATLAB实现三种图像内插法(最近邻内插法、双线性内插法、双三次内插法)

    数字图像处理(Digital Image Processing)是通过计算机对图像进行去除噪声.增强.复原.分割.提取特征等处理的方法和技术.本专栏将以学习笔记形式对数字图像处理的重点基础知识进行总结 ...

最新文章

  1. Supervisor使用详解
  2. 基于VUE只是作为模版引擎的前后端分离
  3. flutter打开第三方应用
  4. python解zuobiaoxi方程_吴恩达《Machine Learning》精炼笔记 2:梯度下降与正规方程
  5. Haiku OS 的黎明
  6. .NET - Diving into System Programming - Part 2[转贴]
  7. 【零基础学Java】—throw关键字(四十六)
  8. java对象描述开车_java面向对象
  9. 快速在多个word文件里面检索到关键字
  10. 详解KubeEdge边缘网络项目EdgeMesh
  11. WIN7 安装使用远程服务器管理工具-如DHCP、AD域、HyperV、远程桌面
  12. 京剧戏曲电脑主题 +唯美爱心win7主题 +刺猥和苹果卡通主题
  13. 编写一个 SQL 查询来实现分数排名
  14. Pandas DataFrame: groupby agg的使用
  15. element 时间转时间戳
  16. 深度剖析channel
  17. 2014年开年计划 - 不积跬步无以至千里
  18. 【实战】(香港城市大学,微软亚洲研究院)让老照片重现光彩(一):Bringing Old Photos Back to Life
  19. 对于穷竭搜索算法优化的思考,以一群蚂蚁在竿子上爬行为例
  20. 前端最全面试指南,从简历到谈薪

热门文章

  1. ORDER BY用法,避坑
  2. (4.2.40)阿里开源路由框架ARouter的源码分析
  3. Mac移动硬盘不正确断开连接导致无法读取加载的解决方法
  4. 跨境电商如何搭建独立站?
  5. Python文字转换语音,抠脚大汉秒变撒娇萌妹
  6. 智慧管廊监控与报警管控一体化系统解决方案
  7. Nothing Phone官宣,手机厂新秀靠啥出圈?
  8. 与网友“阵春风”交流
  9. 我是一只可可爱爱的小粽子
  10. 什么是IP?IP为什么要隔离?浏览器如何实现IP隔离?