2013-09-03 19:55:28 taoyanbian1022 阅读数 2120
最近版上有不少人在讨论图像处理的就业方向,似乎大部分都持悲观的态度。我想结合我
今年找工作的经验谈谈我的看法。

就我看来,个人觉得图像处理的就业还是不错的。首先可以把图像看成二维、三维或者更
高维的信号,从这个意义上来说,图像处理是整个信号处理里面就业形势最好的,因为你
不仅要掌握(一维)信号处理的基本知识,也要掌握图像处理(二维或者高维信号处理)
的知识。其次,图像处理是计算机视觉和视频处理的基础,掌握好了图像处理的基本知识
,就业时就可以向这些方向发展。目前的模式识别,大部分也都是图像模式识别。在实际
应用场合,采集的信息很多都是图像信息,比如指纹、条码、人脸、虹膜、车辆等等。说
到应用场合,千万不能忘了医学图像这一块,如果有医学图像处理的背景,去一些医疗器
械公司或者医疗软件公司也是不错的选择。图像处理对编程的要求比较高,如果编程很厉
害,当然就业也多了一个选择方向,并不一定要局限在图像方向。

下面谈谈我所知道的一些公司信息,不全,仅仅是我所了解到的或者我所感兴趣的,实际
远远不止这么多。

搜索方向
基于内容的图像或视频搜索是很多搜索公司研究的热点。要想进入这个领域,必须有很强
的编程能力,很好的图像处理和模式识别的背景。要求高待遇自然就不错,目前这方面的
代表公司有微软、google、yahoo和百度,个个鼎鼎大名。

医学图像方向
目前在医疗器械方向主要是几个大企业在竞争,来头都不小,其中包括Simens、GE、飞利
浦和柯达,主要生产CT和MRI等医疗器材。由于医疗器械的主要功能是成像,必然涉及到对
图像的处理,做图像处理的很有机会进入这些公司。它们在国内都设有研发中心,simens
的在上海和深圳,GE和柯达都在上海,飞利浦的在沈阳。由于医疗市场是一个没有完全开
发的市场,而一套医疗设备的价格是非常昂贵的,所以在这些地方的待遇都还可以,前景
也看好。国内也有一些这样的企业比如深圳安科和迈瑞

计算机视觉和模式识别方向
我没去调研过有哪些公司在做,但肯定不少,比如指纹识别、人脸识别、虹膜识别。还有
一个很大的方向是车牌识别,这个我倒是知道有一个公司高德威智能交通似乎做的很不错
的样子。目前视频监控是一个热点问题,做跟踪和识别的可以在这个方向找到一席之地。

上海法视特位于上海张江高科技园区,在视觉和识别方面做的不错。北京的我也知道两个
公司:大恒和凌云,都是以图像作为研发的主体。

视频方向
一般的高校或者研究所侧重在标准的制定和修改以及技术创新方面,而公司则侧重在编码
解码的硬件实现方面。一般这些公司要求是熟悉或者精通MPEG、H.264或者AVS,选择了这
个方向,只要做的还不错,基本就不愁饭碗。由于这不是我所感兴趣的方向,所以这方面
的公司的信息我没有收集,但平常在各个bbs或者各种招聘网站经常看到。
我所知道的两个公司:诺基亚和pixelworks

其他
其实一般来说,只要涉及到成像或者图像的基本都要图像处理方面的人。比方说一个成像
设备,在输出图像之前需要对原始图像进行增强或者去噪处理,存储时需要对图像进行压
缩,成像之后需要对图像内容进行自动分析,这些内容都是图像处理的范畴。下面列举一
些与图像有关或者招聘时明确说明需要图像处理方面人才的公司:
上海豪威集成电路有限公司(www.ovt.com.cn)
中芯微
摩托罗拉上海研究院
威盛(VIA)
松下
索尼
清华同方
三星
所有与图像(静止或者运动图像)有关的公司都是一种选择。比如数码相机、显微镜成像
、超声成像、工业机器人控制、显示器、电视、遥感等等,都可以作为求职方向。

要求:
1、外语。如果进外企,外语的重要性不言而喻。一般外企的第一轮面试都是英语口语面试

2、编程。这方面尤以C++为重,很多公司的笔试都是考c++知识。
3、专业水平。如果要找专业相关的工作,研究生期间的研究经历和发表的论文就显的比较
重要。
4、知识面的宽度。我觉得在研究生期间,除了做好自己的研究方向之外,扩宽一下知识面
也有很大的帮助,当然这个知识面指的是图像处理、计算机视觉和模式识别,知识面越宽
,就业时的选择就会越多。

图像处理方向毕业的就业面非常广,而且待遇在应届生应该是中上等。其实还是一句话,
能力决定一切。只要研究生三年没有白过,根本不愁找不到好工作。祝所有正在读研或者
即将读研的朋友将来都能有一份满意的工作。
2016-01-18 13:24:16 baimafujinji 阅读数 5967

图像处理(以及机器视觉)在学校里是一个很大的研究方向,很多研究生、博士生都在导师的带领下从事着这方面的研究。另外,就工作而言,也确实有很多这方面的岗位和机会虚位以待。而且这种情势也越来越凸显。那么图像处理到底都研究哪些问题,今天我们就来谈一谈。图像处理的话题其实非常非常广,外延很深远,新的话题还在不断涌现。下面给出的12个大的方向,系我认为可以看成是基础性领域的部分,而且它们之间还互有交叉

 

1、图像的灰度调节

图像的灰度直方图、线性变换、非线性变换(包括对数变换、幂次变换、指数变换等)、灰度拉伸、灰度均衡、直方图规定化等等)。

例如,直方图规定化(代码请见http://blog.csdn.net/baimafujinji/article/details/41146381)

CLAHE(contrast limited adaptive histogram equalization)自适应的直方图均衡(效果图来自

http://www.cnblogs.com/Imageshop/archive/2013/04/07/3006334.html)

2、图像的几何变换

图像的平移、图像的镜像、转置、缩放和旋转。这里面其实还包含了插值算法(这是某些几何变换所必须的),例如最邻近插值法、双线性插值法等等)

几何变换同时和图像的滤镜特效是紧密联系的,某些特效的实现本质上就是某种类型的几何变换。例如

 

3、图像的特效与滤镜

这方面的应用很多,你可以想想Photoshop里面的滤镜。

文献Combining Sketch and Tone for Pencil Drawing Production中给出的将自然图像变成手绘素描图的效果

例如浮雕效果

贴图太烦了,更多效果请见http://blog.csdn.net/baimafujinji/article/details/50500757

4、图像增强

内容包括图像的平滑(简单平均、中值滤波、高斯平滑等)和锐化(例如Laplace方法)等。

增强处理中的很多算法其实和图像复原中的降噪算法是重合的。现在保持边缘(或纹理结构)的平滑算法属于研究热点。像那些美颜相机里的嫩肤算法都是以此为基础的。比较常见的双边滤波(我给出的代码请见http://blog.csdn.net/baimafujinji/article/details/41598455)

基于全变分方法的TV去噪(http://blog.csdn.net/baimafujinji/article/details/42110831)、基于PM方程的非线性扩散去噪(http://blog.csdn.net/baimafujinji/article/details/42110831)等等。

 

5、图像复原

广义上来说——图像降噪,图像去雾,图像去模糊 都属于这个范畴

去噪实例是我用MagicHouse(http://blog.csdn.net/baimafujinji/article/details/50500757)实现的中值滤波处理椒盐噪声的效果。此外,一些基于非局部均值的降噪算法是当前研究的热点(例如BM3D、NLM等)

图像去模糊(图片取自我的《数字图像处理原理与实践(Matlab版)》)

去雾代码请见(http://blog.csdn.net/baimafujinji/article/details/30060161)或参考我的《数字图像处理原理与实践(Matlab版)》

6、图像的压缩与编码

想想BMP图像如何转换成JPG,JPG如何变成PNG?这些都属于图像压缩编码所要探讨的内容。

7、边缘检测与轮廓跟踪

边缘检测在图像处理中是一个“古老”的话题了,我就不具体给例子了。下面是一个轮廓跟踪的例子

 

8、图像分割

你可以认为轮廓跟踪也是实现图像分割的一种途径。

这是我在《数字图像处理原理与实践(Matlab版)》中给出的一个例子——用分水岭算法对马铃薯图像进行分割。

9、图像的形态学处理

这也属于一种非常古老的图像处理方式了。包括膨胀、腐蚀、细化、击中/击不中、开/闭运算等。但一些对颗粒状物体进行计数的应用中它仍然非常有效。

 

10、图像的频域变换(或称正交变换)

傅立叶、离散余弦、沃尔什-哈达玛变换、K-L(卡洛南-洛伊)变换(也称霍特林变换或PCA)、小波变换(小波变换还分很多种,例如Haar小波、Daubechies小波等等)

仅仅进行频域变换其实并没有多大意义,它往往要与具体应用相结合来发挥作用。例如进行图像压缩、嵌入数字水印、进行图像融合、进行图像降噪等等。

例如,利用PCA进行图像压缩的例子请见

http://blog.csdn.net/baimafujinji/article/details/50373143(源代码请见我的博文)

 

在比如,利用小波融合对由聚焦失败导致的图像模糊进行修复 (本来左图和中图各有部分看不清,融合后变得可以辨识)源代码可见

http://blog.csdn.net/baimafujinji/article/details/49642111

11、图像融合

广义上说融合至少包含三部分内容:像上面的基于小波的Fusion我们也认识是融合的一种,另外一种是以隐藏为目的类似嵌入式的融合,第三种是matting。matting有时反义成抠图,其实它最原本的意思就是融合。如果你理解

I = aF +(1-a)B这个融合公式的话,你应该明白我在所什么。这本质上和第二种融合原理是一样的。

狭义上,融合就是指matting。

例如 著名的Possion融合,下图右,如果直接把月亮图贴上天空,矩形边缘是很明显的,融合处理后的左图则很自然。

代码可见 http://blog.csdn.net/baimafujinji/article/details/46787837

电影技术中常用matting方法来替换人物的场景。例如

 

12、图像信息安全

主要包括两个内容:1)数字水印(主要用于多媒体的版权保护);2)图像的加密(主要用于图像信息的保护)

例子是我用MagicHouse(http://blog.csdn.net/baimafujinji/article/details/50500757)实现的加密效果

 

 

注意上面我们所讨论的领域仅仅是图像处理的范畴,并不涉及机器视觉。所以也没有任何机器学习的内容,有时间我们再继续讨论这方面的东西。

 

 

 

2017-12-22 11:11:47 zqhwando 阅读数 8536

因为自己是一枚图像处理领域的研究生菜鸟,即将从事的方向是图像处理下的图像融合方向,故,把我自己学习中遇到的不太明白的知识列下来,留作纪念,加深印象与理解。
从广义上说,图像是自然界景物的客观反映。以照片形式或视频记录介质保存的图像是连续的,计算机无法接收和
处理这种空间分布和亮度取值均连续分布的图像。图像数字化就是将连续图像离散化,其工作包括两个方面:
取样和量化。
那么,究竟什么是采样,什么又是量化呢?
所谓采样,就是把一幅连续图像在空间上分割成M×N个网格,每个网格用一亮度值来表示。一个网格称为一个像素。M×N的取值满足采样定理。
采样示意图
而量化就是把采样点上对应的亮度连续变化区间转换为单个特定数码的过程。量化后,图像就被表示成一个整数矩阵。每个像素具有两个属性:位置和灰度。位置由行、列表示。灰度表示该像素位置上亮暗程度的整数。此数字矩阵M×N就作为计算机处理的对象了。灰度级一般为0-255(8bit量化)。
量化示意图(a)为量化过程(b)为量化为8bit
在现实生活中,采集到的图像都需要经过离散化变成数字图像后才能被计算机识别和处理。
二维图像的成像过程
采样又可分为均匀采样和非均匀采样。
图像均匀采样量化——像素灰度值在黑白范围较均匀分布的图像。
图像非均匀采样量化——对图像中像素灰度值频繁出现的灰度值范围,量化间隔取小一些,而对那些像素灰度值极少出现的范围,则量化间隔取大一些。
不同分辨率下图像的显示情况
通过自己查资料整理,终于对图像的采样与量化过程有了最基本的了解,不像刚开始写之前,懵懵懂懂的,就感觉听了好多遍这两个词,但就是不知道他两是干啥用的。谨以此文,纪念之。

2018-07-21 11:42:45 baidu_36984161 阅读数 169

       研究生方向准备选择图像方向,现阶段对图像这一块儿还没有一个准确的认知,只知道大致方向是学好图像处理基础之后往计算机视觉上发展。由于本科是软件工程,并没有接触过这方面的课程,一开始对于数字图像处理这门课真的是无从下手,打算利用暑假这段时间把基础课程给学好,在网上看了各种经验帖,总结和计划了一波自己的学习计划,首先把《数字图像处理》刚萨雷西第三版的数字图像基础部分看完,然后配合《数字图像处理matlab》第二版进行实战操作,仿真书上最基本的算法,一步一步慢慢来,把基础给打扎实。然后再去学习和了解一下OpenCV,并且再回顾和学习c++,正好学校要求要考ccf,就多刷刷题,始终认为刷算法题是学好c++的不二选择,后续的学习笔记和经验总结我会及时总结到博客上,给刚刚入门图像的小白们提供思路,一路与君共勉。

2013-09-05 18:39:26 dangodango 阅读数 3608

作为一个遥感图像处理方向研究生,笔者在编程的时候免不得要和矩阵运算打交道,各种矩阵乘法协方差特征值。虽然在自己的研究实验中更喜欢用MATLAB来作为工具,但是在完成工程项目编软件的时候必须要用C++来作为编程语言。在C++中并不能像MATLAB一样,非常方便的进行矩阵运算。当然也可以自己编一些列矩阵运算的函数(笔者以前就干过这事),不过这个运算效率实在无法满足要求。

目前国际上提供了很多矩阵运算线性代数的库,这些库都进行了基于CPU和多核的运算优化,自然比我们自己做的这些函数效率要高的多,而且很多库都有着非常友好的使用方式,这就好比有了又快又舒服汽车自然也就不用再用自己的双腿走到累死。经过了多次折腾,笔者终于大概了解了几个比较常用的矩阵库的安装和使用方式,在这里做一个简要介绍,希望能为其他人提供一个方便。

笔者最早是使用的别人给的MATCOM库,这个库比较古老、不开源而且早就停止维护,唯一的优点就是可以在vc6.0上使用···最近又开始在找更加优质的矩阵运算库,就发现了Armadillo,并且在同学的推荐下用了一下Eigen,发现在vs2010的环境下,这两个库确实比MATCOM要好上N倍。以下就是各个运算库的介绍和安装,本文重点介绍的是Armadillo+OpenBLAS的组合,这个组合是我目前使用的库中最简单效率又最高的。

1MATCOM

MATCOM矩阵库在国内用的貌似还不少,笔者就是从别的同学那里得到的这个库。根据度娘的介绍,MATCOM其实是mathtools公司提供讲MATLAB代码移植到c++上的一个工具,具体两者的关系笔者搞不太清,但是MATCOM4.5版本之后据说就被合并到MATLAB中,没有再更新和维护。

MATCOM有两大优点,一是和MATLAB的使用方式非常像,基本函数都叫一个名字,所以可以非常容易地将MATLAB代码移植到C++上;二是可以在VC6上使用,这一点非常重要···因为目前大多数的库都已经不再支持VC6了。不过MATCOM的缺点也非常多,首先MATCOM并不开源,这一点在完成工程项目编软件的时候很麻烦;其次MATCOMMathTools公司被合并之后就再也没有更新和维护,因此在代码的速度和健康程度上已经是落后于时代了。所以笔者认为除非是必须在VC6下进行编程,不然不建议再使用MATCOM这个矩阵库。

关于MATCOM的具体应用,可以参见http://blog.sina.com.cn/s/blog_60f8483a0100gay7.html这个博客,讲解的非常清楚。在度娘中搜索,也可以找到很多关于MATCOM的文章。不过笔者要提醒一点,在笔者的使用中发现有一些文章和说明中提到的函数和真正使用起来并不一样,这可能是版本差异,所以需要自己动手尝试。

笔者所获得的MATCOM一共只有4个文件,是编译好了的v4501v.lib,v4501v.dllago4501.dllmatlib.h文件。这几个文件读者可以在CSDN等网站上搜索下载。

安装方式很简单,只需要在工程中添加上v4501v.lib,在代码头包含#include "matlib.h",并且把v4501v.dllago4501.dll放到应用文件,例如DEBUG或者RELEASE文件夹中,就可以使用。

2Armadillo

Armadillo是一个开源的矩阵运算库,这个库可以在开源中国下载到

http://www.oschina.net/p/armadillo+cpp+library

Armadillo的主页也非常友好

http://arma.sourceforge.net/

这个库其实是对底层的矩阵运算库(例如BLASLAPACK)的封装,也就是说,这个库本身的计算能力其实不强,但是这个库可以配合开源的底层库来使用,例如最基本的BLAS+LAPACK或者改进后的OpenBLAS,ACML还有强大的MKLArmadillo的速度主要就是由底层库决定,其代码使用可以说是非常非常的简单,基本和MATLAB的代码没有什么差别,总之笔者是用的非常爽。

Armadillo的更新很频繁,这正是它还很有生命力的证据。

Armadillo可以从开源中国的连接或者是其主页的连接上下载,其安装说起来就是几步

1-将下载后的文件解压到某一个文件夹,例如D:\ProgramFiles\Armadillo\armadillo-3.910.0

2-D:\ProgramFiles\Armadillo\armadillo-3.910.0\include目录包含到在VS工程的文件目录中;

3-如果想要使用BLASLAPACK等底层库的加速,需要在将D:\ProgramFiles\Armadillo\armadillo-3.910.0\include\armadillo_bits\config.hpp中的取消一下两行代码的注释

#define ARMA_USE_LAPACK

#define ARMA_USE_BLAS

笔者推荐取消注释,这样才能发挥Armadillo的能力。

4-安装就基本完成了,以上安装可以参考以下两个网址

http://www.cnblogs.com/youthlion/archive/2012/05/15/2501465.html

http://blog.csdn.net/houston11235/article/details/8266646

在度娘上可以搜索到很多Armadillo的安装文章,不过有一些是基于linux的,所以大家可以找针对windows的文章。

安装完毕后需要实践一下才能检验是否知道怎么使用,在压缩文件目录中,有一个examples文件夹,下面有两个例子,安装结束后请运行一下两个例子。

5-因为在Armadillo中使用到了BLASLAPACK,在examples\lib_win32中提供了两个已经编译好了的LIBDLL,在使用到Armadillo的工程中加入两个LIB文件,并把DLL文件拷到执行文件的目录下。在这个文件夹中提供的两个库lapack_win32_MTblas_win32_MT是提前编译好了的,非常好用,笔者测试后发现比网上自己下载的LAPACKBLAS要快很多,而且还不需要其他的DLL支持。如果读者不想麻烦,就可以直接用这两个库。

6-请把压缩文件中的Readme.txt好好阅读一遍,这个帮助文件其实就讲的很详细了。还有docs.html,是一份非常详细的使用说明。

下载最新的LAPACK

可能有读者想使用自己下载的LAPACK库,笔者推荐在以下网址下载

http://icl.cs.utk.edu/lapack-for-windows/lapack/index.html#build

读者可以直接在这个网址搜索Using LAPACKE subroutines in a VisualStudio C/C++ Project,在这个小节下面有一个编译好的LAPACKE examples,里面有编译好的LIBDLL,可以拿来直接使用。

不过需要注意的是,网上目前大多数库,包括LAPACKOpenBLAS,都是使用MinGW进行编译的,所以为了能顺利使用这些库,请读者先去安装一个MinGW吧。请在安装的时候选择CC++FORTRAN,这些编译环境都是经常需要的。

读者自己下载LAPACK之后,就可以使用LIBDLL替换原来Armadillo提供的LIBDLL,不过因为网上下载的LAPACK是使用MinGW编译的,需要相应的编译环境才能使用,单独使用会提示缺少必要的DLL。有两个办法解决这个问题,一是安装MinGW,并且在系统Path中进行配置,具体请度娘;二是将MinGW安装目录bin文件夹中的相应DLL拷到执行文件目录下,缺什么考什么。笔者推荐第二种方式,因为编好的软件一般都会在其他电脑上运行,不能要求所有的电脑都有MinGW环境。一般需要的DLLlibgcc_s_dw2-1.dlllibgfortran-3.dlllibquadmath-0.dll三个。

使用OpenBLAS

ArmadilloReadme.txt中,一共推荐了三个库,并说“The OpenBLAS,MKL and ACML libraries are generally the fastest.”其中笔者推荐要用的,就是OpenBLASOpenBLAS是一个开源的库,这一点正好能够满足Armadillo联合使用工程项目编程的需要。下面就是OpenBLAS的主页

http://xianyi.github.io/

OpenBLAS有很多优点,计算效率高,开源免费,不过最最重要的一点,这是中国人写的!OpenBLAS是由中科院软件研究所的张先轶开发的一个开源计算库。为什么说这是一个很重要的优点,倒不是说笔者呼吁支持国货,而是如果有问题可以直接用中文问开发者!而且还是一个很热心的开发者!还有什么比这更大的优点。

下面就是作者Xianyi Zhang在开源中国开的博客

http://my.oschina.net/u/274748?ft=blog

笔者在有问题的时候晚上9:29留言,开发者9:35就回答了,第二天更是写了一个WindowsArmadillo如何使用OpenBLAS”的博客,笔者当时是感动得泪流满面啊。

这就是开发者提供的如何使用Armadillo+OpenBLAS,里面步骤写的很详细,读者可以按照这个博客来做

http://my.oschina.net/u/274748/blog/158728

唯一要补充一点就是这个库运行也需要MinGW环境,上面关于LAPACK的文字中有提到如何解决。只不过对于OpenBLAS只需要libgfortran-3.dlllibquadmath-0.dll

在使用OpenBLAS的时候,只需要将LIB文件添加到工程中,再把DLL拷到执行文件目录下就行了。在笔者安装的时候拷到一些英文的安装方法说还需要BLAS或者LAPACK,其实OpenBLAS都已经包含了,除了MinGW环境不需要额外的库。

OpenBLAS已经编译好的文件可以在主页上直接下载到,也可以下载源代码自己编译,关于如何编译作者已经在他的博客中说道了。

Armadillo+OpenBLAS是笔者最推荐的组合。

其他库MKL ACML ATLAS

除了上面提到的BLAS+LAPACKOpenBLAS,其他著名的库有Intel MKLAMD ACML以及开源的ATLAS。其中MKL是收费的,ACMLATLAS是免费的。MKL听说是效率最高的库,但是在Windows下要收费,Linux免费,这是赤裸裸地鄙视Windows程序员的节奏吗。MATLAB就是使用的MKLATLAS。当然,有心人总能在网上找到免费的MKL,不过因为只能自己用,所以笔者也就没认真研究。曾经下载到一个MKL的库试过,发现不如OpenBLAS这样容易加到Armadillo,老是出错,也就没再深入过。ACML是免费的,不过貌似需要编译,笔者找到合心的库之后就不想麻烦了,就没弄,如果有兴趣的读者可以自己去网上下载。ATLAS因为是需要编译,笔者也懒了没弄。

3.Eigen

Eigen也是一个开源的矩阵运算库,笔者在同学的推荐下尝试了一下这个库。据笔者同学说,在WindowsEigenOpenBLAS效率更高,而且在下面的这个测评中,EigenArmadillo要快很多,但是笔者猜这里的Armadillo没有使用OpenBLAS.

http://blog.csdn.net/houston11235/article/details/8501135

Eigen不是以动态库的形式,而是以头文件的方式使用,因此不需要再包含其他的DLL,应该算比较方便的。Eigen的安装方式很简单,就是将下载的压缩包直接解压,例如D:\Program Files\Eigen,然后在VS工程中直接包含路径D:\Program Files\Eigen\Eigen,也就是根目录下的Eigen文件夹就行了。

笔者猜测Eigen可能可以在VC6下使用,如果感兴趣的读者可以自己去尝试一下。

Eigen最大的缺点就是和MATLAB的使用方法差得太多,笔者用起来特别费劲。不过Eigen属于大多数算法都用模板函数,可能有人会觉得用起来更方便。

 

以上就是笔者最近尝试用过的矩阵运算库,接下来笔者会进行一个简单的测评。

在这篇博文中,笔者主要进行了针对MATCOMArmadillo+LAPACK_MTArmadillo提供的LAPACKBLAS),Armadillo+LAPACK(网上下载的,需要MinGW环境),Armadillo+OpenBLASEigen以及MATLAB的测评。测评内容大概是一个PCA变换,所有的程序都进行相同的计算内容进行计时。程序都是编译成MTRelease版本进行计算,使用的计时工具是Timer http://www.songho.ca/misc/timer/timer.html)。



MATCOM的代码

///////////////////////////////////////////////////////////////////////////
#include
 
using namespace std;
//包含MATCOM头文件
#include "matlib.h"
 
#include "Timer.h"
//包含GDAL头文件,GDAL是一个用来读取影像的库,搞不懂的就记住这个东西是用来读取一个大矩阵的
#include "gdal_priv.h"
 
int main()
{
winaxes((HWND) NULL);
initM(MATCOM_VERSION);
Timer time;
cout<<"Hello World!"<<endl;
cout<<"Hello VS2010!"<<endl;
cout<<"Hello Armadillo!"<<endl;
GDALDataset * pGDALDataIn;
GDALAllRegister();
//这里读取了一个影像,大小是1061*1078*4
const char * cPath="D:\\2002qb_wuda_ms.img";
pGDALDataIn=(GDALDataset *)GDALOpen(cPath,GA_ReadOnly);
if (pGDALDataIn==NULL)
{
cout<<"输入文件打开失败!"<<endl;
system("pause");
return 1;
}
int nHeight, nWidth, nBand;
nHeight=pGDALDataIn->GetRasterYSize();
nWidth=pGDALDataIn->GetRasterXSize();
nBand=pGDALDataIn->GetRasterCount();
double * pData;
pData=new double [nHeight*nWidth*nBand];
pGDALDataIn->RasterIO(GF_Read,0,0,nWidth,nHeight,pData,nWidth,nHeight,GDT_Float64,nBand,NULL,0,0,0);
int nImageSize=nHeight*nWidth;
//上面都不用管,总之就是把数据读取到了一个double型的数组里
Mm mImage =zeros(nImageSize,nBand);
double *pmImageData=mxGetPr(&mImage);
//这是用拷内存的方式给MATCOM矩阵赋值,这么做应该是最快的赋值方式了,但是要注意
//矩阵和数组都是double型的才可以
memcpy(pmImageData,pData,nImageSize*nBand*sizeof(double));
mImage=transpose(mImage);
//开始计时
time.start();
Mm mMeanImg, mMean;
mMean=mean(mImage,2);
mMeanImg=mImage-repmat(mMean,1,nImageSize);
Mm mCovImg;
mCovImg=mMeanImg*transpose(mMeanImg);
mCovImg=mCovImg/(nImageSize-1);
Mm mTransW;
Mm mEigVal;
i_o_t iot={0,0};
eig(mCovImg, iot, mTransW, mEigVal);
Mm mInv=inv(mCovImg);
//计时结束
time.stop();
cout<<"The time is"<<time.getElapsedTimeInMilliSec()<<endl;
delete pGDALDataIn;
delete [] pData;
system("pause");
}
///////////////////////////////////////////////////////////////////////////


 

Armadillo代码

因为Armadillo代码都是一样的,不同的只不过是加入的底层库不同。

///////////////////////////////////////////////////////////////////////////
#include
#include "armadillo"
 
//命名空间
using namespace arma;
using namespace std;
 
#include "Timer.h"
 
#include "gdal_priv.h"
 
int main()
{
Timer time;
cout<<"Hello World!"<<endl;
cout<<"Hello VS2010!"<<endl;
cout<<"Hello Armadillo!"<<endl;
GDALDataset * pGDALDataIn;
GDALAllRegister();
const char * cPath="D:\\2002qb_wuda_ms.img";
pGDALDataIn=(GDALDataset *)GDALOpen(cPath,GA_ReadOnly);
if (pGDALDataIn==NULL)
{
cout<<"输入文件打开失败!"<<endl;
system("pause");
return 1;
}
int nHeight, nWidth, nBand;
nHeight=pGDALDataIn->GetRasterYSize();
nWidth=pGDALDataIn->GetRasterXSize();
nBand=pGDALDataIn->GetRasterCount();
double * pData;
pData=new double [nHeight*nWidth*nBand];
pGDALDataIn->RasterIO(GF_Read,0,0,nWidth,nHeight,pData,nWidth,nHeight,GDT_Float64,nBand,NULL,0,0,0);
mat Imgmat=zeros(nHeight*nWidth,nBand);
//同样是使用拷内存的方式赋值,好不容易才找到的
double *pmImageData=Imgmat.memptr();
memcpy(pmImageData,pData,nHeight*nWidth*nBand*sizeof(double));
Imgmat=trans(Imgmat);
cout<<Imgmat.n_rows<<""<<Imgmat.n_cols<<endl;
//开始计时
time.start();
mat mMean, mMeanImg;
mMean=mean(Imgmat,1);
mMeanImg=Imgmat-repmat(mMean,1,nHeight*nWidth);
mat mCov1=mMeanImg*trans(mMeanImg);
mCov1=mCov1/(nHeight*nWidth-1);
vec eigval;
mat eigvec;
eig_sym(eigval,eigvec,mCov1);
mat mInvCov=inv(mCov1);
//计时结束
time.stop();
cout<<eigvec<<endl;
cout<<"The time is"<<time.getElapsedTimeInMilliSec()<<endl;
delete pGDALDataIn;
delete [] pData;
system("pause");
}
///////////////////////////////////////////////////////////////////////////


 

Eigen代码



///////////////////////////////////////////////////////////////////////////
#include
//包含Eigen头文件
#include
#include
 
using namespace std;
using namespace Eigen;
 
#include "Timer.h"
 
#include "gdal_priv.h"
 
int main()
{
Timer time;
cout<<"Hello World!"<<endl;
cout<<"Hello VS2010!"<<endl;
cout<<"Hello Armadillo!"<<endl;
GDALDataset * pGDALDataIn;
GDALAllRegister();
const char * cPath="D:\\2002qb_wuda_ms.img";
pGDALDataIn=(GDALDataset *)GDALOpen(cPath,GA_ReadOnly);
if (pGDALDataIn==NULL)
{
cout<<"输入文件打开失败!"<<endl;
system("pause");
return 1;
}
int nHeight, nWidth, nBand;
nHeight=pGDALDataIn->GetRasterYSize();
nWidth=pGDALDataIn->GetRasterXSize();
nBand=pGDALDataIn->GetRasterCount();
double * pData;
pData=new double [nHeight*nWidth*nBand];
pGDALDataIn->RasterIO(GF_Read,0,0,nWidth,nHeight,pData,nWidth,nHeight,GDT_Float64,nBand,NULL,0,0,0);
const int nImageSize=nHeight*nWidth;
//用数组的复制方式
Map mImage(pData,nImageSize,nBand);
cout<<mImage(0,1)<<""<<mImage(1,0)<<endl;
//定义double型矩阵
MatrixXd mTImage;
mTImage=mImage.transpose();
//开始计时
time.start();
MatrixXd mMeanImg, mMean;
mMean=mTImage.rowwise().mean();
mMeanImg=mTImage-mMean.replicate(1,nImageSize);
MatrixXd mCovImg;
mCovImg=mMeanImg*mMeanImg.transpose();
mCovImg=mCovImg/(nImageSize-1);
EigenSolver es;
MatrixXcd mTranW, mEigVal;
es.compute(mCovImg,false);
//这一步赋值运行老是出错,我也不知道错在哪里,不过不影响
//mTranW=es.eigenvectors();
mEigVal=es.eigenvalues().asDiagonal();
MatrixXd mInv=mCovImg.inverse();
//停止计时
time.stop();
cout<<mTranW<<endl;
cout<<"The time is"<<time.getElapsedTimeInMilliSec()<<endl;
delete pGDALDataIn;
delete [] pData;
system("pause");
}
///////////////////////////////////////////////////////////////////////////


 

从上面的三段代码就可以看出来,EigenMATLAB的使用差得非常远,而ArmadilloMATCOM都和MATLAB非常像。笔者用Eigen用得是很痛苦,可能是用习惯MATLAB的关系。



经过测评,以上这段代码,从计时开始到计时结束,各个库的表现是

MATLAB 61.7101ms

Armadillo+OpenBLAS 73.5832ms

Armadillo+LAPACK_MT 86.5733ms

Eigen 99.3488ms

Armadillo+LAPACK 167.915ms

MATCOM 269.978ms

笔者只大概做了一个测试,从测试结果上看,MATLAB最快,而Armadillo+OpenBLAS次之,Armadillo提供的LAPACK_MT比网上下载的LAPACK要快很多,不知道什么原因,MATCOM最慢。

在网上还有一个测评

http://nghiaho.com/?p=1726

这个测评中Armadillo使用了OpenBLAS。其结果也是Armadillo+OpenBLAS最好。

笔者只是大概做了个测评,如果有兴趣,可以自己在做一个更加全面的测评。本次测评使用的环境是Windows7+VS2010

图像处理概念理解

阅读数 1205

图像处理的应用

阅读数 1967

没有更多推荐了,返回首页