- 浏览: 263734 次
- 性别:
- 来自: 济南
文章分类
最新评论
今天百度搜资料还搜到了自己的。。。《访问图像中每个像素的值 》,这是之前写的了,用的也是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风格的内存访问操作符[]来访问:
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; }
注意:书中这段代码是有问题的
,前面写成了
int nRows = I.rows * channels; int nCols = I.cols;
一般情况 isContinous为true,运行不会出错,但你可以注释掉那个if,会有访问越界的问题。
这种访问形式就是在每行定义一个指针,然后在内存上直接连续访问。如果整个数组在内存上都是连续存放的,那么只需要定义一个指针就可以访问所有的数据!如单通道的灰度图访问方式如下:
uchar* p = I.data; for( unsigned int i =0; i < ncol*nrows; ++i) *p++ = table[*p];
安全的方法:迭代器iterator
相比用指针直接访问可能出现越界问题,迭代器绝对是非常安全的方法: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即蓝色通道的值。
这种方式虽然安全,但是挺慢的,一会儿就知道了。
更慢的方法:动态地址计算
这种方法在需要连续扫描所有点的应用时并不推荐,因为它更实用与随机访问。这种方法最基本的用途是访问任意的某一行某一列:
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 种情况。这个操作可以用一个简单的公式:
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 中取结果即可。
在处理图像像素时,每个像素需要进行一遍上述计算也需要一定的时间花销。但我们注意到其实只有 0~255 种像素,即只有256种情况。进一步可以把256种计算好的结果提前存在表中 table 中,这样每种情况不需计算直接从 table 中取结果即可。
int divideWith=10; uchar table[256]; for (int i = 0; i < 256; ++i) table[i] = divideWith* (i/divideWith);于是table[i]存放的是值为i的像素减小颜色空间的结果,这样也就可以理解上述方法中的操作:
p[j] = table[p[j]];
LUT : Look up table
OpenCV 很聪明的有个 LUT 函数就是针对这种 Look up talbe 的操作:Mat lookUpTable(1, 256, CV_8U); uchar* p = lookUpTable.data; for( int i = 0; i < 256; ++i) p[i] = table[i]; for (int i = 0; i < times; ++i) LUT(I, lookUpTable, J);
算法计时
为了验证几种方法的效率,可以用一个简单的计时和输出:
double t; t = (double)getTickCount(); t = 1000*((double)getTickCount() - t)/getTickFrequency(); t /= times;
实验结果
原图:
降低颜色空间结果:
算法时间:
更清楚的时间对比表:
转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/7771760
实验代码下载:http://download.csdn.net/detail/xiaowei_cqu/4443761
发表评论
-
unity基础开发----物体位移和旋转实用代码
2013-11-21 22:46 1222using UnityEngine; using Syst ... -
Android中View绘制优化之一---- 优化布局层次
2012-09-04 23:00 967... -
Android中View绘制优化二一---- 使用<include />标签复用布局文件
2012-09-08 13:54 971... -
Android中View绘制优化之三---- 优化View
2012-09-13 21:00 1044... -
兰林任务管理应用程序雏形版以及概要说明
2012-09-15 21:54 827... -
Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流程浅析(上)
2012-10-10 18:14 1065... -
Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流程浅析(下)
2012-10-17 20:05 809... -
Android中文件选择器的实现
2012-11-30 08:59 1078... -
【编译原理】使用Lex将C/C++文件输出为HTML文件
2012-07-20 09:37 97008年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大 ... -
【编译原理】正则表达式
2012-07-21 21:49 213208年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大 ... -
【编译原理】用Yacc做语法分析
2012-07-23 05:47 169508年9月入学,12年7月毕 ... -
【UML】UML几种图的绘制
2012-07-24 09:49 93808年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大 ... -
【OpenCV】邻域滤波:方框、高斯、中值、双边滤波
2012-07-26 10:52 1407邻域滤波(卷积) 邻域算子值利用给定像素 ... -
【数据结构】排序算法:希尔、归并、快速、堆排序
2012-07-28 06:15 93808年9月入学,12年7月毕 ... -
【OpenCV】角点检测:Harris角点及Shi-Tomasi角点检测
2012-07-31 13:25 1490角点 特征检测与匹配 ... -
【UML】案例分析:机场运作系统
2012-08-01 17:22 292308年9月入学,12年7月毕 ... -
【OpenCV】边缘检测:Sobel、拉普拉斯算子
2012-08-04 13:41 1467边缘 边缘(edge)是指图像局部强度变化最显著的部分。主要 ... -
【OpenCV】Canny 边缘检测
2012-08-08 10:17 1936Canny 边缘检测算法 1986 ... -
【UML】案例分析:新型超市购物自助系统
2012-08-19 01:13 125608年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大 ... -
【数据结构】二叉树、AVL树
2012-08-21 00:30 103708年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大 ...
相关推荐
使用opencv获得图像中每一点的像素值 可以对图像中的每一点像素值进行单独的操作
三种方法访问图像中像素的值。 参考博文:http://blog.csdn.net/xiaowei_cqu/article/details/7771760
1: 输出一个Mat对象的像素 自定义一个Mat 对象,然后输出像素值(像素值基本都在 0 – 255 之间 ,图像为三通道) ... * 小图像的每一个像素值我们都是知道的,可以输出查看,验证算法正确性,然后在ran大图 *
封装在Opencv的Mat图像中绘制中文文字功能!解决Opencv中默认绘制中文字体出现乱码的情况!
自己改写的中文汉字写入到图片Mat的程序
在MFC中显示OpenCV的Mat图像矩阵;使用GDI+可以方便的把OpenCV的图像矩阵类型数据显示在MFC的窗口中。
将内存中YUV数据(char* pBuf,int nLen)转成opencv的Mat格式,RGB显示
OPENCV_Mat类存取方法
opencv中Mat转换成内存数据的jpeg格式,以及显示在mfc的界面中
opencv获取图像像素值,学习opencv如何读图片并显示出来,获取像素值
该CPP应用Opencv的Mat对图像数据进行读取,里面包括单通道、三通道的图像数据的读取和写入等四种方式
这个是关于OpenCV中Mat类的一些数学运算,包括加减运算,点乘,点除,矩阵乘法,还有幂函数指数函数等计算以及一些区域的选取。
//开始处理每个像素 (*it)[0] = (*it)[0] / div*div + div / 2; (*it)[1] = (*it)[1] / div*div + div / 2; (*it)[2] = (*it)[2] / div*div + div / 2; ++it; } } //动态地址计算像素 void atColorReduce(Mat&...
Opencv访问图像像素源码 实例图像 C++代码
opencv2.4.3中访问图像的像素,有at函数法,指针法,迭代器法,帮助初学者入门,供大家参考。
OpenCVSharp 中遍历、修改Mat像素对比 1、指针 2、GetIndexer 4、GetGenericIndexer 5、GetUnsafeGenericIndexer 6、Mat.At 7、Mat.Get和Mat.Set 8、LUT "OpenCVSharp学习笔记3--OpenCV如何扫描图像、利用查找表和...
代码讲解请看本人博客关于opencv访问像素的五种方法。
opencv 读取图像像素值到数组,用指针方式实现 opencv 读取图像像素值到数组,用指针方式实现
使用VS2013+opencv获取鼠标左键点击位置图像的像素值。
以上这篇python opencv判断图像是否为空的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持软件开发网。 您可能感兴趣的文章:ubuntu下编译安装opencv的方法Opencv+Python实现图像...