0


【摸鱼神器】基于python的BOSS识别系统

【摸鱼神器】基于python的BOSS识别系统

前言

Tip:本文仅供技术学习和参考,切勿滥用。珍爱工作,从我做起,滴滴~

试想这样一个场景:一天,风和日丽,波澜不惊。你正在愉快地摸着鱼,是如此的惬意,如此的巴适。
在这里插入图片描述
就在这时,你的BOSS突然出现,打断了这美好的瞬间,迎接你的将是无尽的…
经过这件事之后,你可能会想:”有没有一个工具,可以帮我迅速发现BOSS的到来,并迅速切换屏幕呢?“

于是,它来了。Boss Recognition System 迈着轻快的步伐来了。各位小伙伴,请系好安全带,咋们发车了🚗…(滴,学生卡)

一、整体设计

思路还是比较清晰,简单的。调用摄像头实时采集画面,通过人脸识别算法对人像进行检测,如果是BOSS则将屏幕切换到指定界面。示意图如下:
在这里插入图片描述

下面将对涉及到的每一部分进行介绍。

二、调用摄像头

这里可以直接用python的cv2库即可,利用pip安装:

  1. pip install opencv-python

具体调用方法如下:

  1. import cv2
  2. if __name__ == '__main__':
  3. # 开启摄像头
  4. video_capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
  5. # 实时捕获图像
  6. while True:
  7. _, frame = video_capture.read() # 读取每一帧图像
  8. cv2.imshow('capture', frame) # 展示画面
  9. if cv2.waitKey(1) & 0xFF == ord('q'):# Q退出
  10. break
  11. # 关闭摄像头
  12. video_capture.release()

这样便能获取到视频的每一祯画面frame,接下来我们只需要对frame进行处理和识别就可以了。

三、人脸识别

目前人脸识别的开源算法和在线API接口有很多,都能帮助我们快速地实现人脸识别效果。但是考虑到BOSS识别是分秒必争的事儿🙈,网络延迟可能会让我们错过最佳“战机”。于是,我决定用本地的人脸识别算法。

本次采用的是python中的开源人脸识别项目:face_recognition,只需要简单的几行代码便可实现人脸识别的效果。其安装方法如下:

  1. pip install face_recognition
  1. 注意:使用face_recognition前需要安好dlib库。

BOSS识别有两个思路:一个基于白名单,另一个则基于黑名单。白名单指的是除了白名单里的人像之外,都会触发切屏,其好处是不需要BOSS的照片用于学习,缺点是容易造成误判;而黑名单的好处是可以“精确打击”,但是需要搜集黑名单中对象的照片。
毕竟偷拍BOSS👴的照片成本太高了,老实巴交的我还是决定采用白名单的方式。

1. 构建白名单库

读取本地图像库,计算每个人的人脸特征编码,构建出人脸白名单库:

  1. # 读取本地肖像库,建立识别白名单
  2. def load_portrait(path=path):
  3. '''
  4. path:肖像库路径
  5. '''
  6. # 消息提示
  7. print('>>>本地图像库读取中,请稍后',end='')
  8. for i in range(5):
  9. print('.', end='')
  10. time.sleep(0.3)
  11. # 建立白名单
  12. white_map = {}
  13. for name in os.listdir(path):
  14. filepath = '%s/%s'%(path, name)
  15. avg_coding = np.zeros(128)
  16. n = 0
  17. for file in os.listdir(filepath):
  18. if '.jpg' in file:
  19. image = face_recognition.load_image_file('%s/%s'%(filepath, file))
  20. encoding = face_recognition.face_encodings(image)[0]
  21. avg_coding += encoding
  22. n += 1
  23. avg_coding /= n
  24. white_map[name] = avg_coding
  25. print('>>"%s"人脸数据加载完成!'%name)
  26. return white_map

这里的目录结构如下:
在这里插入图片描述
data为人像数据存储的根目录,每个人的照片单独存于一个文件夹,并以001、002的顺序进行编号。我们可以手工搜集照片并添加进去,当然也能通过代码自动采集,方法如下:

  1. import os
  2. import cv2
  3. import time
  4. import threading
  5. # 全局变量
  6. path = './data' # 采集的图片存储位置
  7. choice = '-1' # 选择,用于判断操作,-1表示暂无选择
  8. # 定义捕捉函数
  9. def capture(name):
  10. '''
  11. 捕捉人像函数
  12. '''
  13. # 定于图片路径及文件名
  14. global path, choice
  15. jpgpath = '%s/%s'%(path, name)
  16. if not os.path.exists(jpgpath):
  17. os.mkdir(jpgpath)
  18. i = 1 # 图片标号
  19. else:
  20. try:
  21. i = int(os.listdir(jpgpath)[0][-7:-4])+1
  22. except:
  23. i = 1
  24. # 开启摄像头
  25. video_capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
  26. # 循环捕捉头像
  27. while True:
  28. ret, frame = video_capture.read()
  29. cv2.imshow('monitor', frame)
  30. if cv2.waitKey(1) & 0xFF == ord('q'):
  31. break
  32. if choice == '0':
  33. choice = '-1'
  34. filename = '%s-%s.jpg'%(name, str(i).zfill(3))
  35. cv2.imwrite('%s/%s'%(jpgpath, filename), frame)
  36. i += 1
  37. print('"%s"保存成功!'%filename)
  38. elif choice == '1':
  39. choice = '-2' # 用于标记退回上一层
  40. break
  41. elif choice == '-1':
  42. continue
  43. else:
  44. choice = '-1'
  45. print('输入错误...')
  46. # 关闭摄像头
  47. video_capture.release()
  48. if __name__ == '__main__':
  49. # 创建目录
  50. if not os.path.exists(path):
  51. os.mkdir(path)
  52. # 显示欢迎界面和说明
  53. os.system('cls')
  54. welcome = '''
  55. _____ _ _ _ _____ _ _ _
  56. | __ \ | | (_) | / ____| | | | | |
  57. | |__) |__ _ __| |_ _ __ __ _ _| |_ | | ___ | | | ___ ___| |_
  58. | ___/ _ \| '__| __| '__/ _` | | __| | | / _ \| | |/ _ \/ __| __|
  59. | | | (_) | | | |_| | | (_| | | |_ | |___| (_) | | | __/ (__| |_
  60. |_| \___/|_| \__|_| \__,_|_|\__| \_____\___/|_|_|\___|\___|\__| v0.1
  61. '''
  62. print(welcome)
  63. # 循环捕捉头像
  64. while True:
  65. choice_1 = input('>>选择(0->输入姓名,1->退出):')
  66. if choice_1 == '0':
  67. name = input('>>姓名:')
  68. print('摄像头启动中...')
  69. time.sleep(1)
  70. threading.Thread(target=capture, args=(name,)).start()
  71. while True:
  72. choice = input('>>选择(0->保存,1->退出):')
  73. time.sleep(0.1) # 等待子线程执行,防止逻辑混乱
  74. if choice == '-2':
  75. choice = '-1'
  76. break
  77. elif choice_1 == '1':
  78. break
  79. else:
  80. print('输入错误')

2. 人脸匹配

在得到人像白名单之后,需要做的便是将视频中出现的人脸与白名单进行匹配,进而判断其身份。运用到的关键函数是compare_faces,其用法如下:

  1. matches = face_recognition.compare_faces(known_face_encodings, face_encoding)

其中known_face_encodings为白名单中的人脸特征编码,face_encoding为视频中出现的人脸特征编码,与之一一进行比较,如果相吻合返回值则为True
据此,可以定义一个人脸匹配的函数:

  1. def recognize(frame, white_map):
  2. '''
  3. frame: 捕获的摄像头帧
  4. white_map: 人像库白名单
  5. '''
  6. # 根据白名单,提取肖像编码
  7. known_face_encodings = list(white_map.values())
  8. known_face_names = list(white_map.keys())
  9. # 图像预处理(包括大小调整、格式转换)
  10. frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) # 调整图像大小,以减小计算需求
  11. frame = frame[:, :, ::-1] # BGR->RGB
  12. # 计算人脸的编码值
  13. face_locations = face_recognition.face_locations(frame)
  14. face_encodings = face_recognition.face_encodings(frame, face_locations)
  15. # 计算的编码与白名单比较,获得其匹配的名字
  16. face_names = []
  17. for face_encoding in face_encodings:
  18. # 默认为"未知"
  19. name = '未知'
  20. # 匹配
  21. matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
  22. if True in matches:
  23. index = matches.index(True)
  24. name = known_face_names[index]
  25. face_names.append(name)
  26. return face_names, face_locations

注:①这里对图像进行了压缩,目的是提高计算效率,对其准确率的影响很小。②这里用了for循环,是因为一张图像中出现的人脸可能不止一个。

四、切换屏幕

利用PyQt5库打开一个全屏的窗口,把背景图替换为正在努力工作的画面,便能轻松地实现瞒天过海,开心摸鱼了~

  1. def lock_screen(image_path='lock.jpg'):
  2. app = QApplication(sys.argv)
  3. pixmap = QPixmap(image_path)
  4. screen = QLabel()
  5. screen.setPixmap(pixmap)
  6. screen.showFullScreen()
  7. sys.exit(app.exec_())

切换屏幕仅仅是一个参考,其实这一步你可以尝试更多的玩法,比如文字提示或者语音提示,又或者直接调用快捷键切换到指定窗口。

五、完整代码

结合上面几部分,完整代码如下:

  1. import os
  2. import cv2
  3. import sys
  4. import time
  5. import numpy as np
  6. import face_recognition
  7. from PyQt5.QtGui import QPixmap
  8. from PyQt5.QtWidgets import QApplication,QLabel
  9. # 全局变量
  10. path = './data' # 人像存储路径
  11. showflag = True # 是否实时显示图像
  12. # 利用PyQt5打开全屏窗口,实现窗口替换效果
  13. def lock_screen(image_path='lock.jpg'):
  14. app = QApplication(sys.argv)
  15. pixmap = QPixmap(image_path)
  16. screen = QLabel()
  17. screen.setPixmap(pixmap)
  18. screen.showFullScreen()
  19. sys.exit(app.exec_())
  20. # 读取本地肖像库,建立识别白名单
  21. def load_portrait(path=path):
  22. '''
  23. path:肖像库路径
  24. '''
  25. # 消息提示
  26. print('>>>本地图像库读取中,请稍后',end='')
  27. for i in range(5):
  28. print('.', end='')
  29. time.sleep(0.3)
  30. # 建立白名单
  31. white_map = {}
  32. for name in os.listdir(path):
  33. filepath = '%s/%s'%(path, name)
  34. avg_coding = np.zeros(128)
  35. n = 0
  36. for file in os.listdir(filepath):
  37. if '.jpg' in file:
  38. image = face_recognition.load_image_file('%s/%s'%(filepath, file))
  39. encoding = face_recognition.face_encodings(image)[0]
  40. avg_coding += encoding
  41. n += 1
  42. avg_coding /= n
  43. white_map[name] = avg_coding
  44. print('>>"%s"人脸数据加载完成!'%name)
  45. return white_map
  46. # 人脸识别,判断当前画面的人像是否与白名单中的匹配
  47. def recognize(frame, white_map):
  48. '''
  49. frame: 捕获的摄像头帧
  50. white_map: 人像库白名单
  51. '''
  52. # 根据白名单,提取肖像编码
  53. known_face_encodings = list(white_map.values())
  54. known_face_names = list(white_map.keys())
  55. # 图像预处理(包括大小调整、格式转换)
  56. frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) # 调整图像大小,以减小计算需求
  57. frame = frame[:, :, ::-1] # BGR->RGB
  58. # 计算人脸的编码值
  59. face_locations = face_recognition.face_locations(frame)
  60. face_encodings = face_recognition.face_encodings(frame, face_locations)
  61. # 计算的编码与白名单比较,获得其匹配的名字
  62. face_names = []
  63. for face_encoding in face_encodings:
  64. # 默认为"未知"
  65. name = '未知'
  66. # 匹配
  67. matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
  68. if True in matches:
  69. index = matches.index(True)
  70. name = known_face_names[index]
  71. face_names.append(name)
  72. return face_names, face_locations
  73. if __name__ == '__main__':
  74. # 加载白名单
  75. white_map = load_portrait(path)
  76. #开启摄像头
  77. video_capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
  78. # 采集图像
  79. flag = 0
  80. while True:
  81. flag %= 3
  82. _, frame = video_capture.read()
  83. if flag == 0: # 每3帧处理因此(提高处理速度,防止视频卡顿)
  84. face_names, face_locations = recognize(frame, white_map)
  85. if '未知' in face_names: # 如果有白名单之外的人
  86. lock_screen()
  87. break
  88. flag += 1
  89. if showflag:
  90. # 将人脸框出
  91. for (top, right, bottom, left), name in zip(face_locations, face_names):
  92. # 改变坐标位置(因为处理时原图被缩小了4*4)
  93. top *= 4
  94. right *= 4
  95. bottom *= 4
  96. left *= 4
  97. # 矩形框
  98. cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
  99. #加上姓名
  100. cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
  101. font = cv2.FONT_HERSHEY_DUPLEX
  102. cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
  103. # 显示图像
  104. cv2.imshow('monitor', frame)
  105. # 按Q退出
  106. if cv2.waitKey(1) & 0xFF == ord('q'):
  107. break
  108. video_capture.release()
  109. cv2.destroyAllWindows()

运行代码之后,先前的场景变得有所不同:还是那日,微风荡漾,你开心的摸着鱼。BOSS加快脚步想要抓个现行,当他刚一过来,电脑屏幕就已经切到了工作画面。BOSS微笑地频频点头:“小伙子,不错,工作很刻苦。”

试想一下,就这操作,咱距离升职加薪,走上人生巅峰还远吗?(手动滑稽脸🙈)

写在最后

总体来说,本次的BOSS识别系统只是从想法的萌生到一次简单的尝试,还有许多可以优化的地方,比如识别的准确率和效率问题,感兴趣的小伙伴可以尝试着进一步优化。

最后,想说的是:摸鱼不是重点,学习技术才是关键,希望大家可以在摸索和尝试中不断提升自己。

我是kimol君,咋们下次再会~

在这里插入图片描述

  1. 创作不易,大侠请留步… 动起可爱的双手,来个赞再走呗 (๑◕ܫ←๑)

本文转载自: https://blog.csdn.net/kimol_justdo/article/details/123967875
版权归原作者 不正经的kimol君 所有, 如有侵权,请联系我们删除。

“【摸鱼神器】基于python的BOSS识别系统”的评论:

还没有评论