使用Raspberry Pi,Arduino和Python进行活体检测检测

2023-11-05 14:59

本文主要是介绍使用Raspberry Pi,Arduino和Python进行活体检测检测,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

生物识别漏洞

几乎所有人脸识别系统都有一个明显的漏洞 - 像这样的硅胶面具:
这里写图片描述
被视为真面目。此外,人们在戴着乳胶面具时抢劫银行 并欺骗移民,乳胶面具变得越来越复杂和随时可用。我买了这个低端面具:
这里写图片描述

在伦敦一家服装店约30英镑。推销员告诉我,大都会警察每隔几周就会联系一名戴着面具犯罪的人。警察实际上到所有商店去搜索销售收据(记住:用现金支付)。

2009年,我 和Ted Dunstone一起写了一本书,我们在其中包含了一章关于生物识别漏洞的内容。我们预测,随着识别系统变得越来越普遍,人们将开始寻找新的方法来绕过它们。我们建议供应商不再仅仅专注于真实演示的匹配准确性,而是开发现场和欺骗检测技术。不幸的是,这是一个在很大程度上被忽视的问题,正如最近的iPhone 5s指纹扫描仪攻击所证明的那样 。一些商业人脸识别系统可以通过更容易的演示攻击进行欺骗 - 只需在登记的人身上放置照片或视频剪辑(例如在iPad上)以使用他们的身份获取访问权限。

据我所知,没有专门针对这个问题的产品。我认为看看是否可以使用廉价的组件和开源软件开发一个简单的欺骗检测系统会很有趣。

伪装检测

仅使用来自可见光谱的信息难以检测掩模。然而,在远红外(IR)光谱中,真实面具有独特的热特征:
这里写图片描述
掩模的表面温度更接近环境温度,并且热分布更均匀。在可见光波长和远红外线中创建一个看似人类的掩模将是一个挑战。

不幸的是,高分辨率热像仪(如上图所示)非常昂贵 - 从5,000美元到50,000美元不等。我们的想法是使用多光谱成像:将高分辨率可见波长相机与低分辨率红外传感器结合使用。基本概念很简单。受试者必须具有看起来 像脸的东西 ,并且这个面部对象的温度必须与人类活皮肤的温度一致。想办法解决这个问题并不难,但这个相对简单的系统可以帮助防范最简单和最常见的恶搞。

组装检测单元
1.你需要什么
Raspberry Pi:由于其低成本,低功耗要求和活跃的社区,这是该项目的完美计算机。
红外传感器:有几种选择。松下制作了 Grid-EYE。我们使用的是 Melexis MLX90620,分辨率为16×4。这种传感器的优点是价格便宜,并且有一些开源代码可用(见下文)。RoBoard构建了一个 方便的MLX90620模块 ,可以直接连接到控制器。它有点贵,但它让我免于焊接几个位。
Arduino:我使用的是Nano,但是任何一块板子(比如Uno)都没问题。
相机:我使用官方的Raspberry Pi相机板。但是,任何兼容RPi的网络摄像头都可以。
其他:有源USB集线器,电线和电缆,LED,wifi加密狗,外壳等。
2.连接红外传感器
我花了一些时间试图让Raspberry Pi和MLX90620直接相互通话。我取得了一些进展,但最终我放弃了,因为RPi的I2C库和一些Melexis组件之间似乎存在不兼容性(详见 本文 )。将它连接到Arduino很简单。这里的大部分信息 都 适用于MLX90620,Arduino官方论坛上有一些有用的帖子。

这是RoBoard的IR组件连接到Arduino Nano:
这里写图片描述
arduino_ir

我使用SparkFun的github repo中的Arduino草图, 使用I2C协议与传感器连接。我做了一些小修改,以支持串行通信,控制LED,并将温度值存储为字节:

int LEDs[] = {4, 5, 6}; // the pins used for connecting the LED// NOTE: I have not included all of the global variables and helper
//   functions here, as these are mostly unchanged. Please see
//   the SparkFun github repo link above for the rest of the source.void setLED(int r, int g, int b)
{digitalWrite(LEDs[0], r);digitalWrite(LEDs[1], g);digitalWrite(LEDs[2], b);
}void setup()
{Serial.begin(115200);// Init the I2C pinsi2c_init();// Enable pull-upsPORTC = (1 << PORTC4) | (1 << PORTC5);delay(5); //Init procedure calls for a 5ms delay after power-on// Read the entire EEPROMread_EEPROM_MLX90620();// Configure the MLX sensor with the user's choice of refresh ratesetConfiguration(refreshRate);// Calculate the current Tambientcalculate_TA();// Init LED pinspinMode(LEDs[0], OUTPUT);pinMode(LEDs[1], OUTPUT);pinMode(LEDs[2], OUTPUT);
}void loop()
{int incomingByte = 0;// Tambient changes more slowly than the pixel readings, so//  update TA only every X loops.if(loopCount++ == 20)   {// Calculate the new Tambientcalculate_TA();// Check that the POR flag is not setif(checkConfig_MLX90620()){// Re-write the configuration bytes to the MLXsetConfiguration(refreshRate);}loopCount = 0; // Reset count}// check if there has been any requestsif (Serial.available() < 0) {char c = Serial.read();if (c == 'I') {// Get the 64 bytes of raw pixel data into the irData arrayreadIR_MLX90620();// Run the calculations to fill the temperatures arraycalculate_TO();for (int i = 0 ; i < 64 ; i++){Serial.write(temperatures[i]);}Serial.println('');}else if (c == 'R') { setLED(HIGH, LOW, LOW); }else if (c == 'G') { setLED(LOW, HIGH, LOW); }else if (c == 'B') { setLED(LOW, LOW, HIGH); }else if (c == 'x') { setLED(LOW, LOW, LOW); }}delay(50);
}

3.连接Raspberry Pi和Ardunio

下一步是在Raspberry Pi和Arduino之间建立通信。Raspberry Pi需要能够发出两种类型的命令:

要求获取最新温度值
更改LED颜色的说明
设置通信有三种标准方法:通过串行USB电缆,GPIO上的串行引脚和使用I2C(本网站讨论所有这三种方法 )。我们将使用USB,因为它可靠,设置简单,也可用于为Arduino供电(尽管确保使用有源USB集线器)。

把它放在一个盒子里
我选择了尺寸为11cm x 15cm x 7cm的盒子。我钻了三个孔:一个在摄像头前面,另一个在前面用于红外传感器,另一个在后面用于LED。有源USB集线器是最大的组件 - 我需要拆开它并将其切断,以便它适合我的盒子:
这里写图片描述
在上图中,您可以看到相机和红外传感器的孔。这里包含所有内容:
这里写图片描述

如你所见,有相当多的空白空间。但是,厚USB线占用了相当多的空间,所以我无法使用更小的盒子。设计合理的外壳会更加紧凑。

编程Raspberry Pi

1.安装库
推荐但可选的步骤是使用sudo raspi-config 选项对Raspberry Pi进行超频 。这将使一切运行得更快一些。

接下来,我们将确保Raspberry Pi上的所有内容都是最新的,并安装一些库:PIL,numpy,scipy,OpenCV,pySerial和其他各种库。在shell中执行以下命令:

sudo rpi-update
sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get install python-setuptools
sudo apt-get install git-core
sudo apt-get install cmake
sudo apt-get install python-numpy
sudo apt-get install python-scipy
sudo apt-get install python-imaging
sudo apt-get install libopencv-dev
sudo apt-get install python-opencv
sudo apt-get install python-serial

完成这些(可能需要一段时间)后,我们 从github repo 安装最新的 scikit-image:

sudo python -m easy_install cython
git clone http://github.com/scikit-image/scikit-image.git
cd scikit-image/
sudo python setup.py install

运行以下Python脚本以确保所有内容都已正确安装,并且RPI和Arduino之间的通信正在运行:

import serial
import time
import skimage
import cv2# establish a connection with the Arduino
ser = serial.Serial('/dev/ttyUSB0', 115200)
time.sleep(1)
ser.setDTR(level=0)
time.sleep(1)# test the LED
for color in ['R', 'G', 'B']:ser.write(color)time.sleep(1)
ser.write('x')# get the most recent temperature readings
ser.write('I')
print ser.readline()
如果一切正常,它将循环显示所有LED颜色并打印出最新

2.用相机板拍摄图像

我在这个项目中使用了官方Rasberry Pi相机板。相机拍摄的图像质量非常高。然而,在撰写本文时,RPi基金会尚未发布相机的官方Video4Linux驱动程序,这使得使用Python变得更加困难。有一些解决方法。运行以下Python脚本以捕获图像,将其转换为灰度,并均衡直方图:

import subprocess
import skimage
from skimage import io, exposuredef AcquireImage():fn = r'/run/shm/temp.jpg'proc = subprocess.Popen('raspistill -o %s -w 480 -h 320 -n -t 0'%(fn),shell=True, stderr=subprocess.STDOUT)proc.wait()im = io.imread(fn, as_grey=True)im = exposure.equalize_hist(im)return skimage.img_as_ubyte(im)im = AcquireImage()
io.imsave('image.jpg', im)

3.将IR传感器输出与光学图像对齐

让我们来看看我们现在拥有的东西:

Arduino可以
(1)从IR传感器获得温度读数,
(2)设置LED的颜色Raspberry Pi可以与Arduino通信,并可以拍照
下图显示了我的测试设置。如您所见,看到相机和传感器彼此靠近,并指向相同的方向:
我们现在需要做的是将温度值与光学图像中的相应位置对齐。换句话说,我们需要对16×4温度阵列应用旋转,缩放和平移。起初我试图手动调整转换参数,但这是不准确和繁琐的。以下是我用于自动化对齐阶段的技术的高级概述:
这里写图片描述
用热水填充红色咖啡杯
在拍摄区域周围移动杯子时拍摄60张照片。对于每张照片,记录相应的IR数组值。
找到马克杯的位置:
照片:应用图像处理技术找到红色斑点的中间部分
红外阵列:IR阵列尺寸的两倍(从16×4到32×8),应用高斯滤波器,找到峰值温度的位置。这是IR中杯子的(内插)位置。
步骤3产生60对对应点。现在找到旋转,缩放和平移参数,这些参数可以在应用变换后最小化点之间的(最小二乘)距离。这是一个经典的优化问题,可以使用scipy.optimize.minimizePowell方法的实现来解决 。
以下是与光学图像对齐的(平滑)温度读数的示例:
如您所见,由于杯子很热,因此红外光谱中存在明显的峰值。请注意,由于杯子处于运动状态(朝向我),因此存在轻微的错位,并且温度读数存在滞后现象。
这里写图片描述
我发现MLX90620可以提供准确/一致的温度读数。我最大的抱怨是宽高比(4:1)对于这个应用来说不方便。如果它垂直定向,则该单元将支持一系列用户高度,但该单元需要直接指向主体。另一方面,如果它是水平定向的(如上图所示),则主体可以更自由地左右移动,并且一次可以跟踪多个人。但是,如果受试者特别短或高,则可能存在问题。我最终使用了垂直方向。

我有兴趣测试松下Grid-EYE,它也有64像素,但它们排列成方形(8×8)。我相信不久之后,一些廉价的高分辨率红外组件就会上市。

4.活体检测

我们现在已经准备好所有的活动以进行活体检测。过程如下:

  1. 拍个照
  2. 使用OpenCV的面部发现器查找照片中的面部
  3. 如果找到的面数为0或大于1,则返回步骤1
  4. 从红外传感器获取温度阵列
  5. 找到脸部的温度
  6. 如果面部温度低于经验确定的阈值(例如25°C):
  7. 将面部分类为假的,并照亮红色LED
  8. 如果面部温度高于阈值:
  9. 将脸部分类为真实,并照亮绿色LED
  10. 可选:以JSON格式保存所有结果,Web服务器将使用该格式

    代码如下:

import numpy as np
import cv2
import subprocess
import os, sys, time
import serial
import json
import datetime
import skimage
from skimage import io, exposure, transformFACE_TEMP_THRESH = 25
JSON_DIR = r'/home/pi/workspace/disguise/data'
IMAGE_DIR = r'[path to web2py application folder]/static/images/'
FACE_CASCADE_FN = r'[OpenCV cascades]/haarcascade_frontalface_alt.xml'# IR registration parameters
ROTATION = 0
SCALE = (34.7, 34.8)
TRANSLATION = (70, 86)# initialize communication with Andriod
ser = serial.Serial('/dev/ttyUSB0', 115200)
time.sleep(1)
ser.setDTR(level=0)
time.sleep(1)
ser.write('B')
time.sleep(1)def AcquireImage():fn = r'/run/shm/temp.jpg';proc = subprocess.Popen('raspistill -o %s -w 480 -h 320 -n -t 0'%(fn),shell=True, stderr=subprocess.STDOUT)proc.wait()im = io.imread(fn, as_grey=True)im = exposure.equalize_hist(im)return skimage.img_as_ubyte(im)def MainLoop():# load the OpenCV face finderfaceClassifier = cv2.CascadeClassifier(FACE_CASCADE_FN)file_count = 0while True:file_count += 1# clear the LEDser.write('x')# take a photo and look for a faceim = AcquireImage()faceRects = faceClassifier.detectMultiScale(im,1.2, 2, cv2.cv.CV_HAAR_SCALE_IMAGE)print 'Faces detected: %d' % (len(faceRects))if len(faceRects) != 1:# no faces found, so take a new photocontinue# get face coordinates, and make sure the face#  isn't too far awayx, y, w, h = faceRects[0]if w < 80:print 'Face too far: %d' % (w)continue# get the temperature array, and align with the imageser.write('I')ir_raw = ser.readline()ir = np.frombuffer(ir_raw.strip(), np.uint8).astype(np.float32)ir = ir.reshape((16, 4))[::-1, ::-1]# align the IR array with the imagetform = transform.AffineTransform(scale=SCALE, rotation=ROTATION,translation=TRANSLATION)ir_aligned = transform.warp(ir, tform.inverse, mode='constant',output_shape=im.shape)# set the temperature of the face as the maximum#  in the face bounding boxface_temp = ir_aligned[y:y+h, x:x+w].max()# create a dictionary to store the resultsresults = {}results['timestamp'] = str(datetime.datetime.now())results['faces_found'] = str(len(faceRects))results['upper_left_x'] = str(x)results['upper_left_y'] = str(y)results['face_width'] = str(w)results['face_height'] = str(h)results['face_termperature'] = str(face_temp)results['disguise_detected'] = str(face_temp < FACE_TEMP_THRESH)results['ir_values'] = ','.join('%0.02f'%(f) for f in ir.flat)# determine face vs non-face based on temperatureif face_temp < FACE_TEMP_THRESH:ser.write('G')time.sleep(5)else:ser.write('R')time.sleep(5)# save image in a place where the web server can display itfn = 'capture_%03d.jpg' % (file_count%100)results['optical_image_filename'] = fnio.imsave(os.path.join(IMAGE_DIR, fn), im)# save the results dictionary as a JSON filefn = os.path.join(JSON_DIR,'results_%03d.json' % (file_count%100))with open(fn, 'w') as f:f.write(json.dumps(results))if __name__ == '__main__':MainLoop()

5. web2py Web界面

最后一步是可选的。对于到目前为止所描述的设备,唯一的输出方式是后部的LED指示灯。但是,在许多情况下,通过网络远程监控结果会更方便。 web2py是一个开源Python Web框架,非常适合这个应用程序。它捆绑了快速启动和运行应用程序所需的一切,包括Web服务器,管理界面和IDE(在进行无头RPi开发时非常方便)。

要在Raspberry Pi上安装web2py,请从终端执行以下操作:

wget http://web2py.com/examples/static/web2py_src.zip
unzip web2py_src.zip
cd web2py

请注意,要远程使用管理界面,您需要生成自签名SSL证书。完成后,执行以下命令启动web2py

sudo python web2py.py -i 0.0.0.0 -p 8000 -c server.crt -k server.key

输入管理员密码,访问https://[ip address of your RPi]:8000/,您就可以开始了。web2py可以使用数据库后端,用户身份验证等为您创建模板应用程序。对于我们的应用程序,我们创建了一个控制器,而不是以JSON的形式返回最新结果:

import glob
import os
import jsonJSON_DIR = r'/home/pi/workspace/disguise/data'def index():# load most recent JSON filefiles = glob.glob(os.path.join(JSON_DIR, '*.json'))if len(files) == 0: return response.json([])files.sort(key=lambda x: os.path.getmtime(x))fn = files[-1]with open(fn) as f:return response.json(json.loads(f.read()))

演示视频

以下视频演示了一些演示攻击,从相机的角度来看。第一次攻击使用印刷的纸板面具(可在网上获得几美元),第二次攻击使用在平板电脑上播放的视频剪辑。此演示使用网络摄像头和PC创建,而不是上面概述的Raspberry Pi方法。结果相同但帧速率更高。红 盒子 =假脸,绿 盒 =真面目:
视频网址:https://youtu.be/Z-U-eXakxy0
以下视频显示了基于Raspberry Pi的检测器。这有点难以看到,但要注意设备后部的LED。红色LED =检测到假冒,绿色LED =未检测到假冒
演示视频2:https://youtu.be/UGyM817b1gc

总结

这个系统并非万无一失。想办法击败它并不难,但也不难想出改进它的方法(例如使用欧拉视频放大检测脉冲)。重点是,如果我们要依赖生物识别系统(例如边境控制),我们需要了解它们的局限性,并研究如何使它们更安全。

此盒子还有许多其他潜在用途。从本质上讲,它是:(低成本硬件)+(开源软件)+(计算机视觉)+(远程温度感应)的组合。这里有一些想法:

相同的系统可用于检测体温异常高或低的人(或动物)。例如,检测有发烧症状的人。
皮肤温度可以洞察计算机用户的情绪状态。例如,它可能能够检测用户体验测试的挫败程度,或者与在线治疗系统集成。

这篇关于使用Raspberry Pi,Arduino和Python进行活体检测检测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/350623

相关文章

Linux使用fdisk进行磁盘的相关操作

《Linux使用fdisk进行磁盘的相关操作》fdisk命令是Linux中用于管理磁盘分区的强大文本实用程序,这篇文章主要为大家详细介绍了如何使用fdisk进行磁盘的相关操作,需要的可以了解下... 目录简介基本语法示例用法列出所有分区查看指定磁盘的区分管理指定的磁盘进入交互式模式创建一个新的分区删除一个存

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat

利用Python编写一个简单的聊天机器人

《利用Python编写一个简单的聊天机器人》这篇文章主要为大家详细介绍了如何利用Python编写一个简单的聊天机器人,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 使用 python 编写一个简单的聊天机器人可以从最基础的逻辑开始,然后逐步加入更复杂的功能。这里我们将先实现一个简单的

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

Python实现高效地读写大型文件

《Python实现高效地读写大型文件》Python如何读写的是大型文件,有没有什么方法来提高效率呢,这篇文章就来和大家聊聊如何在Python中高效地读写大型文件,需要的可以了解下... 目录一、逐行读取大型文件二、分块读取大型文件三、使用 mmap 模块进行内存映射文件操作(适用于大文件)四、使用 pand