一、背景:如何实现电脑防偷窥?自己就百度
(1)贴物理防窥膜,一百度,最多就是卖膜的商家。苹果显示器真心不建议贴膜,貌似是时间久了胶纸会对显示屏表层破坏。
(2)苹果自己申请的有防偷窥专利,比如:
1:当有人看向你的屏幕的时候,电脑摄像头能检测到偷窥者,然后,电脑界面只跟随主人的眼睛显示界面内容,剩下的都是乱码。感觉挺牛的,但是,目前还只是专利,没有应用到手机电脑上。
2:可以调节可视角,从而达到物理防窥膜的功能,貌似手机有应用电脑没有。
(3)华为手机防偷窥屏设置的方法如下:
1、点击打开手机桌面上的设置。
2、在设置菜单下找到并点击进入安全。
3、进入“应用锁”,设置初始密码,并添加应用。
4、应用锁关联人脸后,可借助姿态感应器,当感知到人脸发生变化后(例如多人围观、或他人使用等场景),被加锁的应用需重新验证才能进入,应用的通知详情也会自动隐藏。此功能光线良好时体验效果更佳。
(4)Rearview(后视镜软件,收费),装上它就像给你的Mac装上了后视镜 —— 用前置摄像头随时察看是否有人在背后偷窥。
即使其他应用处于全屏模式,这个摄像头也能一直置于页面前端。
当相机检测到其他脸部时,你还可以为此添加声音警报,这样当你沉迷于工作时,也能立刻察觉到。
关于隐私方面也无需担心。Rearview应用程序不记录任何内容,无需访问网络,也不存储任何个人数据,摄像机视图仅显示当前设备摄像机捕获的图像。不过目前Rearview仅支持Mac上使用而且收费。
二、要实现的目标
综合以上,就想着能不能用脚本去实现Rearview后视镜的功能,“Python 控制Mac摄像头,实现防窥屏”
架构:mac+python3+opencv(调用摄像头)+pillow/PIL(画图库)+dlib(人脸检测库)+shape_predictor_68_face_landmarks.dat(人脸识别68个特征点检测数据库)
功能:可进行拍照、实时控制人脸
(1) https://zhuanlan.zhihu.com/p/64138092 在这里找到想要实现的功能
Blog: 作者的博客
GitHub: https://github.com/coneypo/Dlib_face_cut/ 目录下有4个脚本
- faces_chip_from_camera.py
将检测到的人脸,依次在摄像头窗口实时平铺显示(人脸对齐)(不能戴口罩遮掩口鼻,否则识别不到);
当然,在这个脚本基础上,为了达到跟Rearview后视镜的功能更接近,更满足使用需求,添加需求如下:(1)窗口可调整大小(2)窗口位置固定于左上角or右下角(3)窗口置顶,不被别的应运覆盖(4)界面出来不是镜像的,设置为镜像。
- python3 crop_faces_show.py
将检测到的人脸剪切下来, 依次排序平铺显示在新的图像上; - python3 crop_faces_save.py
将检测到的人脸生成单个图像存储到本地路径; - python3 faces_from_camera.py
将检测到的人脸,依次在摄像头窗口实时平铺显示;
(2)https://zhuanlan.zhihu.com/p/77278306 在这里找到有趣的相关摄像头应用功能
GitHub:https://github.com/tomoncle/face-detection-induction-course
- input_video_stream_paste_mask.py
获取摄像头视频,实时控制多张人脸戴墨镜和叼烟卷(戴口罩也可以) - 原理:从摄像头获取视频流,并转换为一帧一帧的图像,然后将图像信息传递给opencv这个工具库处理,返回灰度图像(就像你使用本地静态图片一样)
程序启动后,根据监听器信息,使用一个while循环,不断的加载视频图像,然后返回给opencv工具呈现图像信息。
创建一个键盘事件监听,按下"d"键,则开始执行面部匹配,并进行面具加载(这个过程是动态的,你可以随时移动)。
面部匹配使用Dlib中的人脸检测算法来查看是否有人脸存在。如果有,它将为每个人脸创建一个结束位置,眼镜和烟卷会移动到那里结束。
然后我们需要缩放和旋转我们的眼镜以适合每个人的脸。我们将使用从Dlib的68点模型返回的点集来找到眼睛和嘴巴的中心,并为它们之间的空间旋转。
在我们实时获取眼镜和烟卷的最终位置后,眼镜和烟卷从屏幕顶部进入,开始匹配你的眼镜和嘴巴。
假如没有人脸,程序会直接返回你的视频信息,不会有面具移动的效果。
默认一个周期是4秒钟。然后你可以通过"d"键再次检测。
程序退出使用"q"键。 - input_static_pic_to_gif2_for_class.py
识别任意存在人脸的照片,动态生成戴墨镜和叼烟卷的动图GIF(细长的照片容易生成效果图) - GIF动图(眼镜和烟卷从上往下匹配到眼镜,最后出现字母),可以添加到VX表情包里。
- upload_image_to_draw_bounding_box.md
识别上传对象,标注类型,并定位其准确坐标
(3)还发现好多类似Python功能脚本,这里就不赘述,感兴趣可以搜一下。
三、 架构搭建
上边的脚本运行简单,前提是你搭建好完整的架构,即Python软件、Python运行环境、各种Python库包、数据包。
具体安装什么库包,可以一边运行Python脚本看报错,一边安装缺少的库包解决报错。
架构:mac(跟Linux系统很相似)+python3+opencv(调用摄像头库)+pillow/PIL(画图库)+dlib(人脸检测库)+shape_predictor_68_face_landmarks.dat(人脸识别68个特征点检测数据库)
我自己先后安装命令记录如下:
默认Python是Python2:
pip install opencv-python #不成功
python -m pip install opencv-python==4.2.0.32 #成功
pip install PIL #提示没有安装PIL,但是,这种命令是错误的,不成功
pip install Pillow #成功安装PIL(历史渊源,具体可以自己百度,PIL很久没有维护版本更新了,后来出来了pillow是对PIL的延伸,而且pillow的上级目录名称沿用了PIL)
pip install imutils #成功
pip install dlib #失败
pip install dlib -vvv #失败
pip install dlib-19.8.1-cp36-cp36m-win_amd64.whl #失败
pip install cmake #百度说是先安装cmake 成功
pip install dlib #还是失败
换用Python3:
python3 -m pip install opencv-python #成功
/Library/Developer/CommandLineTools/usr/bin/python3 -m pip install --upgrade pip #升级pip
python3 -m pip install pillow #成功
python3 -m pip install imutils #成功
python3 -m pip install dlib #失败
python3 -m pip install dlib -vvv #失败
python3 -m pip install cmake #成功
python3 -m pip install dlib #失败,换Python3也不行,跟Python2一样。所以就不是Python版本问题。
brew install anaconda #成功,百度,好多借用anaconda搭建Python环境,去解决dlib安装失败问题。
conda create -n face python=3.8 #创建3.8环境,名为face,失败
/usr/local/anaconda3/conda create -n face python=3.8 #成功,创建face环境,但是conda不在环境变量下
/usr/local/anaconda3/condabin/conda activate face #成功,激活face环境
/usr/local/anaconda3/condabin/conda init #将环境变量信息写入.bashrc文件中,下次启动之后会自动激活conda的环境
source .bash_profile #激活,是环境变量起效
conda install opencv-python #失败,默认下载源里没有,名称不对
conda install -c conda-forge opencv #成功,在face环境下,安装opencv #-c 是在默认的下载源里增加conda-forge下载源,提高下载成功率
python3 -m pip install imutils #成功
python3 -m pip install dlib #虽然成功安装,但还是运行报错没有dlib
conda install -c menpo
conda install -c conda-forge pillow #安装到Anaconda的环境下
conda install -c conda-forge pillow=8.1.2 #成功
conda install -c conda-forge dlib
Pip install cmake -i https://pypi.tuna.tsinghua.edu.cn/simple/ #忘记了
Pip install dlib -i https://pypi.tuna.tsinghua.edu.cn/simple/ #忘记了
pip install dlib #安装提示:Requirement already satisfied: dlib in /usr/local/anaconda3/envs/face/lib/python3.8/site-packages (19.21.1)「就是,用conda安装好的dlib」
conda list |grep "dlib" #查看conda安装列表中dlib版本等信息。
dlib 19.21.1 py38hfe90ab8_0 conda-forge
conda list #查看已安装的包
pip uninstall dlib #卸载dlib
conda install -c conda-forge face_recognition #成功
pip install --no-dependencies face_recognition #可参考
Pip install face_recognition -i https://pypi.tuna.tsinghua.edu.cn/simple/ #成功
还需要,手动下载shape_predictor_68_face_landmarks.dat(人脸识别68个特征点检测数据库),然后,放到跟脚本匹配的目录下。
颚点= 0–16
右眉点= 17–21
左眉点= 22–26
鼻点= 27–35
右眼点= 36–41
左眼点= 42–47
口角= 48–60
嘴唇分数= 61–67
百度云链接:https://pan.baidu.com/s/1Z1a_ud__BWXgCWZeSdpL2g
提取码:lzjy
人脸识别69个特征点检测数据库具体可参考:和
报错解决 :
1、报错:关于ERROR: Failed building wheel for dlib
解决:这个,真的很费时间,思路就是,借用anaconda搭建Python环境,去解决dlib安装失败问题。具体看上边的命令。
关于这个问题,也可以参考:
2、报错:/anaconda3/envs/face/lib/python3.8/site-packages/skimage/io/manage_plugins.py:23: UserWarning: Your installed pillow version is < 8.1.2. Several security issues (CVE-2021-27921, CVE-2021-25290, CVE-2021-25291, CVE-2021-25293, and more) have been fixed in pillow 8.1.2 or higher. We recommend to upgrade this library.
解决:conda install -c conda-forge pillow=8.1.2,成功了。
3、报错:AttributeError: module 'dlib' has no attribute dlib.image_window()
解决:
先说一下出现问题的环境:
Mac + Anaconda 其中Python版本为3.8 。
在终端跑dlib官方样例的时候报这个错误的,但是疑惑的是,我的Anaconda创建的环境中安装dlib是很成功的,conda list 也可以找到,并且是当前最新版本dlib 19.19 :
于是看到有的解决方案中是要求安装lib11-dev ,
即 :sudo apt-get install libx11-dev
本人照做了,但是提示已经是最新版本,所以不是这个问题。
有的博客中说需要cmake,我的电脑中一直都有这个环境,所以也不是这个问题。
所以,我尝试了卸掉dlib然后再重新装,结果依旧报错,不过我装的时候都是用conda install 装的,所以前后没变化也正常。
最后解决的办法是:不用conda命令装,而是用pip。我的电脑在命令行上如果直接输入Python的话,默认导入的是Anaconda的Python3.8 ,如图
常规意义上如果用pip装的话,应该是安装到非Anaconda的环境下,但是确实在终端输入
pip install dlib
后就进入了安装状态,安装完之后,重新运行样例代码就没有这个报错了。
四、库简单介绍
(1)opencv:
import cv2 #Python脚本引入库
cap = cv2.VideoCapture(0) #创建摄像头对象——使用opencv自带的VideoCapture()函数定义摄像头对象,其参数0表示第一个摄像头。
cap.set(3, 960) #设置视频播放的的大小,需要了解摄像头支持的视频大小。 视频每一帧的宽
cap.set(4, 960) #视频每一帧的高
当然也可以设置其他的参数(第一个参数就是图中的值),具体参考下图:
逐帧显示实现视频播放
在while循环中,利用摄像头对象的read()函数读取视频的某帧,并显示,然后等待1个单位时间,如果期间检测到了键盘输入q,则退出,即关闭窗口。
while(1):
# get a frame
ret, frame = cap.read() #返回值:R1:布尔值(视频读取正确 True,错误False) R2:图像的三维矩阵,这样 ret 存储布尔值,frame 存储图像。如果不要布尔值,也可以_, frame = cap.read()。若使用一个变量来接收两个值,如 frame = cap.read() 则 frame 为一个元组,原来使用 frame 处需更改为 frame[1]。
# show a frame
cv2.imshow("capture", frame) # 窗口显示,显示名为 capture
if cv2.waitKey(1) & 0xFF == ord('q'): # cv2.waitKey(1)每帧数据延时 1ms(延时不能为 0,否则读取的结果会是静态帧)。waitKey(int delay)函数接收一个整型值,如果值是0,那么函数不会有返回值,如果delay大于0,那么超过delay ms后,如果没有按键,那么会返回-1,如果按键会返回键盘值。 在某些系统中,返回的键盘值可能不是ASCII编码(整型值)(就是没法直接判断它按的是哪个按钮了),所以通过与运算(& 0xFF)只取第八位(即,字符最后一个字节),就能愉快地玩耍了。
break
while(cap.isOpened()): # 循环读取每一帧 #函数名:cap.isOpened(),返回一个布尔值( True / False ),检查是否初始化成功,成功返回 True
print(cap.get(3)) #cap.get( propId )查询视频的参数,返回值:无,参数propId:查询的视频参数,其中部分值可以使用 cap.set() 进行修改
print(cap.get(4))
'1.jpg', frame) #保存一帧图片
cap.release() #调用release()释放摄像头
cv2.destroyAllWindows() #调用destroyAllWindows()释放所有图像窗口
(2)其他库有机会用到再补充。
生活其实也很简单,喜欢的就去争取、得到的就珍惜、失去的就忘记。