设为首页 收藏本站
查看: 2041|回复: 0

[Cloudstack] 访问Mat图像中每个像素的值

[复制链接]

尚未签到

发表于 2015-10-14 07:30:29 | 显示全部楼层 |阅读模式
  http://blog.iyunv.com/xiaowei_cqu/article/details/7771760
  

  

  







  • DSC0000.jpg

小魏的修行路
Talk is cheap. Show me the code.

  • DSC0001.gif 目录视图
  • DSC0002.gif 摘要视图
  • DSC0003.gif 订阅
有奖征资源,博文分享有内涵        社区问答:芈峮iOS测试指南       专访阿里陶辉       2014CSDN博文大赛       10月微软MVP申请 【OpenCV】访问Mat图像中每个像素的值
分类: 【图像处理】2012-07-2207:10 21945人阅读 评论(26) 收藏 举报tabletutorialsmatlabiterator算法up
目录(?)[+]

  今天百度搜资料还搜到了自己的。。。《访问图像中每个像素的值》,这是之前写的了,用的也是2.0的风格IplImage*格式,不太适用后来Mat的格式,特此重写一篇。
  以下例子源自《The OpenCV Tutorials --Release 2.4.2》2.2 How to scan images, lookup tables and time measurement with OpenCV

图像容器Mat
还是先看Mat的存储形式。Mat和Matlab里的数组&#26684;式有点像,但一般是二维向量,如果是灰度图,一般存放<uchar>类型;如果是RGB彩色图,存放<Vec3b>类型。单通道灰度图数据存放&#26684;式: DSC0004.png
多通道的图像中,每列并列存放通道数量的子列,如RGB三通道彩色图: DSC0005.png
注意通道的顺序反转了:BGR。通常情况内存足够大的话图像的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行,这中情况在访问时可以提供很大方便。可以用 isContinuous()函数来判断图像数组是否为连续的。
访问图像中的像素

高效的方法:C操作符[ ]
最快的是直接用C风&#26684;的内存访问操作符[]来访问:[cpp] viewplaincopy

  • Mat& ScanImageAndReduceC(Mat& I, const uchar* const table)  
  • {  
  •     // accept only char type matrices  
  •     CV_Assert(I.depth() != sizeof(uchar));  
  •     int channels = I.channels();  
  •     int nRows = I.rows ;  
  •     int nCols = I.cols* channels;  
  •     if (I.isContinuous())  
  •     {  
  •         nCols *= nRows;  
  •         nRows = 1;  
  •     }  
  •     int i,j;  
  •     uchar* p;  
  •     for( i = 0; i < nRows; &#43;&#43;i)  
  •     {  
  •         p = I.ptr<uchar>(i);  
  •         for ( j = 0; j < nCols; &#43;&#43;j)  
  •         {  
  •             p[j] = table[p[j]];  
  •         }  
  •     }  
  •     return I;  
  • }  
注意:书中这段代码是有问题的,前面写成了
[cpp] viewplaincopy

  • int nRows = I.rows * channels;  
  • int nCols = I.cols;  
一般情况 isContinous为true,运行不会出错,但你可以注释掉那个if,会有访问越界的问题。这种访问形式就是在每行定义一个指针,然后在内存上直接连续访问。如果整个数组在内存上都是连续存放的,那么只需要定义一个指针就可以访问所有的数据!如单通道的灰度图访问方式如下:[cpp] viewplaincopy

  • uchar* p = I.data;  
  • for( unsigned int i =0; i < ncol*nrows; &#43;&#43;i)  
  •     *p&#43;&#43; = table[*p];  

安全的方法:迭代器iterator
相比用指针直接访问可能出现越界问题,迭代器绝对是非常安全的方法:
[cpp] viewplaincopy

  • Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)  
  • {  
  •     // accept only char type matrices  
  •     CV_Assert(I.depth() != sizeof(uchar));  
  •     const int channels = I.channels();  
  •     switch(channels)  
  •     {  
  •     case 1:  
  •         {  
  •             MatIterator_<uchar> it, end;  
  •             for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; &#43;&#43;it)  
  •                 *it = table[*it];  
  •             break;  
  •         }  
  •     case 3:  
  •         {  
  •             MatIterator_<Vec3b> it, end;  
  •             for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; &#43;&#43;it)  
  •             {  
  •                 (*it)[0] = table[(*it)[0]];  
  •                 (*it)[1] = table[(*it)[1]];  
  •                 (*it)[2] = table[(*it)[2]];  
  •             }  
  •         }  
  •     }  
  •     return I;  
  • }  
这里我们只定义了一个迭代器,用了一个for循环,这是因为在OpenCV里迭代器会访问每一列然后自动跳到下一行,不用管在内存上是否isContinous。另外要注意的是在三通道图像中我们定义的是 <Vec3b>&#26684;式的迭代器,如果定义成uchar,则只能访问到B即蓝色通道的&#20540;。
这种方式虽然安全,但是挺慢的,一会儿就知道了。
更慢的方法:动态地址计算
这种方法在需要连续扫描所有点的应用时并不推荐,因为它更实用与随机访问。这种方法最基本的用途是访问任意的某一行某一列:
[cpp] viewplaincopy

  • Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table)  
  • {  
  •     // accept only char type matrices  
  •     CV_Assert(I.depth() != sizeof(uchar));  
  •     const int channels = I.channels();  
  •     switch(channels)  
  •     {  
  •     case 1:  
  •         {  
  •             for( int i = 0; i < I.rows; &#43;&#43;i)  
  •                 for( int j = 0; j < I.cols; &#43;&#43;j )  
  •                     I.at<uchar>(i,j) = table[I.at<uchar>(i,j)];  
  •             break;  
  •         }  
  •     case 3:  
  •         {  
  •             Mat_<Vec3b> _I = I;  
  •   
  •             for( int i = 0; i < I.rows; &#43;&#43;i)  
  •                 for( int j = 0; j < I.cols; &#43;&#43;j )  
  •                 {  
  •                     _I(i,j)[0] = table[_I(i,j)[0]];  
  •                     _I(i,j)[1] = table[_I(i,j)[1]];  
  •                     _I(i,j)[2] = table[_I(i,j)[2]];  
  •                 }  
  •                 I = _I;  
  •                 break;  
  •         }  
  •     }  
  •     return I;  
  • }  
因为这种方法是为随机访问设计的,所以真的是奇慢无比。。。

减小颜色空间 color space reduction
现在来介绍下上述函数对每个元素的操作,也就是用table更改像素&#20540;。这里其实是做了个减小颜色空间的操作,这在一些识别之类的应用中会大大降低运算复杂度。类如uchar类型的三通道图像,每个通道取&#20540;可以是0~255,于是就有 256*256个不同的&#20540;。我们可以通过定义:
0~9 范围的像素&#20540;为 0
10~19 范围的像素&#20540; 为 10
20~29 范围的像素&#20540;为 20
。。。。。。
着这样的操作将颜色取&#20540;降低为 26*26*26 种情况。这个操作可以用一个简单的公式:
DSC0006.png
来实现,因为C&#43;&#43;中int类型除法操作会自动截余。 类如 Iold=14; Inew=(Iold/10)*10=(14/10)*10=1*10=10;
在处理图像像素时,每个像素需要进行一遍上述计算也需要一定的时间花销。但我们注意到其实只有 0~255 种像素,即只有256种情况。进一步可以把256种计算好的结果提前存在表中 table 中,这样每种情况不需计算直接从 table 中取结果即可。
[cpp] viewplaincopy

  • int divideWith=10;   
  • uchar table[256];  
  • for (int i = 0; i < 256; &#43;&#43;i)  
  •     table = divideWith* (i/divideWith);  
于是table存放的是&#20540;为i的像素减小颜色空间的结果,这样也就可以理解上述方法中的操作:
[cpp] viewplaincopy

  • p[j] = table[p[j]];  
LUT : Look up table
OpenCV 很聪明的有个 LUT 函数就是针对这种 Look up talbe 的操作:[cpp] viewplaincopy

  • Mat lookUpTable(1, 256, CV_8U);  
  • uchar* p = lookUpTable.data;  
  • for( int i = 0; i < 256; &#43;&#43;i)  
  •     p = table;  
  • for (int i = 0; i < times; &#43;&#43;i)  
  •     LUT(I, lookUpTable, J);  

算法计时
为了验证几种方法的效率,可以用一个简单的计时和输出:
[cpp] viewplaincopy

  • double t;  
  • t = (double)getTickCount();  
  • t = 1000*((double)getTickCount() - t)/getTickFrequency();  
  • t /= times;  

实验结果

原图:
DSC0007.jpg

降低颜色空间结果:
DSC0008.png

算法时间:
DSC0009.png

更清楚的时间对比表:
DSC00010.png

转载请注明出处:http://blog.iyunv.com/xiaowei_cqu/article/details/7771760
实验代码下载:http://download.iyunv.com/detail/xiaowei_cqu/4443761



更多7

  • 上一篇【编译原理】正则表达式
  • 下一篇【编译原理】用Yacc做语法分析
顶30踩0主题推荐opencv迭代器内存指针安全猜你在找我的OpenCV学习笔记(二):操作每个像素OpenCv的连通域操作计算机视觉目标检测的框架与过程计算机视觉&#43;图像处理的好的链接网站!不断更新中!!!!【模式识别】多层感知器 MLP图像处理与计算机视觉:基础,经典以及最近发展(5)计算机视觉在实验室还是企业实习,这个无定数学习OpenCV:滤镜系列(3)——颜色变幻cvFindContours && cvDrawContours 的应用2-----图像内轮廓填充Android NDK开发篇(一):新版NDK环境搭建(免Cygwin,超级快)查看评论18楼 aprhz 2013-11-01 12:48发表 [回复] DSC00011.jpg I.ptr<uchar>(i)是什么意思?17楼 小魔大树哥 2013-10-17 17:01发表 [回复] DSC00012.jpg 单通道(灰度图)的读取像素 最后像素&#20540;放在哪 table还是p中,初学者请教小魏,还有const uchar*const table[352*288];
uchar *p = I.data ;这两行代码过不去,类型不一致16楼 byctw 2013-06-05 11:49发表 [回复] DSC00013.jpg 请问:
Mat outfile; 要访问其第二个像素
用 outfile.data[1] 的语法是否也可以?15楼 masikkk 2013-06-03 20:23发表 [回复] DSC00014.jpg 知道什么是LUT了14楼 cxchenxingcool 2013-04-18 00:14发表 [回复] DSC00015.jpg 由IplImage*转到Mat,总感觉不适应,在二者之间只能IplImage与Mat互换13楼 郑海波 2013-03-26 11:28发表 [回复] DSC00016.jpg 楼主对android版的OpenCV可有研究?里面的Mat(java版)元素如何访问?Re: xiaowei_cqu 2013-03-26 13:12发表 [回复] DSC00017.jpg 回复NUPTboyZHB:没用过12楼 AaBb301 2012-12-03 21:05发表 [回复] DSC00018.jpg 2了,看到下面原来里有介绍,呵呵11楼 AaBb301 2012-12-03 20:28发表 [回复]突然明白好像是”离散量化“的,请问博主是这个主要功能吗Re: xiaowei_cqu 2012-12-03 20:57发表 [回复]回复AaBb301:嗯,用来减小颜色空间Re: AaBb301 2012-12-03 21:06发表 [回复]回复xiaowei_cqu:嗯 谢谢博主10楼 AaBb301 2012-12-03 20:21发表 [回复]想问下博主,ScanImageAndReduceC函数参数里那个table有什么用啊,我刚学opencv,很多不懂9楼 zhangnzhen 2012-11-20 13:27发表 [回复] DSC00019.jpg 代码里lut的计时部分错了,t=(double)getTickCount()应该在代码执行前面。要不这速度也太发指了~8楼 xiaojidan2011 2012-09-11 13:45发表 [回复] DSC00020.jpg 哦哦哦哦 不好意思的 我刚刚调试了下的 单幅是可以显示的 成功了 嘻嘻 可能运行的时候占据内存太大了的原因的 ,搞不懂 了7楼 xiaojidan2011 2012-09-11 13:41发表 [回复]代码运行编译都没什么问题,局势显示的时候 窗口全部是灰色的,貌&#20284;图像的&#20540;没有传进去的6楼 xiaojidan2011 2012-09-11 13:38发表 [回复]写的很好的呀 但是我跑了代码 却显示不出图像,是怎么回事的呀5楼 jizhihang2000 2012-09-07 14:00发表 [回复] DSC00021.jpg “另外要注意的是在三通道图像中我们定义的是 <Vec3b>&#26684;式的迭代器,如果定义成uchar,则只能访问到B即蓝色通道的&#20540;。”
为什么不是所有像素的所有通道都访问了一遍?Re: xiaowei_cqu 2012-09-07 14:37发表 [回复]回复jizhihang2000:三通道像素是BRG排放的,相当于每个元素里放了三个uchar。迭代器定义成uchar只取出了第一个B的&#20540;,你可以试试4楼 caiqi1123 2012-09-07 10:33发表 [回复] DSC00022.jpg 才女:
代码
03. // accept only char type matrices
04. CV_Assert(I.depth() != sizeof(uchar));
有问题吧?改为:
// accept only char type matrices
CV_Assert(mat.depth() == CV_8U);Re: xiaowei_cqu 2012-09-07 10:42发表 [回复]回复caiqi1123:我传递的参数是I;而且CV_8U不就是uchar的类型嘛Re: caiqi1123 2012-09-07 10:58发表 [回复]回复xiaowei_cqu:回复caiqi1123:CV_8U 宏是0哦。sizeof(uchar)=8
mat.depth() 返回的是CV_8U。仅供探讨啊。3楼 afery 2012-09-06 17:25发表 [回复] DSC00023.jpg 有翻译版的看诶2楼 meiqingfly 2012-07-23 13:28发表 [回复] DSC00024.jpg 这个好呢。。Re: xiaowei_cqu 2012-07-23 14:11发表 [回复]回复meiqingfly:没写什么,是tutorials里自带的例子1楼 skiaazure 2012-07-23 07:45发表 [回复] DSC00025.jpg 我还是习惯用at。。。Re: xiaowei_cqu 2012-07-23 08:46发表 [回复]回复skiaazure:我也是,感觉直接用[]很危险发表评论

  • 用 户 名:
  • wslz2001


  • 评论内容:
  • DSC00026.gif

      
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场 DSC00027.png 核心技术类目
全部主题 Java VPN Android iOS ERP IE10 Eclipse CRM JavaScript Ubuntu NFCWAP jQuery 数据库 BI HTML5 Spring Apache Hadoop .NET API HTML SDK IISFedora XML LBS Unity Splashtop UML components Windows Mobile Rails QEMU KDECassandra CloudStack FTC coremail OPhone CouchBase 云计算 iOS6 RackspaceWeb App SpringSide Maemo Compuware 大数据 aptech Perl Tornado Ruby HibernateThinkPHP Spark HBase Pure Solr Angular Cloud Foundry Redis Scala DjangoBootstrap
    个人资料

    DSC00028.jpg
    xiaowei_cqu DSC00029.gif DSC00030.gif

    • 访问:644509次
    • 积分:11064分
    • 排名:第323名


    • 原创:139篇
    • 转载:0篇
    • 译文:1篇
    • 评论:1723条


    博客专栏

    DSC00031.jpg 图像处理文章:18篇
    阅读:44774 DSC00032.jpg 模式识别文章:13篇
    阅读:43860 DSC00033.jpg 算法设计与分析文章:20篇
    阅读:69232 DSC00034.jpg OpenCV学习与实践文章:30篇
    阅读:294025

    系列索引


  • 【我的本科】 (61)
  • 【我在读研】 (11)
  • 【项目汇总】 (18)

    文章分类


  • 【图像处理】(44)
  • 【机器视觉】(36)
  • 【算法分析】(34)
  • 【数据结构】(5)
  • 【编程语言】(41)
  • 【工程项目】(30)
  • 【模式识别】(15)
  • 【移动开发】(8)
  • 【文艺青年】(9)

    文章搜索



    博主简介

    CS小硕一枚,兴趣领域:计算机视觉、媒体分析、图像处理;认知心理学,生理心理学。
    喜欢C++、Matlab、OpenCV、Qt、UML、VS、XMind等各种优秀的、提高码农生产力的工具。

    爱逛豆瓣<table cellspacing=&quot;0&quot; cellpadding=&quot;4&quot; center&quot;=&quot;&quot;> DSC00035.jpg DSC00036.jpg DSC00037.gif
    我的邮箱
    weilan.cqu#gmail.com


    阅读排行


  • 【OpenCV】SIFT原理与源码分析(23666)
  • 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图(22174)
  • 【OpenCV】访问Mat图像中每个像素的值(21945)
  • 【OpenCV】图像几何变换:旋转,缩放,斜切(19629)
  • 【OpenCV】边缘检测:Sobel、拉普拉斯算子(18858)
  • 【OpenCV】SIFT原理与源码分析:DoG尺度空间构造(17224)
  • 【OpenCV】访问图像中每个像素的值(16641)
  • 【OpenCV】数字图像灰度直方图(16327)
  • 【Error】安装VS2012后VS2010工程失败(15621)
  • 【OpenCV】基于Adaboost和Haar-like特征人脸识别(12845)

    评论排行


  • 【大学生活】在软件学院的那些课(106)
  • 【面向对象】小游戏“终结者”程序的设计与实现(81)
  • 【OpenCV】SIFT原理与源码分析:DoG尺度空间构造(66)
  • 【OpenCV】图像几何变换:旋转,缩放,斜切(49)
  • 【算法分析】查找算法:二分查找、顺序查找(48)
  • 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图(45)
  • 【博客分享】优秀的有趣的博客(45)
  • 【OpenCV】访问图像中每个像素的值(43)
  • 【OpenCV】数字图像灰度直方图(40)
  • 【UML】UML几种图的绘制(39)

    最新评论


  • 【计算机视觉】步态能量图GEI学生新手: 我想问问怎么用MATLAB把保存在TXT文本中的GEI转换成图片
  • 【计算机视觉】会议投稿相关推荐masikkk: http://www.wikicfp.com/cfp/这个网站好,有用,多谢大牛
  • 【OpenCV】访问图像中每个像素的值XiaoShuoYiMei: LZ,又来叨扰了。。。我想把一个cvMat矩阵转化成一幅图片,结果运行出来是灰色的,不知道怎么改,还...
  • 【模式识别】SVM核函数蝴蝶也可以飞过沧海: 第二个多项式核函数是不是少了个y呢?
  • 【OpenCV】视频标注工具frank133788: 你好,你给的链接怎么打不开啊,我想下载你的源码。
  • 【模式识别】Learning To Rank之RankBoostxiaojidan2011: 用这种learning to rank的思想, 还有什么文章的啊? 麻烦推荐下
  • 【计算机视觉】SIFT中LoG和DoG比较jinjunweina: 确实讲得比较详细,而且也正确。
  • 【OpenCV】访问Mat中每个像素的值(新)lc900411: 您好,看到您前面一篇博客写的灰度图,一般存放类型;如果是RGB彩色图,存放类型。我想问一下 ...
  • 【模式识别】OpenCV中使用神经网络 CvANN_MLPSCU_911: 为什么运行后只有一个黑框,不显示图片,无错误。。。
  • 【OpenCV】基元检测 Primitive DetectionMermesworth: 学姐,nonfree里的头文件在哪下的?我怎么就找不到呢
公司简介|招贤纳士|广告服务|银行汇款帐号|联系方式|版权声明|法律顾问|问题报告|合作伙伴|论坛反馈网站客服 杂志客服 微博客服 webmaster@iyunv.com 400-600-2320京 ICP 证 070598 号北京创新乐知信息技术有限公司 版权所有江苏乐知网络技术有限公司 提供商务支持Copyright &copy; 1999-2014, CSDN.NET, All Rights Reserved  








小魏的修行路
Talk is cheap. Show me the code.

  • 目录视图
  • 摘要视图
  • 订阅
有奖征资源,博文分享有内涵        社区问答:芈峮iOS测试指南       专访阿里陶辉       2014 CSDN博文大赛       10月微软MVP申请 【OpenCV】访问Mat图像中每个像素的值
分类: 【图像处理】2012-07-22 07:10 21945人阅读 评论(26) 收藏 举报tabletutorialsmatlabiterator算法up
目录(?)[+]

  今天百度搜资料还搜到了自己的。。。《访问图像中每个像素的值》,这是之前写的了,用的也是2.0的风格IplImage*格式,不太适用后来Mat的格式,特此重写一篇。
  以下例子源自《The OpenCV Tutorials --Release 2.4.2》2.2 How to scan images, lookup tables and time measurement with OpenCV

图像容器Mat
还是先看Mat的存储形式。Mat和Matlab里的数组格式有点像,但一般是二维向量,如果是灰度图,一般存放<uchar>类型;如果是RGB彩色图,存放<Vec3b>类型。单通道灰度图数据存放格式:
多通道的图像中,每列并列存放通道数量的子列,如RGB三通道彩色图:
注意通道的顺序反转了:BGR。通常情况内存足够大的话图像的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行,这中情况在访问时可以提供很大方便。可以用 isContinuous()函数来判断图像数组是否为连续的。
访问图像中的像素

高效的方法:C操作符[ ]
最快的是直接用C风格的内存访问操作符[]来访问:[cpp] view plaincopy

  • Mat& ScanImageAndReduceC(Mat& I, const uchar* const table)  
  • {  
  •     // accept only char type matrices  
  •     CV_Assert(I.depth() != sizeof(uchar));  
  •     int channels = I.channels();  
  •     int nRows = I.rows ;  
  •     int nCols = I.cols* channels;  
  •     if (I.isContinuous())  
  •     {  
  •         nCols *= nRows;  
  •         nRows = 1;  
  •     }  
  •     int i,j;  
  •     uchar* p;  
  •     for( i = 0; i < nRows; ++i)  
  •     {  
  •         p = I.ptr<uchar>(i);  
  •         for ( j = 0; j < nCols; ++j)  
  •         {  
  •             p[j] = table[p[j]];  
  •         }  
  •     }  
  •     return I;  
  • }  
注意:书中这段代码是有问题的,前面写成了
[cpp] view plaincopy

  • int nRows = I.rows * channels;  
  • int nCols = I.cols;  
一般情况 isContinous为true,运行不会出错,但你可以注释掉那个if,会有访问越界的问题。这种访问形式就是在每行定义一个指针,然后在内存上直接连续访问。如果整个数组在内存上都是连续存放的,那么只需要定义一个指针就可以访问所有的数据!如单通道的灰度图访问方式如下:[cpp] view plaincopy

  • uchar* p = I.data;  
  • for( unsigned int i =0; i < ncol*nrows; ++i)  
  •     *p++ = table[*p];  

安全的方法:迭代器iterator
相比用指针直接访问可能出现越界问题,迭代器绝对是非常安全的方法:
[cpp] view plaincopy

  • Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)  
  • {  
  •     // accept only char type matrices  
  •     CV_Assert(I.depth() != sizeof(uchar));  
  •     const int channels = I.channels();  
  •     switch(channels)  
  •     {  
  •     case 1:  
  •         {  
  •             MatIterator_<uchar> it, end;  
  •             for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)  
  •                 *it = table[*it];  
  •             break;  
  •         }  
  •     case 3:  
  •         {  
  •             MatIterator_<Vec3b> it, end;  
  •             for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)  
  •             {  
  •                 (*it)[0] = table[(*it)[0]];  
  •                 (*it)[1] = table[(*it)[1]];  
  •                 (*it)[2] = table[(*it)[2]];  
  •             }  
  •         }  
  •     }  
  •     return I;  
  • }  
这里我们只定义了一个迭代器,用了一个for循环,这是因为在OpenCV里迭代器会访问每一列然后自动跳到下一行,不用管在内存上是否isContinous。另外要注意的是在三通道图像中我们定义的是 <Vec3b>格式的迭代器,如果定义成uchar,则只能访问到B即蓝色通道的值。
这种方式虽然安全,但是挺慢的,一会儿就知道了。
更慢的方法:动态地址计算
这种方法在需要连续扫描所有点的应用时并不推荐,因为它更实用与随机访问。这种方法最基本的用途是访问任意的某一行某一列:
[cpp] view plaincopy

  • Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table)  
  • {  
  •     // accept only char type matrices  
  •     CV_Assert(I.depth() != sizeof(uchar));  
  •     const int channels = I.channels();  
  •     switch(channels)  
  •     {  
  •     case 1:  
  •         {  
  •             for( int i = 0; i < I.rows; ++i)  
  •                 for( int j = 0; j < I.cols; ++j )  
  •                     I.at<uchar>(i,j) = table[I.at<uchar>(i,j)];  
  •             break;  
  •         }  
  •     case 3:  
  •         {  
  •             Mat_<Vec3b> _I = I;  
  •   
  •             for( int i = 0; i < I.rows; ++i)  
  •                 for( int j = 0; j < I.cols; ++j )  
  •                 {  
  •                     _I(i,j)[0] = table[_I(i,j)[0]];  
  •                     _I(i,j)[1] = table[_I(i,j)[1]];  
  •                     _I(i,j)[2] = table[_I(i,j)[2]];  
  •                 }  
  •                 I = _I;  
  •                 break;  
  •         }  
  •     }  
  •     return I;  
  • }  
因为这种方法是为随机访问设计的,所以真的是奇慢无比。。。

减小颜色空间 color space reduction
现在来介绍下上述函数对每个元素的操作,也就是用table更改像素值。这里其实是做了个减小颜色空间的操作,这在一些识别之类的应用中会大大降低运算复杂度。类如uchar类型的三通道图像,每个通道取值可以是0~255,于是就有 256*256个不同的值。我们可以通过定义:
0~9 范围的像素值为 0
10~19 范围的像素值 为 10
20~29 范围的像素值为 20
。。。。。。
着这样的操作将颜色取值降低为 26*26*26 种情况。这个操作可以用一个简单的公式:

来实现,因为C++中int类型除法操作会自动截余。 类如 Iold=14; Inew=(Iold/10)*10=(14/10)*10=1*10=10;
在处理图像像素时,每个像素需要进行一遍上述计算也需要一定的时间花销。但我们注意到其实只有 0~255 种像素,即只有256种情况。进一步可以把256种计算好的结果提前存在表中 table 中,这样每种情况不需计算直接从 table 中取结果即可。
[cpp] view plaincopy

  • int divideWith=10;   
  • uchar table[256];  
  • for (int i = 0; i < 256; ++i)  
  •     table = divideWith* (i/divideWith);  
于是table存放的是值为i的像素减小颜色空间的结果,这样也就可以理解上述方法中的操作:
[cpp] view plaincopy

  • p[j] = table[p[j]];  
LUT : Look up table
OpenCV 很聪明的有个 LUT 函数就是针对这种 Look up talbe 的操作:[cpp] view plaincopy

  • Mat lookUpTable(1, 256, CV_8U);  
  • uchar* p = lookUpTable.data;  
  • for( int i = 0; i < 256; ++i)  
  •     p = table;  
  • for (int i = 0; i < times; ++i)  
  •     LUT(I, lookUpTable, J);  

算法计时
为了验证几种方法的效率,可以用一个简单的计时和输出:
[cpp] view plaincopy

  • double t;  
  • t = (double)getTickCount();  
  • t = 1000*((double)getTickCount() - t)/getTickFrequency();  
  • t /= times;  

实验结果

原图:


降低颜色空间结果:


算法时间:


更清楚的时间对比表:


转载请注明出处:http://blog.iyunv.com/xiaowei_cqu/article/details/7771760
实验代码下载:http://download.iyunv.com/detail/xiaowei_cqu/4443761



更多7

  • 上一篇【编译原理】正则表达式
  • 下一篇【编译原理】用Yacc做语法分析
顶30踩0主题推荐opencv迭代器内存指针安全猜你在找我的OpenCV学习笔记(二):操作每个像素OpenCv的连通域操作计算机视觉目标检测的框架与过程计算机视觉+图像处理的好的链接网站!不断更新中!!!!【模式识别】多层感知器 MLP图像处理与计算机视觉:基础,经典以及最近发展(5)计算机视觉在实验室还是企业实习,这个无定数学习OpenCV:滤镜系列(3)——颜色变幻cvFindContours && cvDrawContours 的应用2-----图像内轮廓填充Android NDK开发篇(一):新版NDK环境搭建(免Cygwin,超级快)查看评论18楼 aprhz 2013-11-01 12:48发表 [回复]I.ptr<uchar>(i)是什么意思?17楼 小魔大树哥 2013-10-17 17:01发表 [回复]单通道(灰度图)的读取像素 最后像素值放在哪 table还是p中,初学者请教小魏,还有const uchar*const table[352*288];
uchar *p = I.data ;这两行代码过不去,类型不一致16楼 byctw 2013-06-05 11:49发表 [回复]请问:
Mat outfile; 要访问其第二个像素
用 outfile.data[1] 的语法是否也可以?15楼 masikkk 2013-06-03 20:23发表 [回复]知道什么是LUT了14楼 cxchenxingcool 2013-04-18 00:14发表 [回复]由IplImage*转到Mat,总感觉不适应,在二者之间只能IplImage与Mat互换13楼 郑海波 2013-03-26 11:28发表 [回复]楼主对android版的OpenCV可有研究?里面的Mat(java版)元素如何访问?Re: xiaowei_cqu 2013-03-26 13:12发表 [回复]回复NUPTboyZHB:没用过12楼 AaBb301 2012-12-03 21:05发表 [回复]2了,看到下面原来里有介绍,呵呵11楼 AaBb301 2012-12-03 20:28发表 [回复]突然明白好像是”离散量化“的,请问博主是这个主要功能吗Re: xiaowei_cqu 2012-12-03 20:57发表 [回复]回复AaBb301:嗯,用来减小颜色空间Re: AaBb301 2012-12-03 21:06发表 [回复]回复xiaowei_cqu:嗯 谢谢博主10楼 AaBb301 2012-12-03 20:21发表 [回复]想问下博主,ScanImageAndReduceC函数参数里那个table有什么用啊,我刚学opencv,很多不懂9楼 zhangnzhen 2012-11-20 13:27发表 [回复]代码里lut的计时部分错了,t=(double)getTickCount()应该在代码执行前面。要不这速度也太发指了~8楼 xiaojidan2011 2012-09-11 13:45发表 [回复]哦哦哦哦 不好意思的 我刚刚调试了下的 单幅是可以显示的 成功了 嘻嘻 可能运行的时候占据内存太大了的原因的 ,搞不懂 了7楼 xiaojidan2011 2012-09-11 13:41发表 [回复]代码运行编译都没什么问题,局势显示的时候 窗口全部是灰色的,貌似图像的值没有传进去的6楼 xiaojidan2011 2012-09-11 13:38发表 [回复]写的很好的呀 但是我跑了代码 却显示不出图像,是怎么回事的呀5楼 jizhihang2000 2012-09-07 14:00发表 [回复]“另外要注意的是在三通道图像中我们定义的是 <Vec3b>格式的迭代器,如果定义成uchar,则只能访问到B即蓝色通道的值。”
为什么不是所有像素的所有通道都访问了一遍?Re: xiaowei_cqu 2012-09-07 14:37发表 [回复]回复jizhihang2000:三通道像素是BRG排放的,相当于每个元素里放了三个uchar。迭代器定义成uchar只取出了第一个B的值,你可以试试4楼 caiqi1123 2012-09-07 10:33发表 [回复]才女:
代码
03. // accept only char type matrices
04. CV_Assert(I.depth() != sizeof(uchar));
有问题吧?改为:
// accept only char type matrices
CV_Assert(mat.depth() == CV_8U);Re: xiaowei_cqu 2012-09-07 10:42发表 [回复]回复caiqi1123:我传递的参数是I;而且CV_8U不就是uchar的类型嘛Re: caiqi1123 2012-09-07 10:58发表 [回复]回复xiaowei_cqu:回复caiqi1123:CV_8U 宏是0哦。sizeof(uchar)=8
mat.depth() 返回的是CV_8U。仅供探讨啊。3楼 afery 2012-09-06 17:25发表 [回复]有翻译版的看诶2楼 meiqingfly 2012-07-23 13:28发表 [回复]这个好呢。。Re: xiaowei_cqu 2012-07-23 14:11发表 [回复]回复meiqingfly:没写什么,是tutorials里自带的例子1楼 skiaazure 2012-07-23 07:45发表 [回复]我还是习惯用at。。。Re: xiaowei_cqu 2012-07-23 08:46发表 [回复]回复skiaazure:我也是,感觉直接用[]很危险发表评论

  • 用 户 名:
  • wslz2001


  • 评论内容:


      
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场核心技术类目
全部主题 Java VPN Android iOS ERP IE10 Eclipse CRM JavaScript Ubuntu NFCWAP jQuery 数据库 BI HTML5 Spring Apache Hadoop .NET API HTML SDK IISFedora XML LBS Unity Splashtop UML components WindowsMobile Rails QEMU KDECassandra CloudStack FTC coremail OPhone CouchBase 云计算 iOS6 RackspaceWebApp SpringSide Maemo Compuware 大数据 aptech Perl Tornado Ruby HibernateThinkPHP Spark HBase Pure Solr Angular CloudFoundry Redis Scala DjangoBootstrap
    个人资料


    xiaowei_cqu

    • 访问:644509次
    • 积分:11064分
    • 排名:第323名


    • 原创:139篇
    • 转载:0篇
    • 译文:1篇
    • 评论:1723条


    博客专栏

    图像处理文章:18篇
    阅读:44774模式识别文章:13篇
    阅读:43860算法设计与分析文章:20篇
    阅读:69232OpenCV学习与实践文章:30篇
    阅读:294025

    系列索引


  • 【我的本科】 (61)
  • 【我在读研】 (11)
  • 【项目汇总】 (18)

    文章分类


  • 【图像处理】(44)
  • 【机器视觉】(36)
  • 【算法分析】(34)
  • 【数据结构】(5)
  • 【编程语言】(41)
  • 【工程项目】(30)
  • 【模式识别】(15)
  • 【移动开发】(8)
  • 【文艺青年】(9)

    文章搜索



    博主简介

    CS小硕一枚,兴趣领域:计算机视觉、媒体分析、图像处理;认知心理学,生理心理学。
    喜欢C&#43;&#43;、Matlab、OpenCV、Qt、UML、VS、XMind等各种优秀的、提高码农生产力的工具。

    爱逛豆瓣<table cellspacing=&quot;0&quot; cellpadding=&quot;4&quot; center&quot;=&quot;&quot;>
    我的邮箱
    weilan.cqu#gmail.com


    阅读排行


  • 【OpenCV】SIFT原理与源码分析(23666)
  • 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图(22174)
  • 【OpenCV】访问Mat图像中每个像素的&#20540;(21945)
  • 【OpenCV】图像几何变换:旋转,缩放,斜切(19629)
  • 【OpenCV】边缘检测:Sobel、拉普拉斯算子(18858)
  • 【OpenCV】SIFT原理与源码分析:DoG尺度空间构造(17224)
  • 【OpenCV】访问图像中每个像素的&#20540;(16641)
  • 【OpenCV】数字图像灰度直方图(16327)
  • 【Error】安装VS2012后VS2010工程失败(15621)
  • 【OpenCV】基于Adaboost和Haar-like特征人脸识别(12845)

    评论排行


  • 【大学生活】在软件学院的那些课(106)
  • 【面向对象】小游戏“终结者”程序的设计与实现(81)
  • 【OpenCV】SIFT原理与源码分析:DoG尺度空间构造(66)
  • 【OpenCV】图像几何变换:旋转,缩放,斜切(49)
  • 【算法分析】查找算法:二分查找、顺序查找(48)
  • 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图(45)
  • 【博客分享】优秀的有趣的博客(45)
  • 【OpenCV】访问图像中每个像素的&#20540;(43)
  • 【OpenCV】数字图像灰度直方图(40)
  • 【UML】UML几种图的绘制(39)

    最新评论


  • 【计算机视觉】步态能量图GEI学生新手:我想问问怎么用MATLAB把保存在TXT文本中的GEI转换成图片
  • 【计算机视觉】会议投稿相关推荐masikkk:http://www.wikicfp.com/cfp/这个网站好,有用,多谢大牛
  • 【OpenCV】访问图像中每个像素的&#20540;XiaoShuoYiMei:LZ,又来叨扰了。。。我想把一个cvMat矩阵转化成一幅图片,结果运行出来是灰色的,不知道怎么改,还...
  • 【模式识别】SVM核函数蝴蝶也可以飞过沧海:第二个多项式核函数是不是少了个y呢?
  • 【OpenCV】视频标注工具frank133788:你好,你给的链接怎么打不开啊,我想下载你的源码。
  • 【模式识别】LearningTo Rank之RankBoostxiaojidan2011:用这种learning to rank的思想, 还有什么文章的啊? 麻烦推荐下
  • 【计算机视觉】SIFT中LoG和DoG比较jinjunweina:确实讲得比较详细,而且也正确。
  • 【OpenCV】访问Mat中每个像素的&#20540;(新)lc900411:您好,看到您前面一篇博客写的灰度图,一般存放类型;如果是RGB彩色图,存放类型。我想问一下 ...
  • 【模式识别】OpenCV中使用神经网络CvANN_MLPSCU_911:为什么运行后只有一个黑框,不显示图片,无错误。。。
  • 【OpenCV】基元检测Primitive DetectionMermesworth:学姐,nonfree里的头文件在哪下的?我怎么就找不到呢
公司简介|招贤纳士|广告服务|银行汇款帐号|联系方式|版权声明|法律顾问|问题报告|合作伙伴|论坛反馈网站客服 杂志客服 微博客服 webmaster@iyunv.com 400-600-2320京 ICP 证 070598 号北京创新乐知信息技术有限公司 版权所有江苏乐知网络技术有限公司 提供商务支持Copyright © 1999-2014, CSDN.NET, All Rights Reserved

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-126409-1-1.html 上篇帖子: docker-management遇到的一些问题 下篇帖子: zoj训练指南
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表