Excel狂魔?单元格做计算机视觉:人脸检测、OCR都不在话下
机器之心报道
参与:一鸣、张倩、杜伟
计算机视觉是什么?过于专业,一步劝退?在普通人看来,计算机视觉是软件开发者才能涉足的领域,需要用到很多专业的框架,普通人只能围观。但 GitHub 上的一个项目似乎颠覆了我们的认知。
Excel 基本操作会吧?上网搜索公式会吧?基本的数学理解能力有吧?OK,如果以上你都能做到,你也能上手计算机视觉项目了。
图 1:将一张图像转换为 Excel 单元格表示的灰度图像。可以看到,只要单元格细粒度足够高,就可以存储足够的图像信息。
具体来说,在这个项目中,作者尝试用 Excel 实现的样本算法来帮助我们学习计算机视觉的基础知识。为此,他用到了很多只有一行的 Excel 公式。作者表示,在这个项目中,用 Excel 做人脸检测、霍夫变换都不在话下,而且不依赖任何脚本或第三方插件。
以下是使用 Excel 进行的一些计算机视觉任务。首先,我们有一个示例图像。这是一个护照。如图所示,Excel 的算法可以实现对照片人像的检测(使用传统手工算法)。
同样,这幅图像也可以被 Excel 转换,然后找到边和线的特征。
最后,Excel 还可以进行 OCR 操作。首先对图像进行手工分割,找到相关的图像文本,然后进行 OCR 即可。
这个项目不要求你提前掌握计算机视觉背景知识,但需要了解 Microsoft Excel 基础操作,会阅读 Excel 文档或上网搜索需要用到的公式的相关解释。对于后者,推荐使用 Exceljet。
此外,你还需要具备一些数学理解能力:如果理解不了加权平均数,可能很难继续学下去。掌握偏微分很有帮助,但不是硬性要求。项目中用到的复杂数学概念大多数是特征值。
使用 Excel 做计算机视觉,乍一听显得有点魔幻。但其实原理很简单:这个教程利用了 Excel 强大的单元格计算能力,只要将图像的像素数据转换为单元格(如下图所示),然后计算即可。我们知道每个单元格都可以表示一个值,那么很多个单元格是不是就可以表示成矩阵了?
对示例文件的截图(样本图片局部),可以看到 Excel 单元格表示了图像的灰度。
而另一方面,我们可以很方便地利用 Excel 计算单元格的数据。那么整合起来,是不是和矩阵计算很相似了?这样,不同图像位置表示的特征也就很容易被计算出来。自然也就方便完成下游计算机视觉的任务了,不管是传统算法也好,还是机器学习也好。
可是,图像怎样输入到 Excel 中呢?作者提供了一个方法:用 CSV 呀。
你可以用很多种方式转换 RGB 图像到像素点数据,如使用一个程序等:
https://alvinalexander.com/blog/post/java/getting-rgb-values-for-each-pixel-in-image-using-java-bufferedi
当图像的像素转换为 CSV 后,使用 Excel 读取即可。
项目需要的关键材料都可以在「Downloads」部分找到。这些材料都带有注释,通俗易懂,可以按部就班,一步一步学。
这个项目是在 Excel 2016 上创建的,在其他版本上应该也能打开(目前已经在 Excel 2007 和 Mac 的 Excel 上进行了测试)。
此外,虽然这些文件能在 LibreOffice 上打开(测试版本是 6.4.0.3 (x64)),但速度极慢,可以说没办法用。目前还没有在 Apache OpenOffice 上进行测试。
在打开项目中的 Excel 文件之前,请先把 Excel 的「公式」→「计算选项」调为「手动」,因为有些计算(尤其是霍夫变换)非常耗时。然后根据需要手动触发重算。
此外,不要勾选「保存工作簿前重新计算」,否则 Excel 将在每次保存文件时重新计算所有公式。
注意:这个项目做完后,记得把设置改回来。
熟悉 Excel 中 R1C1 公式引用样式的人或者喜欢冒险的人,应该尝试通过查看 Excel 选项来切换到 R1C1 引用样式。
参考下面的屏幕截图,勾选 R1C1 引用样式对应的复选框来启用这个选项。如此一来,我们可以把公式从「D5」类型的格式更改为「R[-1]C[2]」这样的相对样式,使其更接近编程语言并有助于理解。
下图所示为本项目的相关教程目录和项目文件,总共 50MB,大家可以前往 GitHub 下载。
这一项目分为五个部分:
1. 计算机视觉 Excel 基础
2. 边和线
3. 关键点和描述算子
4. 人脸检测
5. 文本识别(OCR)
这些项目都有相关说明和代码,非常详细。
作者在留下教程之余,也对相关的一些问题提供了解答。
问题 1:这些技术是否可被深度学习替代?
这些技术依然是相关的。尽管神经网络已经替代了所有复杂的计算机视觉问题,特别是那些传统技术没有解决的问题。但是在简单的计算上,传统方法更快,而且计算效率更高。另外,传统方法依然是边缘设备(智能手机、网络客户端)等的首选,虽然已有很多硬件加速的方法。
问题 2:为什么使用图像的绿通道,而不是红或蓝?如果想在 Excel 中用这种方式展示彩色图像要怎么做?
作者表示,三种基本的颜色通道中,绿通道对亮度的影响最大。理论上,图像会首先被转换为灰度图,即计算其亮度,在教程中为了简便被省略了。关于彩色图像的表示,可以看一下第 6 个问题。
问题 3:护照中带有水印的人脸为什么没被检测到?
作者使用的是一个流行的人脸检测算法,仅使用三个类 Haar 特征和两个步骤。这一算法是针对蒙娜丽莎(示例)中的图像手工设计的。而在实际应用中,机器学习可以学习数千个这样的特征,因此才能准确检测到人脸。
问题 4:在 OCR 示例中如何选择 mask 以及方向?
对于文档 OCR(与场景文本识别相反)来说,在识别文档中的字符之前,文档通常先被拉直。所以,字符一般为直立的。
在示例中,作者使用单神经元来识别大写字母「E」。神经网络利用多层神经元来识别所有感兴趣的字符。然后神经网络输出输入端出现的字符。需要注意的是,组合神经元将在识别每个字符的过程享一些神经元。
问题 5:OCR 方法在不同字体上的效果如何?
作为示例,作者使用单卷积神经元来识别大写字母「E」。实际系统通常会使用到神经网络(并不仅是单神经元),并且在不同字体和语言上都表现良好。
具体是如何实现的呢?作者使用单神经元来同时扫描图像和识别字母。通常情况下,扫描不同篇幅的文本需要通过不同的方法单独完成。一旦文本的每个字符被隔离,则字符重新缩放至一个固定大小,然后使用神经网络来识别字母。
手写识别更加困难。当笔画数据为时间函数(如在触摸屏上识别是写输入)时,能够实现最佳效果。此外,在示例中,即使单个神经元的权重是手工的,实际上也不使用训练算法来学习。在实际训练时,单个神经元的效果也比 demo 展示中的要好。
问题 6:作者是如何想到用 Excel 做计算机视觉的呢?
起初,作者要给亚马逊内部员工讲授计算机视觉教程,但他们对该主题不熟悉。所以,作者通过展示图像本质上是数字的 2D 阵列来讲述计算机视觉的基础知识,并想要使用 Excel 来展示。作者大约花费 7 个小时来创建了第一个功能完善的版本,但不涵盖人脸检测和文本识别。之后的版本又做了进一步完善。
自那时起,作者已经创建了以下在 Excel 中展示图像的视频作品或教程(附链接):
- Excel 电子表格中的图像(包括颜色):https://www.youtube.com/watch?v=UBX2QQHlQ_I
- Excel 光线跟踪:https://www.youtube.com/watch?v=m28jJ7CMp8A&feature=emb_logo
- Excel 3D 引擎:https://www.youtube.com/watch?v=bFOL9kantXA
- Excel 3D 图形:https://www.gamasutra.com/view/feature/131968/microsoft_excel_revolutionary_3d_.php
问题 7:是否有计算机视觉的交互式开发者环境?
由于 Matlab 具有内置或在工具箱中具有很多计算机视觉功能,所以它通常用于计算机视觉任务。其中,「imshow」功能可直接将阵列数据以图像的形式显示出来。此外,基于 Python 和 Notebooks 的工具也很流行。
项目作者
项目作者有两位,分别为 Alok Govil 和合作者 Venkataramanan Subramanian,他们都是亚马逊的首席工程师。
其中,Alok Govil 是一位全栈技术架构师,本科和硕士分别毕业于德里技术大学(Delhi Technological University)和美国南加利福尼亚大学。他毕业后曾先后就职于飞利浦美国研究院、高通等公司,现为亚马逊首席工程师。
Alok Govil。
合作者 Venkataramanan Subramanian 本科毕业于印度马德拉斯大学,之后攻读班加罗尔国际信息技术学院的在职硕士。他毕业后先后就职于 Hexaware Technologies 和甲骨文公司,并于 2011 年入职亚马逊担任首席工程师至今。
参考链接:
https://news.ycombinator.com/item?id=22357374https://github.com/amzn/computer-vision-basics-in-microsoft-excel
最简单常用的Matlab绘图教学:只要学会这几句代码
Matlab是科研人员常用的绘图工具,但是对很多人来说,Matlab的编程是最头疼的,很多人还没尝试就退缩了,但实际上一些基本的图形通过一些简单的代码就可以实现,并没有想象中的那么难。
下面我就简单介绍一些简单的Matlab编程命令,帮助科研小白入门。
主页
Matlab基本界面包含这几块内容:
菜单栏:含有一些控制程序进行的按钮
当前文件夹:工作路径所在的文件夹
命令行窗口:写程序的地方
数据区:数据的族谱
主页
绘图
应用程序
值得讲的是绘图页面,里面给了许多预设的模板,鼠标放到某模板上停留一下会出现该模板的标准程序代码格式,可以看出我们需要的数组是二维还是三维的。其他页面无所谓,满足日常需求的话用不到。
Matlab不像Excel能够直接对数据进行编辑 ,刚打开时Matlab的界面是空的,我们需要将我们要用的数据导入进来供我们使用。常用的导入方式有三种:直接声明在脚本里(适合数据量少的情况)、在数据区新建新数据(适合数据量居中的情况)、在脚本里调用(适合数据量大的情况)。
首先新建脚本,在脚本中写程序(以一个简单的二维图为例),定义我们需要的X、Y数据,数据定义语句主要有四种方法:
X=1; //单个数据声明
X=1:1:3; //范围数据声明,分别为起始值、增量、终止值
X=[1 2 3]; //数组声明,行向量
X=[1;2;3]; //数组声明,列向量
Y数据定义同理,定义好后,利用plot(X,Y)语句做出简单的二维图(点击菜单栏“运行并前进”按钮)。
数据定义方式一
下面换一种方式定义数据,我们在数据区新建数据,改名为X(非固定),双击,此时出现我们熟悉的Excel表格,我们可以在里面输入我们的数据,或者从excel粘贴过来。Y同理,这时我们只需要在脚本中写plot(X,Y)语句即可。
数据定义方式二
针对数据量大的情况,我们手动录入数据会很麻烦,这时候直接用代码提取即可,需要满足一些前提:一个EXCEL文档、将Matlab当前的工作路径设置为该EXCEL所在位置。
数据定义方式三
在脚本区域定义X Y取用EXCEL文档数据的区域,定义格式为(粗体为固定格式,其余皆可更改):
X=xlsread(\’大量数据.xls\’,\’T2:V223\’); //第一个单引号内容为文件名
Y=xlsread(\’大量数据.xls\’,\’D2:F223\’); //第二个单引号内容为数据区域的左上角坐标和右下角坐标,两个坐标即可定义一个区域
再次使用plot(X,Y)语句即可作图。
前面的教程解释了一个图一条线的基本写法,我们经常碰到的是一个图多条线或多个子图并存的情况。
一图多线关键代码:hold on
多图并存关键代码:subplot(1,2,1)、figure()
当我们需要在一个图里做多条线的时候,肯定会用到一个X数据和若干个Y数据,这时一个plot(X,Y)语句就不够了,需要再增加plot(X,Z),或者更多,但是直接增加语句会导致后面的语义覆盖前面的语义,最后的结果就是只会出现最后一次声明曲线,为了实现多条plot(X,Z)并存,我们需要在每两个plot()之间加入hold on语句。
多线并存方式一
当我们需要更多并存的线条时,再用这种方法就会显得麻烦,于是我们可以用另一种方式plot(x,a,x,b,x,c)。
多线并存方式二
当一幅图是由多幅子图组合而成的,我们一幅一幅合并肯定是不方便的,这时候需要用到subplot(行,列,序号)语句,行和列用来定义子图的排列方式和排列数量,序号代表子图出现的顺序,在每一个subplot()语句后面都要跟一个plot()语句。
多图并存方式一
当我们希望多图不以上述方式出现,而是以单独的图出现时,就要将subplot()语句换成figure()语句了,figure(1)代表声明第一幅图,后面可存在figure(2)……
多图并存方式二
我们学会作图方式后,需要了解一些美化图形的方式,因为Matlab默认的线型是固定的,图片留白太多,并不美观,修改线型与添加网格有两种方式可以采取:
手动:需要美化的图片较少时
自动:需要批量出图时
当按照默认方式出图后,图片如上图所示,只有横纵坐标轴的数字,我们需要添加横纵坐标的名称、图例、网格,调整图片大小。手动的方式是在Figure页面手动调整。
定义横纵坐标信息
选中线条,出现线条编辑选项。
修改线型并插入图例
除了这样,还能设定横纵坐标的起始终止值和增量大小,手动方法比较简单,适合代码小白,但是当批量画图时,再这样一个一个的去调就会很浪费时间,这时候就需要用代码设定,一劳永逸了。
- x=[1 2 3];
- a=[1 2 3];
- plot(x,a,\’–r\’,\’linewidth\’,3) //“–r”代表虚线红色,3代表线宽
- xlabel(\’时间/t\’) //定义横坐标名称
- ylabel(\’位移/mm\’)//定义纵坐标名称
- grid on //网格开启
代码方式修改图形信息一
当我们需要横纵坐标以特定的值起始或终止时,需要再加入axis([0 3 0 3])语句,四个数字分别代表横坐标的起始终止值和纵坐标的起始终止值。
代码方式修改图形信息二
Matlab的线型和颜色组合有多种,有需求的朋友可以百度,这里不做详解。
学过C语言的朋友肯定知道函数,一般我们会在主程序里面调用其他函数,这样不仅能够使主程序代码简洁,还有利于代码的修改。比如,我现在有两个变量a和b,我要做的事是将a和b相加,但是我在过程中加入了一个前提条件,就是b得先乘以2再与a相加,这时候b乘以2的过程我们就可以写一个子函数,然后在主程序里面调用这个函数即可。(只用来说明函数的用法)
我们需要建立两个脚本,一个脚本用来写函数,一个脚本用来写主程序。
首先是函数脚本,代码格式为:
- function [m]=doublex(n)
- m=n*2;
- end //m为程序结果返回值,n为形式参数,doublex为函数名称
中间的函数内容我们可以自己定义,不管经过多少复杂的运算,只返回m的值,当然了,还可以加入其他要返回的值,需要注意的是,这个脚本要保存到工作路径下,文件名与函数名相同。
其次是主程序,主程序定义了a和b的值,主程序doublex(b)的b是实参,可以是其他字母。直接用函数名就可以调用刚才的函数。
function函数的基本用法
当我们程序需要写很长时就会用到函数,一般情况下,用的不多,基本原理就是这样,更多用法用到的时候再扩展。
循环语句的使用频率还是较高的,属于一劳永逸之一劳永逸级别,因为涉及到更简便的运算复制,构造时比较费脑,现在以上文的一个例子来讲一下原理和用法。
前面说到多图并存,用循环语句的话也能实现,代码如下:
- a=[1 2 3];
- b=[2 4 6;3 6 9;4 8 12];
- for i=1:1:3 // 循环条件是i从1开始以1的增量到3停止,共执行3次循环
- figure(i) //这里我将figure语句中的变量改为了i,i会按照1 2 3变化
- plot(a,b(i,:)) //这里b(i,:)表示b的第i行第所有列,即第i行数据,i会按照1 2 3变化
- end //结束循环
这里我将b、c和d三个变量的数据量综合成了一个3行3列的数组,直接以变化的列号调用,不用再一个一个定义和调用,省去了大量的时间。
一级循环
当然,循环也是可以套用的,实现二级循环,需要协调好变量的关系,当我想画3个图,每个图由3个子图组成时,代码如下,在这里共进行了9次循环
- a=[1 2 3];
- b=[2 4 6;3 6 9;4 8 12];
- for i=1:1:3
- figure(i)
- for j=1:1:3
- subplot(3,1,j)
- plot(a,b(j,:))
- end
- end
二级循环
循环语句还有while和switch语句,个人感觉for语句就可以解决很多问题了,就不在此深入探索了,不然又得吓退一群代码小白了。
本期内容就到这里结束了,目前想到的最基础的+足够用的就这些了,回顾看来,需要学习的并不多,可以实现的功能却很多。
Matlab进阶我觉得不是学习了多少语句,而是如何以所学的语句解决各种各样的问题,思考复杂问题的过程才是进阶的过程。
Matlab学习是一个持久的过程,我觉得没必要捧着Matlab教程书全篇去读,而是在有解决问题需求的时候能够想到用Matlab去解决,在有新语句学习需求的时候去找新语句,这样能够将各种用法记得很清楚。希望对大家有帮助!
关注“博硕科研绘图”公众号,了解更多科研绘图知识!
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。