今天我们来看一下如何访问图像的像素,以及如何改变图像的亮度与对比度。

在之前我们先来看一下图像矩阵数据的排列方式。我们以一个简单的矩阵来说明:

对单通道图像排列如下:

对于双通道图像排列如下:

那么对于三通道的RGB图像则为:

知道了排列方式之后我们来讨论一下访问图像像素常用的三种方式:

1.使用指针访问;

2.使用迭代器访问;

3.使用动态地址访问;

为了比较一下三种方式的效率,我们介绍两个函数来统计一下每种方式所需的时间。

int64 getTickCount()函数:返回CPU自某个时间(如开启电脑)以来走过的时钟周期数。

double getTickFrequency()函数:返回每秒钟CPU走过的时钟周期数。

然后我们来看第一种方式。

1.使用指针访问图像像素:我们将输入图像img_src的每一个像素值加上50后赋值给输出图像img_dst。

1 intmain()2 {3 intc;4 Mat img_src = imread("1.jpg");5 Mat img_dst;6

7 namedWindow("原图");8 namedWindow("处理图");9

10 int channels = img_src.channels();//获取图像通道数

11 img_dst =img_src.clone();12

13 double time1 = static_cast(getTickCount());//获取开始处理前时间

14

15 for (int i = 0; i < img_src.rows; i++)//访问图像行数据

16 {17 uchar* p_data1 = img_src.ptr(i);//获取图像行首地址

18 uchar* p_data2 = img_dst.ptr(i);//获取图像行首地址

19 for (int k = 0; k < img_src.cols*channels; k++)//获取图像列(含通道)

20 {21 p_data2[k] = saturate_cast(p_data1[k] + 50);//图像处理22

23 //*p_data2++ = saturate_cast((*p_data1++) + 100);//与上一行图像处理的等效方式24 //*(p_data2 + k) = saturate_cast(*(p_data1 + k) + 50);//同上

25 }26 }27

28 double time2 = static_cast(getTickCount());//获取结束处理时间

29

30 time1 = (time2 - time1) / getTickFrequency();//计算处理所用时间

31 cout << "指针访问像素时间(S):" << time1 <

33 while (1)34 {35 imshow("原图", img_src);//显示图像

36 imshow("处理图", img_dst);//显示图像

37 c = waitKey(0);38 if (c == 27 || char(c) == 'q' || char(c) == 'Q')//按下Q键或者ESC键退出程序

39 break;40 }41 return 0;42 }

2.使用迭代器方式:

1 intmain()2 {3 intc;4 Mat img_src = imread("1.jpg");5 Mat img_dst;6

7 namedWindow("原图");8 namedWindow("处理图");9

10 int channels = img_src.channels();//获取图像通道数

11 img_dst =img_src.clone();12

13 double time1 = static_cast(getTickCount());//获取开始处理前时间

14

15 Mat_::iterator it = img_src.begin();//获取原图开始地址

16 Mat_::iterator itend = img_src.end();//获取原图结束地址

17 Mat_::iterator it2 = img_dst.begin();//获取输出图开始地址

18 for (; it != itend; ++it, ++it2)19 {20 for (int i = 0; i < 3; i++)21 {22 (*it2)[i] = saturate_cast((*it)[i] + 50);//图像处理

23 }24 }25

26 double time2 = static_cast(getTickCount());//获取结束处理时间

27

28 time1 = (time2 - time1) / getTickFrequency();//计算处理所用时间

29 cout << "指针访问像素时间(S):" << time1 <

31 while (1)32 {33 imshow("原图", img_src);//显示图像

34 imshow("处理图", img_dst);//显示图像

35 c = waitKey(0);36 if (c == 27 || char(c) == 'q' || char(c) == 'Q')//按下Q键或者ESC键退出程序

37 break;38 }39 return 0;40 }

3.动态地址方式:

1 intmain()2 {3 intc;4 Mat img_src = imread("1.jpg");5 Mat img_dst;6

7 namedWindow("原图");8 namedWindow("处理图");9

10 int channels = img_src.channels();//获取图像通道数

11 img_dst =img_src.clone();12

13 double time1 = static_cast(getTickCount());//获取开始处理前时间

14

15 for (int i = 0; i < img_src.rows; i++)16 {17 for (int k = 0; k < img_src.cols; k++)18 {19 for (int j = 0; j < channels; j++)20 {21 img_dst.at(i, k)[j] = saturate_cast(img_src.at(i, k)[j] + 50);22 }23 }24 }25

26 double time2 = static_cast(getTickCount());//获取结束处理时间

27

28 time1 = (time2 - time1) / getTickFrequency();//计算处理所用时间

29 cout << "指针访问像素时间(S):" << time1 <

31 while (1)32 {33 imshow("原图", img_src);//显示图像

34 imshow("处理图", img_dst);//显示图像

35 c = waitKey(0);36 if (c == 27 || char(c) == 'q' || char(c) == 'Q')//按下Q键或者ESC键退出程序

37 break;38 }39 return 0;40 }

我们来看一下处理的结果吧:

实例

下面我们来看一个完整调用三种方式的例子,我们定义三个函数Mat image_bright1(Mat src);Mat image_bright2(Mat src);Mat image_bright3(Mat src);分别用来用三种方式处理图片。

1 //************头文件包含*************

2 #include "stdafx.h"

3 #include

4 #include//包含opencv的头文件5 //***********************************6

7

8 //************命名空间***************

9 using namespace cv;//使用opencv命名空间

10 using namespacestd;11 //***********************************12

13

14 //************全局变量***************15

16 //***********************************17

18

19 //************全局函数***************

20 Mat image_bright1(Mat src);//使用指针访问像素

21

22 Mat image_bright2(Mat src);//使用迭代器访问像素

23

24 Mat image_bright3(Mat src);//使用动态地址访问像素25 //***********************************26

27

28 //************主函数*****************

29 intmain()30 {31 intc;32 Mat img_src = imread("1.jpg");33 Mat img_dst1, img_dst2, img_dst3;34

35 namedWindow("原图",0);36 namedWindow("指针访问像素",0);37 namedWindow("迭代器访问像素",0);38 namedWindow("动态地址访问像素",0);39

40 double time1 = static_cast(getTickCount());41 img_dst1 = image_bright1(img_src);//使用指针访问像素

42

43 double time2 = static_cast(getTickCount());44 img_dst2 = image_bright2(img_src);//使用迭代器访问像素

45

46 double time3 = static_cast(getTickCount());47 img_dst3 = image_bright3(img_src);//使用动态地址访问像素

48

49 double time4 = static_cast(getTickCount());50

51 time1 = (time2 - time1) /getTickFrequency();52 time2 = (time3 - time2) /getTickFrequency();53 time3 = (time4 - time3) /getTickFrequency();54

55 cout << "指针访问像素时间(S):"<

59 while (1)60 {61 imshow("原图", img_src);//显示图像

62 imshow("指针访问像素", img_dst1);//显示图像

63 imshow("迭代器访问像素", img_dst2);//显示图像

64 imshow("动态地址访问像素", img_dst3);//显示图像

65

66 c = waitKey(0);67 if (c == 27 || char(c) == 'q' || char(c) == 'Q')//按下Q键或者ESC键退出程序

68 break;69 }70

71 return 0;72 }73

74

75 //使用指针访问像素

76 Mat image_bright1(Mat src)77 {78 Mat dst;79 int channels =src.channels();80 dst =src.clone();81

82 for (int i = 0; i < src.rows; i++)83 {84 uchar* p_data1 =src.ptr(i);85 uchar* p_data2 =dst.ptr(i);86

87 for (int k = 0; k < src.cols*channels; k++)88 {89 //*p_data2++ = saturate_cast((*p_data1++) + 100);90 //*(p_data2 + k) = saturate_cast(*(p_data1 + k) + 50);

91 p_data2[k] = saturate_cast(p_data1[k] + 50);//输出图像像素=原图像像素+50

92 }93 }94 returndst;95 }96

97

98 //使用迭代器访问像素

99 Mat image_bright2(Mat src)100 {101 Mat dst;102 dst =src.clone();103

104 Mat_::iterator it = src.begin();105 Mat_::iterator itend = src.end();106 Mat_::iterator it2 = dst.begin();107 for (; it != itend; ++it, ++it2)108 {109 for (int i = 0; i < 3; i++)110 {111 (*it2)[i] = saturate_cast(2*(*it)[i]);//输出图像像素=2*原图像像素

112 }113 }114 returndst;115 }116

117

118 //使用动态地址访问像素

119 Mat image_bright3(Mat src)120 {121 Mat dst;122 int channels =src.channels();123 dst =src.clone();124 for (int i = 0; i < src.rows; i++)125 {126 for (int k = 0; k < src.cols; k++)127 {128 for (int j = 0; j < channels; j++)129 {130 dst.at(i, k)[j] = saturate_cast(2*src.at(i, k)[j] + 50);//输出图像像素=2*原图像像素+50

131 }132 }133 }134 returndst;135 }

结果:

从时间上我们可以看出来,使用指针的速度是最快的。

有些童鞋应该已经看出来了,在三种方法中我们将图像像素的处理方法变了一下,得出的图像也不一样了。在三种方法中我们处理像素的计算方式分别为:

输出图像像素=原图像像素+50;

输出图像像素=2*原图像像素;

输出图像像素=2*原图像像素+50;

其实这就是处理亮度与对比度的方法,从图像上也能看出来。

总结一下:g(x)=k*f(x)+b;其中g(x)为输出图像,f(x)为输入图像;

调节k的值则可以改变图像的对比度;

调节b的值则可以改变图像的亮度;

下载

功能很简单,代码很少,建议自己写一下或者在博文中复制一下,当然实在是懒的不要不要的土豪可以去下面的连接直接下载。

opencv计算图像亮度调节_【opencv学习笔记七】访问图像中的像素与图像亮度对比度调整...相关推荐

  1. 《OpenCV3编程入门》学习笔记5 Core组件进阶(一)访问图像中的像素

    第5章 Core组件进阶 5.1 访问图像中的像素 5.1.1 图像在内存中的存储方式 1.图像矩阵大小取决于通道数,矩阵中的子列个数与通道数相等. 2.如果内存足够大,可以实现连续存储,有助于提升图 ...

  2. 【OpenCV】OpenCV实战从入门到精通之 -- 访问图像中的像素

    目录 1.图像在内存之中的存储方式 2.颜色空间缩减 3.LUT函数:Look up table操作 4.计时函数 5.访问图像中像素的三类方法 5.1.指针访问像素 5.2.迭代器操作像素 5.3. ...

  3. 相机计算坐标公式_相机标定后,从图像坐标(像素)向物理坐标的转换计算,...

    各位大侠,本人用1组35张图片,标定相机参数.分别用MATLAB和OPENCV分别标定,标定结果基本一致. 现在,我希望从标定的一副图像中(使用这幅图像标定的相机外参),计算图像上几个红点之间的在3维 ...

  4. 【OpenCV】OpenCV函数精讲之 -- 访问图像中的像素

    图像在内存之中的存储方式: 图像矩阵的大小取决于所用的颜色模型,确切说,取决于所用通道数.如果是灰度图像,矩阵就会如图5.1所示. 对于多通道图像来说,矩阵中的列会包含多个子列,其子列个数与通道数相同 ...

  5. 三相逆变器双pi控制器参数如何调节_电工学习笔记 - 比例谐振控制器- PR controller...

    ===============本文为个人学习小结,方便自己和其他同学参考使用========= ===============如有错误望同学们指出,不定期进行补充更新============= 一般大 ...

  6. android将彩图转为黑白_[Android学习笔记九] Android 开发中图片灰阶(黑白)显示...

    阅读本文之前关于将RGB颜色值转换为灰阶值的计算方法可参见: 灰阶显示图片的典型应用就是用户头像,如用户在线头像显示彩色(原图),不在线显示灰色(黑白图).总结一点就是更加一张原始图片来通过颜色的过滤 ...

  7. 【OpenCV】OpenCV函数精讲之 -- 访问图像中的像素--计时函数

    计时函数: 简便的计时函数:getTickCount()和get TickFrequency() getTickCount()函数:返回CPU自某个事件以来走过的时钟周期数 getTickFreque ...

  8. OpenCV访问Mat图像中每个像素的值

    原文:http://blog.csdn.net/xiaowei_cqu/article/details/7771760 matlab中, a=[1,2,3;4,5,6;7,8,9] a(1,2) 第一 ...

  9. OpenCV学习笔记(七)——图像梯度及边缘检测

    图像梯度计算的是图像变化的速度.对于图像的边缘部分,其灰度值变化较大,梯度值也较大:相反,对于图像中比较平滑的部分,其灰度值变化较小,相应的梯度值也较小.一般情况下,图像梯度计算的是图像的边缘信息. ...

最新文章

  1. php实现附件上传下载,PHP实现文件上传与下载
  2. 在Eclipse中添加JDK源码包
  3. linux usb声卡 submit urb,linux usb urb详解
  4. 二叉树的前序中序后序 递归与非递归解法
  5. “”和“”的你真的理解吗?
  6. C语言—黑客数字雨特效
  7. C#: PDF转图片(ghostscript)
  8. 微信小程序自动化测试——智能化 Monkey
  9. ignite 集成oracle,Ignite 配置更新Oracle JDBC Drive
  10. 使用Tor以加密方式发送BCH
  11. 陈经纶2021年高考成绩查询时间,北京30余所高中2017年高考成绩汇总
  12. Latex ulem包设置下划线删除线强调文本等效果
  13. 运营版uniapp多商户商城小程序+H5+APP+商家入驻短视频社区种草直播阶梯拼团
  14. 修改CheckBox选择框、设置选择框颜色
  15. Poi 自定义封装方法 合并excel中的单元格
  16. 惊闻!港媒:中国首艘航母海试时间延后1个月(图)
  17. 告诉你那里最受欢迎,python爬取全国13个城市旅游数据
  18. (每日一练c++)解数独
  19. 随手记——(细节)1
  20. 昆明理工大学计算机组成原理考试,昆工计科组成原理实验の计算机组成原理各部件实验.doc...

热门文章

  1. 了解Ceph 分布式存储
  2. linux16.04安装NS-3-DCE的一些记录
  3. 在腾讯、阿里、字节跳动工作的区别
  4. 基于C语言的分数阶微分方程,基于分数阶C~α空间的积分微分方程的配置解法
  5. 计算机论文答辩注意哪些问题,计算机科学与技术在职研究生论文答辩注意事项...
  6. 时间复杂度分析符号说明
  7. StyleSheet样式编写和查找
  8. 机动车驾驶员考试系统(科目二、三)数据采集卡介绍
  9. 一行代码求出100以内为3倍数的所有数
  10. 集合的生产力工具类:Collections,我直呼好家伙。。