首页 技术 正文
技术 2022年11月21日
0 收藏 818 点赞 3,896 浏览 2027 个字

小白,入门中,不足其指正。刚刚接触opencv,从一个Matlab风格的编程环境突然跳转到C++,实在有些不适。单就pixels scanning花了好长时间研究。opencv-tutorials给出了四种方法。这里将比较其中最高效的方法与Mat类里定义的at()的效率。

本文以opencv-tutorials中给出的color reduction 为例进行比较。

  • 图像的读取

为了简化问题,直接对灰度图进行操作,灰度图的获取可以用Mat类里的imread函数(每每看到这个函数都很激动,又有了Matlab的感觉)。

//read the image data
Mat GrayImage;
GrayImage = imread("test.jpg",);
//show the image that read
namedWindow("OriginalGrayImage");
imshow("OriginalGrayImage",GrayImage);

其中imread的参数0表示的就是读取灰度图。相比于Matlab里面还要用rgb22gray转化,这里就方便一点了哈!

原图:

Mat中两种像素遍历方法比较

灰度读取效果:

Mat中两种像素遍历方法比较

  • lookup table的产生

我们的目的是把读取的图像像素值进行量化,如果将0~255的像素量化成4级,就需将0~63的像素计算成0,64~127的像素计算成为64……

因为在C++编译过程中,uchar/int的结果还是uchar,所以直接利用下面公式就可以得到

Mat中两种像素遍历方法比较

注意的是这里我用的是opencv.org上盗的图,图中的10可以用dividewidth替换,dividewidth的值需要根据量化的结果来确定,比如如果dividewidth=64;那么0~63的像素都会计算成0,64~127的像素都会计算成为64……以此类推,这样就会被量化成4级。

但是值得注意的是,对于一张100*100的灰度图就需要计算10000次,所以lookup table产生了。lookup table的思路是产生一个0~255的向量,没个存放用上述公式计算的结果,然后遍历的时候只需要查表就可以了,这样对于一个100*100的灰度图,本来需要计算10000次的,现在只需要计算256次。

产生lookup table的代码段

uchar table[];
int div = ;
for(int i=;i<;i++)
table[i] = (uchar)(div*(i/div));
  • 灰度量化-classic C style operator[]

Mat.ptr<type>(i)可以获得第i行的指针,其中type表示的是Mat中存放的数据类型,一般的灰度图为uchar,rgb图则是Vec3b。Mat.rows和Mat.cols中分别存放的是图像的行数和列数。

具体代码段如下

//get some informations from GrayImage
int nr = GrayImage.rows;
int nc = GrayImage.cols;

uchar* p;
for(int i=0;i<nr;i++)
{
  p = GrayImage.ptr<uchar>(i);
  for(int j=0;j<nc;j++)
  {
    p[j] = table[p[j]];
  }
}

运行结果:

Mat中两种像素遍历方法比较

  • 灰度量化-Mat.at<type>(i,j)

Mat类里定义的at函数可以直接访问图像中的像素。其中type参见上一条的解释。(i,j)为图像中的坐标。 具体代码段如下:

for(int i=;i<nr;i++)
for(int j=;j<nc;j++)
GrayImage.at<uchar>(i,j) = table[GrayImage.at<uchar>(i,j)];

运行结果:

Mat中两种像素遍历方法比较

  • 如何获得运行时间

opencv中提供了两个函数,getTickCount()和getTickFrequency();

Well OpenCV offers two simple functions to achieve this getTickCount() and getTickFrequency().

opencv.org盗来的代码段:

double t = (double)getTickCount();
// do something ...
t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Times passed in seconds: " << t << endl;
  • 结果比较

运行环境:OS: Windows 10-64bitIDE: codeblocks 13.12 with g++CPU: i3内存: 4GB 运行结果:

classic C style operator[]

0.00136458
Mat.at<type>(i,j) 0.00498963

从结果可以看出,指针操作明显更高效,这也就是为什么opencv-tutorials中把它称为the effective way的原因。但是,指针操作有危险性,所以很多人还是原因用Mat.at的方法。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,944
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,469
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,283
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,099
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,729
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,766