标签归档: 人脸识别

介绍一个照片管理工具:PhotoPrism

最近发现一个跟jAlbum功能高度一致的相册工具,PhotoPrism,安装步骤不复杂,这里不作介绍。准备拿来跟jAlbum对比一下。看了官网的Demo,发现跟我之前做jAlbum时预想的功能完全一致:照片分类、人脸识别、照片日历还有照片打Tag,最重要的是,我一直不会做的界面,这个工具的要好用很多。赶紧docker安装试用了一下,挂载Home Server下的图片目录,在照片比较少时,完成加载很快,但是照片一但多了,就很慢。下面从各个维度对比一下,以打分的方式比较 :-)

比较项 jAlbum PhotoPrism
人脸识别 借助于第三方系统,识别精确特别是人脸对比方面精准。
5分
使用Pigo,All In One的方式,识别准确率较低。
3分
图片场景识别 不支持 支持识别图片场景,自动打标签,准确率不高
3分
备份照片到远端 支持对象存储(华为OBS和Amazon S3)
4分
使用Webdav协议备份。某些云盘支持WebDAV,因此可以网云盘备份照片。
4分
视频管理 支持
4分
支持,支持从照片中抽帧并做图片分析。
4分
界面 简陋
2分
界面精美,动态页面非常好用,支持编辑元数据,指定人像名字,编辑人像。
5分
客户端 浏览器 浏览器,有准备推出手机端的应用。
自动识别新增文件 支持
4分
需要手动点击分析图片文件按钮。
2分
支持上传照片 不支持 支持
支持自动备份手机照片 不支持 不支持
访问安全 支持简单的发放Token方式,支持Https 支持单账号登录。
照片分享 不支持 支持
功能定制 支持通过服务端参数定制很少的页面行为。
2分
支持在界面配置各种功能。
5分
性能 流畅
4分
页面响应明显卡顿。
2分
技术栈 Java、少量JS、处理EXIF信息、FFmpeg、SQLite。
更多依赖第三方服务。
Golang、Vue.js、SQLite、处理EXIF信息、FFmpeg、WebDAV。
All In One,几乎不依赖第三方
开发规模 个人玩具 ^_^,16年基本完成,后面没在大规模开发。 形成规模的开源社区,多人协作开发,正在商业化的路上。18年开始在Github开源,具体开始时间不详。
| 1 分2 分3 分4 分5 分 (5.00- 2票) Loading ... Loading ... | 归档目录:WEB网络, 数码硬件 | 同时打有标签:, , , |

基于Dlib、Flask和Sqlite的人脸检测和识别服务

这个十一原定的计划取消了,没有做好备份计划,也就不打算出远门了,关在家里,把一直都想做的一个本地化的人脸识别服务整了一下。提供人脸分析的开源服务似乎很多年都没有大的变化了,一直都是Dlib和OpenCV,对比了一下,Dlib更容易使用。一直没有正经写过Python代码,翻出N年前买的Python编程书,边翻书Google、边写代码。基本的代码流程比较简单,Dlib官方也有例子,很容易运行起来,但是要服务化,要做人脸比对,并且是增量的人脸比对和识别,并不容易。说做就做,最终整个服务形成如下架构。

架构图:
image

代码和部署使用方法在如下git工程:https://git.codefine.site:3000/Shentar/facerec

首先需要将探测的过的“人脸”存储起来,然后能输入一张人脸返回与该人脸近似的所有人脸,这样客户端好做人脸归集。很快做好了一个初步的框架:使用Flask提供REST接口接收照片,在响应中返回人脸的特征标识,使用SHA256对人脸68点位的描述向量进行HASH,返回给客户端。同时将HASH值和实际的token存储到Sqlite。第一天大概就完工了这个功能。

运行起来,发现单纯的Flask不能并发,第二个请求会报错,一次只能接受和处理一个请求。于是又按照网上的经验,使用Gunicorn和Gevent来做多线程的方案,因为习惯了单进程多线程的方式,多线程访问Sqlite需要加锁,按照通用的做法,使用一个队列来管理Sqlite实例。继续验证,发现多线程并不能加速Detect的效率,貌似Dlib不支持多线程加速。调整为多进程,四个CPU都能运用起来。

1d2dd2b5bcde40b6a563996821d84843

终于找到了一个能将这个3.2GHZ的四核CPU跑满的业务了 ^_^

Architecture: x86_64
CPU op-mode(s):                  32-bit, 64-bit
Byte Order:                      Little Endian
Address sizes:                   39 bits physical, 48 bits virtual
CPU(s):                          4
On-line CPU(s) list:             0-3
Thread(s) per core:              2
Core(s) per socket:              2
Socket(s):                       1
NUMA node(s):                    1
Vendor ID:                       GenuineIntel
CPU family:                      6
Model:                           94
Model name:                      Intel(R) Core(TM) i3-6100T CPU @ 3.20GHz

人脸检测的效果还不错,错误率的话,自己家用是够了。特别是在侧脸检测上面,比较准确。在人脸比对方面,错误率就要高一些了,反复验证,发现0.36的比对阀值比较合适。侧脸虽然检测率高,但是在比对上面,只用通用的拟合范数,结果会表现为差异很大。因此这里应该是需要有定制化的比对实现,只做部分比对。这块需要深入到人脸检测技术内部,去分析128D的特征值向量的每一个值,短时间内没办法去研究透了。

由于采用了多进程,因此没法共用一个Sqlite运行时实例,强行并发读写访问会导致数据库错乱,不得不又做了一个服务来封装Sqlite,多个检测进程输出的人脸特征值都发给该服务来顺序存储,同时也返回给客户端。两个服务之间同样采用REST接口交互。

准备大规模上量,将jAlbum目前使用的线上人脸识别服务切换到这个本地服务上面,又发现检测时长非常高,一张4M的图片,大概需要几秒的时间,并且还有些非常小的区块被检测到了。对于检测慢的问题,考虑降低输入的照片的像素,图片减小后,长宽的像素点都相应减少了,但是人脸的特征点并不会损失太多。因此先对图片进行降低像素和尺寸,识别完成后,对识别到的人脸在照片上的位置也要相应做缩放,对比了一下,原始大小检测和缩放后检测,再对结果做相反的缩放,最终结果误差不大,但是这样能极大提速。对于非人脸和质量不高的人脸被检测到的问题,做了一些粗浅的限制,人脸长宽必须大于100的阀值才认为是正常的人脸。Dlib应该有正统的输出人脸的质量的参数,查了很久,没有找到合适的方法,就只能先这样吧。在比对方面,还有一些重要的概念,没有弄明白,如人脸对齐、年龄、性别检测等,不清楚我的代码里面是否已经有调用已经做了这块。

具体的处理代码:

data = np.frombuffer(data, np.uint8) 
if data is None: 
    raise Exception('image is required.') 

zoom_ratio = 1 
if data.size > 6 * 1024 * 1024: 
    img = cv2.imdecode(data, cv2.IMREAD_REDUCED_COLOR_4) 
    zoom_ratio = 4 
elif data.size > 4 * 1024 * 124: 
    img = cv2.imdecode(data, cv2.IMREAD_REDUCED_COLOR_2) 
    zoom_ratio = 2 
else: 
    img = cv2.imdecode(data, cv2.IMREAD_COLOR) 

faces = [] 
dets = detector(img, 1)

总的来说,开源项目,适合做一下Demo,如果要尽善尽美,那么就要深入到源码,有针对性的去优化检测和比对模型。作为个人的实验和家用还是很不错的。至少在快速编程和服务化这方面。

| 1 分2 分3 分4 分5 分 (5.00- 2票) Loading ... Loading ... | 归档目录:WEB网络, 数码硬件, 架构设计, 移动互联, 软件应用 | 同时打有标签:, , , , |
返回顶部