目录
0.1 我的DIPer开始之旅
在此,我用DIPer表示从事DIP算法开发的人员,不知道是不是第一次使用。我从1999年读硕士时开始接触图像处理技术的,现在算来,居然有25年了。当时最直接的原因是我硕导的研究方向是图像处理。在研一下学期有一门专业课,名称就是《数字图像处理》,用的是一本薄薄的教材,印刷质量一般,相对于后来经典的 Gonzalez系列DIP教材相比,内容明显单薄,但我们仍然学的很起劲。现在想来,原因主要有两个,一是有用,二是有趣。说“有用”是因为课题组的老师和师兄都是搞DIP的,干课题、写论文都要用到。说“有趣”是相对于当时落后的软硬件条件,记得当时能在屏幕上用C语言程序调用putpixel命令,逐行扫屏显示一幅256灰度级的lena图,那种成就感至今难忘。
![](https://i-blog.csdnimg.cn/blog_migrate/2e88816430d2083334b3082666bde497.jpeg)
写到这儿多说几句。在2000年前后,学术圈里做DIP和CV的人还很少,那是受到数字电视技术的发展需要,大家都热衷于搞图像和视频的编解码,做处理的也主要关注手写体数字/汉字、虹膜、人脸等特定领域,整个DIP/CV领域不像现在这么热,因此学习DIP的门槛也相对较高,相对于周边做其他信号处理和通信的同学相比,心里总有一种莫名的优越感。如果有对上面提到说法有同感的读者,咱们握握手,大家都是同行,且是同龄人。
0.2 DIP开发语言之我所见
(1)C语言
书归正传,下面我结合自己的切身经历,介绍开发DIP算法所用到的编程工具,当然主要集中在学术圈,可能和业界实际情况并不完全相符。据我查到的文献,早期(1980年前后)的DIP开发工具主要是FORTRAN和C,前者在早期科学计算领域赫赫有名,后者我就不说了,地球人都知道。FORTRAN我上大二时专门学过,学了个皮毛,后来也没有使用它真正开发过任何实用的算法。但学习FORTRAN的过程中,让我首次感受到早期高级语言的鲜明特点,语法严谨、格式要求严格,但对初学者不友好,语法繁冗。相对而言,C的优点就太突出了,甚至我是在大四上C语言这门课之前,就将谭老师的经典教材啃了一遍。当时的感觉真的是,学会C就可以走天下了。抱着这样的执念,我上研究生进到实验室分到第一台专属自己使用的计算机后,安装的第一个windows软件就是Visual Studio。那是感觉在计算机旁边在VC6.0的IDE环境下,编写DIP的C/C++代码,简直就是一种享受。
![](https://i-blog.csdnimg.cn/blog_migrate/022a0f5ce85eb02ab70b52a5e769d05e.png)
因为有一定的C语言基础,因此在完成研究生专业课《数字图像处理》的课程大作业时,我好不犹豫的选择了VC作为开发工具。记得当时DIP老师并没有限定实现什么算法作为作业,结果周围很多偷懒的同学,不约而同地选择了最简单的反色处理。学过DIP课程的同学,在此会会心地微笑,因为反色处理的代码实现其实就几行,即读取每一个像素点的灰度值,然后用
,得到其反色值,并扫屏显示。对此,我表示非常不屑,感觉太low了。我记得自己做的是用
算子完成的一种图像的边缘检测,编程实现了空域卷积、取绝对值、二值化等过程,最终以二值图像的方式显示处理。现在想来很是简单,但在当时,当将代码和实验结果用古老的针式打印机打出来并提交作业,我内心充满的成就感。
这种对C语言的偏爱,一直持续到我读PhD期间。硕士大论文的代码是用C写的一个车牌识别程序,博士参加的第一个横向课题是在Linux下的视频播放器,具体工作是MPEG-2的转码,也是用C完成的。因此在3年多的时间里,我都将C语言作为开发DIP算法的首选。但在不经意期间,另外一种强大的语言,一步步地渗透到我的DIP学习之旅,它就是大名鼎鼎的Matlab。
(2)Matlab
第一次听说Matlab这个名字,已经是研一了。那时有一门专业必修课《小波变换》,教授一边讲解小波变换的原理,一边用幻灯片(注意,这儿是老式的幻灯机投影的幻灯片,不是现在大家熟知的PPT)在幕布上投影出各种小波基的波形图,以及小波变换的中间变换过程和结果。当时我大屏幕上呈现的波形图感到很好奇,老师是用的什么绘图工具绘制出如此精致的波形图呢?很快就有机会知道答案。
一天,教授安排课后答疑,地点是她的办公室。我们一帮好学的学生都围在老师身旁,目不转睛地盯着她身前的一台电脑。那台小小的14寸Philips CRT显示屏上,正显示出我们上课所见到的那些波形图。我注意到似乎是在某个IDE软件环境下生成的这些波形,就问道:“老师,您用什么绘图软件画出的这些波形呀?”老师笑而不语,默默的关闭了窗口,会到熟悉的Win95桌面,指了指一个对我来说当时从没见过(但在后来相当长的一段时间内又再熟悉不过的)的一个图标,一边单击图标打开软件,一边跟我们解释:“不是绘图软件,是一种科学计算工具,叫Matlab。你们将来都会用到。”这就是我第一次接触Matlab的经历,当时真没想到,这款软件居然会一直伴随我从事教学和科研工作至今,虽然期间经历了几次起伏,但仍无法替代。
![](https://i-blog.csdnimg.cn/blog_migrate/ab5ebcad101bb2de36a383ee3e967fd3.jpeg)
Matlab具有强大的科学计算功能,以及强大而便捷的数据图形化显示功能,其全面、庞大而且与时俱进的工具箱(Toolbox),使得它成为诸多工程计算领域首选的开发和仿真工具,DIP领域也不例外。有关Matlab及其配套的图像处理工具箱(Image Processing Toolbox,我简称IPT)的功能介绍和使用说明,相关科技书籍和网络资源无数,不再赘述。一句话,本专栏将来所介绍的各种方法和技术,绝大多是在IPT中找到直接的实现。看到这儿,读者肯定有个疑问,既然Matlab如此彪悍,那你还为何费力的码字来介绍skimage?还有意义吗?答案是肯定的,当然有,而且意义很大。在此就不展开介绍,只简述我认为的原因。
原因有三:一、贵。Matlab是收费的商业软件,虽然我相信绝大多数科研圈里的人员所用的Matlab版本都是经过破解的,但那是个人行为,且使用目的是科研。如果是公司或者科研机构要使用,那就需要购买正版的的。那售价不是一般的贵,且有时人家还不卖,具体原因大家自行百度。二、慢且大。说它慢,主要是相对于C和JAVA开发的DIP算法,Matlab程序执行起来要慢不止一个数量级。与后面介绍的Python相比,也慢不少。说它大,是安装包大,安装后所占用的空间和文件数也十分庞大。从起初一张650M的光盘就能存下整个软件,到现在动辄10G+的安装程序。更不要谈安装完上万个文件,这还是帮助文档变成线上之后的结果。总之在早期,每次安装完Matlab软件,我的C盘容量就告急。三、扩展性差。在此我举两个例子,比如我想为设计好的DIP算法开发一个简单的GUI,或者撰写实时运行笔记。Python有Qt和Jupyter Notebook可以使用,上手方便,功能强大,Matlab有吗?还别说,它真的集成了这些功能,但用过的同仁都知道哪有多不好用。
我对Matlab的态度,经历了好几次转变。经历了从最开始的惊艳、中间的慢慢接受、到完全依赖、再到后期的质疑、嫌弃,最后基本放弃,就像一位青年找女友相类似的历程。在此因牵扯到许多个人隐私问题,不便细说。有关使用Matlab开发DIP算法的讨论,网上的讨论比比皆是,大家有兴趣可自行搜索。
就我而言,我个人建议如果是非电子信息类或者计算机类专业的初学者,编程能力和兴趣不够强,且恰好又用过Matlab,不妨在学习DIP过程中使用Matlab进行辅助学习。反之,如果想起点高一些,或者想将来往更高水平的过度更顺畅一些,那么建议您直接用Python平台吧。相信我,就DIP、CV和AI领域,虽然说Python是第一选择有些绝对,但肯定比Matlab要正确。
(3)Python
终于到了这一部分的主角。有关Python的起源、用途、特点等等,不是我一个外行人所能评价的,在此仅分享一下我从Matlab转到Python的思考。
由于我所从事的教学和科研工作的要求,一方面考虑到给当时的小白们提供一个合适的平台,使其能够迅速了解和验证各种经典的DIP算法,要求门槛不能太高,代码量不能太多,对初学者非常友善;另一方面,从科研角度考虑,希望所使用的平台功能足够强大,有良好的文档支持,更新足够快,扩展性要强,最重要的一点是,最好是与论文作者所发布的代码所用平台一致,拿来就能用。我相信对于上面标红色字体的这一句,在读研究生会深有感触。如果就现在而言,可以说的更直接一些,比如说“原作者在GitHub上发的代码是用什么语言写的,我就学什么”。
其实,对于第一个方面,以及第二个方面的大部分,Matlab都符合,但唯独研究者最看重的可重用性这一点,Python完胜Matlab,原因不过多解释。我就说两点,大家自己体会。一是大家自行查一下Python到目前为止,有多少个扩展包?二是登录GitHub,看一下上面的代码所用语言排第一的是哪一种。搞清楚了上面两件事情,就不难体会我为何推荐Python了,或者说Python是不二选择了。
于是,从大概2016年开始,我就考虑尝试将Python引入到DIP的教学和科研工作中。当时还没有像现在这么多好用的扩展包,甚至OpenCV才刚刚支持Python。但一旦迈出去这一步,就回不了头,因为Python平台多提供的自由发挥的空间实在是太大了,被Matlab约束了十多年,一下子突然重新体验到无比自由的感觉,让我愈陷愈深。相信读者中有超过10年以上DIP教学和科研经历的人,也有和我类似的经历。
看到这儿,有一定DIP学习和开发基础的人会问,为何不介绍OpenCV+Python的组合,而是选择相对冷门的skimage呢?别着急,下一节就回答。
0.3 为什么是skimage?
在DIP的开发工具中,OpenCV的名字赫赫有名,甚至很多人是就是在学习OpenCV过程中,才接触DIP和CV的。那么问题来了,既然OpenCV机会已经是行业内的标杆和首选,为何你还要在此费时费力的介绍另外一个工具包,或者换一种说法,读者自己为什么还要花时间看我写的专栏文章呢?有这个必要吗?
要想完整地回答这个问题,不太容易。如果读者就是一名公司的算法工程师,主要关心如何省时省力的完成老板或者组长交给的DIP算法开发任务,那确实OpenCV是你的首选,而且没有必要再看这个专栏了。
但如果你不满足OpenCV提供的有限的功能,或者你想了解传统DIP领域中的那些经典方法极其实现,更像做一个researcher,而不是一个码农或者Engineer,那么了解一下与OpenCV功能回补的另外一个工具包,岂不是很值得?
当然,如果你是一名在校大学生,或者是研究生在读,那么你更有必要了解并使用更多的Python扩展包,说不定会对你的学术生涯起到意想不到的作用。
(1)PIL和Pillow
好了,闲话说的太多,还是回到对skimage的介绍主题上吧。Python被称为万能胶语言,其最显著的优点之一就是有非常多的第三方扩展库。不要看到第三方的字样,就认为是水货,恰恰相反,很多扩展库在所在领域都是T0般的存在,比如NumPy,再比如SciPy。
在图像处理和计算机视觉领域,研究者开发出的扩展库也不少,比如PIL、Pillow、OpenCV, scikit-image等等。其中,PIL和Pillow出现的最早,但功能也相对有限,只提供最基础的图像处理操作。
PIL(Python Imaging Library),直译为“Python成像库”,它是Python早期御用的图像处理库,但官方只支持到Python 2.7,已经停止更新了。后来有志愿者将其改造升级,支持Python 3.x系列。
以下是对PIL的简要总结,看看就行。
- PIL包含基本的图像处理功能,包括像素操作、一套内置空域卷积核、彩色空间转换。
- PIL支持图像的基本仿射变换,包括缩放、旋转、任意角度的转换。
- PIL支持图像的直方图操作,包括直方图的计算,以及在此基础上实现的对比度增强。
Pillow(PIL fork)是在PIL基础上发展起来的。Pillow 的设计初衷只是想作为 PIL 库的分支和补充,但目前它已经成为了比 PIL 更强大的图像处理库,当然,也仅仅是比PIL强大而已。
![](https://i-blog.csdnimg.cn/blog_migrate/fc3f36c96cce59d043d34818eaba6b9b.jpeg)
Pillow所能实现的功能,与PIL几乎一样,只不过对Python 3.x更佳友好。如果你是在Anaconda平台下使用Python,那么Pillow是自带的。当然,也可以通过命令行代码“pip install pillow”,完成Pillow的安装。详细步骤可参考本专栏的第二篇。
(2)OpenCV v.s. scikit-image
OpenCV在业界赫赫有名,但它实际上是一个C++库,底层函数使用C/C++编写的。它在早期的2.x版本是不支持Python的,后来迫不得已(我主观臆断的)才开始支持Python,但也只是提供了相应的Python接口。因此,严格意义上讲,OpenCV for Python并不是一个真正为Python开发的扩展库。
与之相反,scikit-image不仅是完全用Python语言编写的扩展库,而且它的出身可以用“红二代”来形容。它的父类是大名鼎鼎的SciPy,相信使用过Python做数据处理和科学计算的人,都对这个库名耳熟能详。准确的说,scikit-image是一款建立在SciPy基础之上的专用于图像处理的扩展库,你可以将它视为SciPy的一个子模块,没有任何疑问。
另外,它在处理图像时,将图像数据作为NumPy数组进行处理,得益于NumPy强大的数据处理能力和优化功底,使得scikit-image在一定程度上改善了基于Python语言的DIP算法运行速度慢的不足。
如果将OpenCV和Skimage看作是两个竞争对手,他们相互吹自己的优势的话,可能会有如下场景!
- 第一回合:Skimage说:“我兼容性好!(从头到尾都是用Python写的)”OpenCV回怼:“我运行速度比你快!”
- 第二回合:Skimage说:“我更新的快(三个月已更新),手下小弟比你多!(函数多)”OpenCV回怼:“我运行速度比你快!”
- 第三回合:Skimage说:“我爸爸(SciPy)和二舅(NumPy)是Python界大佬!”OpenCV回怼:“我运行速度比你快!”
![](https://i-blog.csdnimg.cn/blog_migrate/4f258e92dda5ed3c179aff58303d230e.jpeg)
大家不难看出,OpenCV相对的优势就只有一个,就是运行速度快(当然,易于部署,扩平台使用,也是其主要优点),没办法,谁叫它底层是C/C++,甚至是汇编写的呢?但是在当前电脑性能严重过剩,高计算量依仗GPU的时代,这点优势似乎已经不那么值得炫耀了。
好了!到此我已经将为什么选用Skimage作为本教程的首选扩展库的原因解释的比较明白了,那么,让我们开始真正的学习之旅吧!
(本节初稿完成日期:2024-01-26)
(欢迎对DIP+python算法开发感兴趣的初学者,尤其是相关专业本科和低年级研究生关注,本专栏完将持续更新,敬请关注)