读取图像,LUT以及计算耗时
使用LUT(lookup table)检索表的方法,提高color reduce时对像素读取的速度。
实现对Mat对象中数据的读取,并计算color reduce的速度。
方法一:使用Mat的ptr()遍历行(row),效率较高,使用时需要小心细节
- #include <opencv2/core/core.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <iostream>
- #include <sstream>
- using namespace std;
- using namespace cv;
- static void help(){
- cout
- << "Author: BJTShang" << endl
- << "2016-12-22, CityU" << endl
- << "Use: " << "./1222_LUP imageName divideWith [G]" << endl
- <<endl;
- }
- Mat& ScanImageAndReduceC(Mat& I, const uchar* table);
- Mat& ScanImageAndReduceIterator(Mat& I, const uchar* table);
- int main(int argc, char** argv){
- help();
- if(argc<){
- cout << "Not enough parameters!" << endl;
- return -;
- }
- Mat I;
- char* imageName = argv[];
- if(argc== && !strcmp(argv[],"G")){
- I = imread(imageName, CV_LOAD_IMAGE_GRAYSCALE);
- }else{
- I = imread(imageName, CV_LOAD_IMAGE_COLOR);
- }
- if(!I.data){
- cout << "The image" << imageName << " has no data!";
- return -;
- }
- int divideWith = ;
- stringstream s;
- s << argv[];
- s >> divideWith;
- if(!s || !divideWith){
- cout << "Invalid divideWith, input again (positive integer)!" << endl;
- return -;
- }
- // use this table to search for (by simple assignment) reduced intensity,
- // instead of calculating for each pixel, which is computational high-cost
- uchar table[];
- for(int i=; i < ; ++i){
- table[i] = uchar((i/divideWith)*divideWith);
- }
- int64 t0 = getTickCount();
- Mat J = I.clone();
- J = ScanImageAndReduceC(J, table);
- double t = (double)(getTickCount() - t0)/getTickFrequency();
- cout << "Elapse time = " << t* << " ms" <<endl;
- namedWindow("before", CV_WINDOW_AUTOSIZE);
- namedWindow("after color reduce by LUT", CV_WINDOW_AUTOSIZE);
- imshow("before", I);
- imshow("after color reduce by LUT", J);
- waitKey();
- return ;
- }
- Mat& ScanImageAndReduceC(Mat& I, const uchar* table){
- CV_Assert(I.depth() == CV_8U);
- const int channels = I.channels();
- int nRows = I.rows;
- int nCols = I.cols*channels;
- if (I.isContinuous()){
- nCols *= nRows;
- nRows = ;
- }
- uchar* p = NULL;
- for(size_t i=; i<nRows; ++i){
- p = I.ptr<uchar>(i);
- for(size_t j=; j<nCols; ++j){
- p[j] = table[p[j]];
- }
- }
- // Mat结构的ptr()方法,返回指向Mat每一行的头元素指针
- // Mat结构的data属性,返回指向元素的指针,p++指针自加到下一块元素地址。
- // 如果Mat中元素连续,才可以使用*p++取出所有元素值;若Mat中元素不连续,*p++取出第二行开始肯定错误!
- // uchar* p = I.data;
- // for(size_t i = 0; i < nRows*nCols; ++i){
- // *p++ = table[*p];
- // }
- return I;
- }
结果:
如果使用*p++的方法,结果不同:
这种方法,需要自己考虑图像每一行之间的gap,以及元素类型(uchar和float32f的不同)。效率较高,但不小心会出问题。
方法二:通过MatIterator类安全地访问Mat结构
效果相同,但是运行时间会变长几倍(我的电脑上大约是3倍)
- Mat& ScanImageAndReduceIterator(Mat& I, const uchar* table){
- CV_Assert(I.depth() == CV_8U);
- int channels = I.channels();
- switch(channels){
- case :
- {
- MatIterator_<uchar> it,end;
- for(it = I.begin<uchar>(), end = I.end<uchar>(); it!=end; ++it)
- *it = table[*it];
- break;
- }
- case :
- {
- MatIterator_<Vec3b> it, end;
- for(it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it!=end; ++it){
- (*it)[] = table[(*it)[]];
- (*it)[] = table[(*it)[]];
- (*it)[] = table[(*it)[]];
- }
- break;
- }
- }
- return I;
- }
对于3通道彩色图像,需要指定迭代器中元素类型为short vector: <Vec3b>。如果指定为uchar,迭代器器将只会扫描B蓝色通道;当然,这里的情况因为使用了[]操作符访问short vector中的sub colomun, 编译就通不过。。。
方法三:最容易理解,但是最不推荐的是使用Mat的at()方法
- Mat& ScanImageAndReduceRandomAccsee(Mat& I, const uchar* table){
- CV_Assert(I.depth() == CV_8U);
- const int channels = I.channels();
- switch(channels){
- case :
- {
- for(int i=; i<I.rows; ++i)
- for(int j=; j<I.cols; ++j)
- I.at<uchar>(i,j) = table[I.at<uchar>(i,j)];
- break;
- }
- case :
- {
- Mat_<Vec3b> _I = I; // this was used to check the data (3 channels), as well as to use [] operator to access different channels
- for(int i=; i<I.rows; ++i)
- for(int j=; j<I.cols; ++j){
- _I(i,j)[] = table[_I(i,j)[]]; // equal to _I.at(i,j*3) = table[_I.at(i,j*3)]
- _I(i,j)[] = table[_I(i,j)[]]; // equal to _I.at(i,J*3+1) = table[_I.at(i,j*3+1)]
- _I(i,j)[] = table[_I(i,j)[]]; // equal to _I.at(i,j*3+2) = table[_I.at(i,j*3+2)]
- }
- I = _I;
- break;
- }
- }
- return I;
- }
效率和安全的使用MatIterator类差不多,想访问矩阵中特定位置的元素使用这种方法是比较合适的。
最后,OpenCV封装了LUT的color reduce方法。平常直接使用即可,效率比较高。
- Mat lookUpTable(, , CV_8U);
- uchar* p = lookUpTable.data;
- for(int i=; i<; i++)
- p[i] = table[i];
- LUT(I,lookUpTable,J);
读取图像,LUT以及计算耗时的更多相关文章
- Exif.js 读取图像的元数据
Exif.js 提供了 JavaScript 读取图像的原始数据的功能扩展,例如:拍照方向.相机设备型号.拍摄时间.ISO 感光度.GPS 地理位置等数据. 注意事项: EXIF 数据主要来自拍摄的照 ...
- GDAL库——读取图像并提取基本信息
GDAL库是一个跨平台的栅格地理数据格式库,包括读取.写入.转换.处理各种栅格数据格式(有些特定的格式对一些操作如写入等不支持).它使用了一个单一的抽象数据模型就支持了大多数的栅格数据.这里有GDAL ...
- 图像相似度计算之哈希值方法OpenCV实现
http://blog.csdn.net/fengbingchun/article/details/42153261 图像相似度计算之哈希值方法OpenCV实现 2014-12-25 21:27 29 ...
- PS图像菜单下计算命令
PS图像菜单下计算命令通过通道的混合模式得到的选区非常精细,从而调色的时候过度非常好.功能十分强大. 下面用计算命令中的"相加"和"减去"模式做实例解析,这 ...
- OpenCV2:第三章 读取图像
一.简介 将图像文件读入内存,可以用cv::imread()函数 二.读取图像 Mat imread(const string& filename,int flags=1); Mat: 如果读 ...
- python3读取图像并可视化的方法(PIL/Pillow、opencv/cv2)
原图: 使用TensorFlow做图像处理的时候,会对图像进行一些可视化的操作.下面,就来列举一些我知道的图像读取并可视化的方法. 1. Pillow模块 1.1 Pillow模块的前生 Pillow ...
- 基于gtk的imshow:用stb_image读取图像并用gtk显示
在前面一篇,已经能够基于gtk读取图像并显示.更前面的一篇:基于GDI的imshow:使用stb_image读取图像并修正绘制,通过stb_image读取图像并通过GDI显示图像,实现了一个imsho ...
- OpenCV读取图像问题:OpenCV(3.4.3) D:\Build\OpenCV\opencv-size.width0 && size.height0 in function 'cvimshow'
版权声明:本文为博主原创文章,转载 请注明出处:https://blog.csdn.net/sc2079/article/details/83280067 - 问题与解决 最近正在学OpenCV,发现 ...
- opencv学习之读取图像-imread函数
序 想要完整全面地学习opencv,仅凭阅读samples的示例源码是不够的.毕竟opencv是一个拥有非常多函数的程序库,所以在每学习一个函数时,芒果觉得有必要记录下来,分享给有需要的同学.于是,就 ...
随机推荐
- EL表达式
跳转传到: : 相当于(接值放值): --------------------------- --------------------------------- ------------------- ...
- kettle中含有参数传递的定时任务
(1)新建一个作业(新建->作业),并在控制面板右键: (2)设置一个命令参数: (3)把作业的参数传递给转换: (4)在转换中右键设置转换属性: (5)接收作业中设置的传递参数: (6)参数的 ...
- NodeJS使用formidable实现文件上传
最近自学了一下NodeJS,然后做了一个小demo,实现歌曲的添加.修改.播放和删除的功能,其中自然要实现音乐和图片的上传功能.于是上网查找资料,找到了一个formidable插件,该插件可以很好的实 ...
- MVC 数据验证
MVC 数据验证 前一篇说了MVC数据验证的例子,这次来详细说说各种各样的验证注解.System.ComponentModel.DataAnnotations 一.基础特性 一.Required 必填 ...
- html5标签知多少
此文为前段时间团队研究会出品,与小伙伴兮兮圆一起研究的成果,意外地上了公司km的今日推荐,今日挪过来,为新开张的博客先暖暖场吧. 一.常用标签 <header>.<footer> ...
- 踢出非法Linux用户
非法添加用户及非法进去的远程操作用户! 01.非法用户闯入系统 最简单的办法就是用 w 命令来检查. 如果确认有非法用户出现在系统内,可以立即 kill 用户相关进程. kill -9 `lsof ...
- webBrowser1
HTMLDocument类的引用 using mshtml;
- 前端性能优化---yahoo军规
一.尽可能减少HTTP请求数 二.使用CDN(内容分发网络) 三.添加Expire/Cache-Control头 四.启用Gzip压缩 五.将CSS放在页面最上面 六.将Script放在页面最下面 七 ...
- java中IO流小解
下面这张图列出了java中一些处理流: java中根据操作对象的不同可以分为:字节流和字符流. 首先我们先表示一下什么叫节点流和处理流: 节点流:可以从或向一个特定的地方(节点)读写数据.如FileR ...
- BZOJ 3931: [CQOI2015]网络吞吐量
3931: [CQOI2015]网络吞吐量 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1555 Solved: 637[Submit][Stat ...