再谈OpenCV中查询表lookup table的LUT函数
2016-02-28 14:00
239 查看
今天在复习之前的OpenCV的学习内容时,发现自己对OpenCV的LUT这个函数理解得不是很透彻,研究了一上午终于是搞明白了,但自己在学习的时候发现对于这个函数的解释很少,现在把自己的理解分享出来,给大家一个参考。
首先看下我测试用的程序:
上面只是解释了查询表是如何产生的,那么查询表有什么作用呢?其作用就是:提高我们扫描图像时效率。我们要处理一张图片,其实就是对整个图像数据进行处理,那么这就要求我们在处理的时候要对图像的全部数据进行扫描读取,然后进行相应的处理,而处理中耗时最短的操作便是赋值,但是这种方法对于数据比较大的图像来说处理起来效率会很低。那么我们应该怎么办呢?前面我们讲过尽量不去进行所谓加减乘除这些操作,能不能直接在图像处理中只进行赋值操作呢?那么这时候查询表就排上用场了,前面我们已经介绍了查询表的产生方法了,那么查询表是怎么用的呢?其实用查询表来进行图像处理的实质就是:根据源图像(img)中的像素值例如灰度值是78,然后去查询表中去找它对应的是哪个灰度值(对于上面的程序78在查询表中对应的灰度值是0),然后把查询表中78对应的灰度值0赋值给新的图像矩阵(out)中。
下面通过图像介绍一下这个过程:
首先我们调试程序,先看一下程序产生的table在内存中是什么样子:
从查询表在内存中的情况来看,它已经通过150这个值把256这个灰度级分成了3个灰度级空间,这个灰度空间只包含三种灰度值即0(对应于图像中灰度值在0-100之间的)、100(对应101-200)、200(对应201-256).这说明我们的查询表已经有了,那么接下来就看查询表是怎么用来替换原始图像(img)中的数据的:
先看一下原始图像在内存中的数据:
从图中看出原始图像灰度值都比较低,原始图像应该在边缘是比较暗的,下面我们再看一下原始图像经过查询表替换成什么样的输出图像了:
从图中可以看出,确实灰度值在0-100之间的值都被替换成新的灰度空间中的灰度值0了,这里屏幕有限,其它灰度值在100以上的都在后面,可以自己看下。最终的效果图是:
从右边的输出图像中可以看出,其只有三种灰度变化。
那么可能会有人疑问了,这种替换是怎么实现的呢?请看下面的代码:
到这里应该解释得很明白了,总之,遇到问题多调试,多想。
首先看下我测试用的程序:
#include <cv.h> #include <highgui.h> using namespace std; using namespace cv; #define QUAN_VAL (100) void CreateLookupTable(Mat& table, uchar quan_val) { table.create(1, 256, CV_8UC1); uchar *p = table.data; for (int i = 0; i < 256; ++i) { p[i] = quan_val*(i / quan_val); } } int main(int argc, char *argv[]) { Mat img; Mat out; img = imread("F:/Photo/OpenCV_Photo/tsukuba_l.png", 1); Mat table;//定义查找表 //创建灰度级别是100的查找表 CreateLookupTable(table, QUAN_VAL); //使用查找表直接计算出量化灰度级后的图像并将其保存到out1中 LUT(img, table, out); namedWindow("源图像", CV_WINDOW_NORMAL); imshow("源图像", img); namedWindow("利用查询表灰度等级变换后", CV_WINDOW_NORMAL); imshow("利用查询表灰度等级变换后", out); waitKey(0); return 0; }在学习OpenCV二的博客中已经详细讲了查询表的作用以及它到底是什么东西,这里就不多说了。其实查询表的实质就是:把图像中的数据从之前的比较高的灰度级降下来,例如灰度级是256的char类型的灰度级,我们通过一个参数(例如上述程序中就是100),将原来的256个灰度级降到了3个灰度级,原来图像中灰度值在0-100的数据现在灰度值变成了0,原来灰度值为101-200的图像数据现在灰度值变为了1,而201-256的灰度值就变为了2。所以通过参数100,图像的灰度级就到了2,只有0,1,2三个灰度值,那么原来的图像矩阵中的每一位数据我们是char型的,需要8位来表示一个数据,而灰度级降下来之后,我们只需要2位就足以表示所有灰度值。
上面只是解释了查询表是如何产生的,那么查询表有什么作用呢?其作用就是:提高我们扫描图像时效率。我们要处理一张图片,其实就是对整个图像数据进行处理,那么这就要求我们在处理的时候要对图像的全部数据进行扫描读取,然后进行相应的处理,而处理中耗时最短的操作便是赋值,但是这种方法对于数据比较大的图像来说处理起来效率会很低。那么我们应该怎么办呢?前面我们讲过尽量不去进行所谓加减乘除这些操作,能不能直接在图像处理中只进行赋值操作呢?那么这时候查询表就排上用场了,前面我们已经介绍了查询表的产生方法了,那么查询表是怎么用的呢?其实用查询表来进行图像处理的实质就是:根据源图像(img)中的像素值例如灰度值是78,然后去查询表中去找它对应的是哪个灰度值(对于上面的程序78在查询表中对应的灰度值是0),然后把查询表中78对应的灰度值0赋值给新的图像矩阵(out)中。
下面通过图像介绍一下这个过程:
首先我们调试程序,先看一下程序产生的table在内存中是什么样子:
从查询表在内存中的情况来看,它已经通过150这个值把256这个灰度级分成了3个灰度级空间,这个灰度空间只包含三种灰度值即0(对应于图像中灰度值在0-100之间的)、100(对应101-200)、200(对应201-256).这说明我们的查询表已经有了,那么接下来就看查询表是怎么用来替换原始图像(img)中的数据的:
先看一下原始图像在内存中的数据:
从图中看出原始图像灰度值都比较低,原始图像应该在边缘是比较暗的,下面我们再看一下原始图像经过查询表替换成什么样的输出图像了:
从图中可以看出,确实灰度值在0-100之间的值都被替换成新的灰度空间中的灰度值0了,这里屏幕有限,其它灰度值在100以上的都在后面,可以自己看下。最终的效果图是:
从右边的输出图像中可以看出,其只有三种灰度变化。
那么可能会有人疑问了,这种替换是怎么实现的呢?请看下面的代码:
//制作查询表,做颜色空间减少操作 uchar table[256]; for (int i = 0; i < 256; ++i) table[i] = (uchar)(divideWith * (i / divideWith));
uchar* p; for (i = 0; i < nRows; ++i) { p = I.ptr<uchar>(i); for (j = 0; j < nCols; ++j) { p[j] = table[p[j]];//假设图像第一个像素的第一个灰度值23,则p[0]=table[p[0]]=table[23]=2; //这样就实现了利用查找表table的方法来替换源图像中的数据,并且灰度等级 //降下来了,例如源图像的灰度级23变成了灰度等级2了。 }这里p是图像矩阵的第i行指针,p[j]即是图像的第i行第j列的像素值,例如我们上面的原始图像第一行第一列的像素值是1,即p[0]=table[p[0]]=table[1]=0。这对图像就不是加减乘除这种计算了,而全部是直接去查询表中找对应的值然后再替换。
到这里应该解释得很明白了,总之,遇到问题多调试,多想。
相关文章推荐
- linux C宏定义实现打印调试信息
- Centos7安装配置vnc
- Linux下多目录的Makefile编写
- centos6.4的本地yum源配置
- linux中根据进程的PID值来查找执行文件的及其路径
- linux下查找包含关键字的文件
- nginx
- tomcat和java环境配置
- shell编程之文件包含
- 常用的tomcat和webLogic的区别
- [Linux]O_CLOEXEC 标志
- Hadoop安装教程_单机/伪分布式配置_Hadoop2.6.0/Ubuntu14.04
- 使用Eclipse编译运行MapReduce程序 Hadoop2.6.0_Ubuntu/CentOS
- 大型网站架构系列:负载均衡详解(4)
- 大型网站架构系列:负载均衡详解(3)
- Hadoop安装教4程_单机/伪分布式配置_Hadoop2.6.0/Ubuntu14.0
- linux内存管理之初始化zonelists
- 大型网站架构系列:负载均衡详解(2)
- 大型网站架构系列:负载均衡详解(1)
- linux之ifconfig命令