再也不怕別人動電腦了!用Python實時監控
作者:美圖博客
https://www.meitubk.com/zatan/386.html
前言
最近突然有個奇妙的想法,就是當我對着電腦屏幕的時候,電腦會先識別屏幕上的人臉是否是本人,如果識別是本人的話需要回答電腦說的暗語,答對了纔會解鎖並且有三次機會。如果都沒答對就會發送郵件給我,通知有人在動我的電腦並上傳該人頭像。
過程
環境是 win10
代碼我使用的是 python3
所以在開始之前需要安裝一些依賴包,請按順序安裝否者會報錯
pip install cmake -i https://pypi.tuna.tsinghua.edu.cn/simple pip install dlib -i https://pypi.tuna.tsinghua.edu.cn/simple pip install face_recognition -i https://pypi.tuna.tsinghua.edu.cn/simple pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple
接下來是構建識別人臉以及對比人臉的代碼
import face_recognition import cv2 import numpy as np video_capture = cv2.VideoCapture(0) my_image = face_recognition.load_image_file("my.jpg") my_face_encoding = face_recognition.face_encodings(my_image)[0] known_face_encodings = [ my_face_encoding ] known_face_names = [ "Admin" ] face_names = [] face_locations = [] face_encodings = [] process_this_frame = True while True: ret, frame = video_capture.read() small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) rgb_small_frame = small_frame[:, :, ::-1] if process_this_frame: face_locations = face_recognition.face_locations(rgb_small_frame) face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) face_names = [] for face_encoding in face_encodings: matches = face_recognition.compare_faces(known_face_encodings, face_encoding) name = "Unknown" face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) best_match_index = np.argmin(face_distances) if matches[best_match_index]: name = known_face_names[best_match_index] face_names.append(name) process_this_frame = not process_this_frame for (top, right, bottom, left), name in zip(face_locations, face_names): top *= 4 left *= 4 right *= 4 bottom *= 4 font = cv2.FONT_HERSHEY_DUPLEX cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2) cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED) cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1) cv2.imshow('Video', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break video_capture.release() cv2.destroyAllWindows()
其中 my.jpg
需要你自己拍攝上傳,運行可以發現在你臉上會出現 Admin
的框框,我去網上找了張圖片類似這樣子
識別功能已經完成了接下來就是語音識別和語音合成,這需要使用到百度AI來實現了,去登錄百度AI的官網到控制檯選擇左邊的語音技術,然後點擊面板的創建應用按鈕,來到創建應用界面
創建後會得到AppID、API Key、Secret Key記下來,然後開始寫語音合成的代碼。安裝百度AI提供的依賴包
pip install baidu-aip -i https://pypi.tuna.tsinghua.edu.cn/simple pip install playsound -i https://pypi.tuna.tsinghua.edu.cn/simple
然後是簡單的語音播放代碼,運行下面代碼可以聽到萌妹子的聲音
import sys from aip import AipSpeech from playsound import playsound APP_ID = '' API_KEY = '' SECRET_KEY = '' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) result = client.synthesis('你好吖', 'zh', 1, {'vol': 5, 'per': 4, 'spd': 5, }) if not isinstance(result, dict): with open('auido.mp3', 'wb') as file: file.write(result) filepath = eval(repr(sys.path[0]).replace('\\', '/')) + '//auido.mp3' playsound(filepath)
有了上面的代碼就完成了檢測是否在電腦前(人臉識別)以及電腦念出暗語(語音合成)然後我們還需要回答暗號給電腦,所以還需要完成語音識別。
import wave import pyaudio from aip import AipSpeech APP_ID = '' API_KEY = '' SECRET_KEY = '' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) CHUNK = 1024 FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 8000 RECORD_SECONDS = 3 WAVE_OUTPUT_FILENAME = "output.wav" p = pyaudio.PyAudio() stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) print("* recording") frames = [] for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)): data = stream.read(CHUNK) frames.append(data) print("* done recording") stream.stop_stream() stream.close() p.terminate() wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb') wf.setnchannels(CHANNELS) wf.setsampwidth(p.get_sample_size(FORMAT)) wf.setframerate(RATE) wf.writeframes(b''.join(frames)) def get_file_content(): with open(WAVE_OUTPUT_FILENAME, 'rb') as fp: return fp.read() result = client.asr(get_file_content(), 'wav', 8000, {'dev_pid': 1537, }) print(result)
運行此代碼之前需要安裝 pyaudio
依賴包,由於在win10系統上安裝會報錯所以可以通過如下方式安裝。到這個鏈接 https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio 去下載對應的安裝包然後安裝即可。
運行後我說了你好,可以看到識別出來了。那麼我們的小模塊功能就都做好了接下來就是如何去整合它們。可以發現在人臉識別代碼中 if matches[best_match_index]
這句判斷代碼就是判斷是否爲電腦主人,所以我們把這個判斷語句當作main函數的入口。
if matches[best_match_index]: # 在這裏寫識別到之後的功能 name = known_face_names[best_match_index]
那麼識別到後我們應該讓電腦發出詢問暗號,也就是語音合成代碼,然我們將它封裝成一個函數,順便重構下人臉識別的代碼。
import cv2 import time import numpy as np import face_recognition video_capture = cv2.VideoCapture(0) my_image = face_recognition.load_image_file("my.jpg") my_face_encoding = face_recognition.face_encodings(my_image)[0] known_face_encodings = [ my_face_encoding ] known_face_names = [ "Admin" ] face_names = [] face_locations = [] face_encodings = [] process_this_frame = True def speak(content): import sys from aip import AipSpeech from playsound import playsound APP_ID = '' API_KEY = '' SECRET_KEY = '' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) result = client.synthesis(content, 'zh', 1, {'vol': 5, 'per': 0, 'spd': 5, }) if not isinstance(result, dict): with open('auido.mp3', 'wb') as file: file.write(result) filepath = eval(repr(sys.path[0]).replace('\\', '/')) + '//auido.mp3' playsound(filepath) try: while True: ret, frame = video_capture.read() small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) rgb_small_frame = small_frame[:, :, ::-1] if process_this_frame: face_locations = face_recognition.face_locations(rgb_small_frame) face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) face_names = [] for face_encoding in face_encodings: matches = face_recognition.compare_faces(known_face_encodings, face_encoding) name = "Unknown" face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) best_match_index = np.argmin(face_distances) if matches[best_match_index]: speak("識別到人臉,開始詢問暗號,請回答接下來我說的問題") time.sleep(1) speak("天王蓋地虎") error = 1 / 0 name = known_face_names[best_match_index] face_names.append(name) process_this_frame = not process_this_frame for (top, right, bottom, left), name in zip(face_locations, face_names): top *= 4 left *= 4 right *= 4 bottom *= 4 font = cv2.FONT_HERSHEY_DUPLEX cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2) cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED) cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1) cv2.imshow('Video', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break except Exception as e: print(e) finally: video_capture.release() cv2.destroyAllWindows()
這裏有一點需要注意,由於 playsound
播放音樂的時候會一直佔用這個資源,所以播放下一段音樂的時候會報錯,解決方法是修改 ~\Python37\Lib\site-packages
下的 playsound.py
文件,找到如下代碼
在 sleep
函數下面添加 winCommand('close', alias)
這句代碼,保存下就可以了。運行發現可以正常將兩句話都說出來。那麼說出來之後就要去監聽了,我們還要打包一個函數。
def record(): import wave import json import pyaudio from aip import AipSpeech APP_ID = '' API_KEY = '' SECRET_KEY = '' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) CHUNK = 1024 FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 8000 RECORD_SECONDS = 3 WAVE_OUTPUT_FILENAME = "output.wav" p = pyaudio.PyAudio() stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) print("* recording") frames = [] for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)): data = stream.read(CHUNK) frames.append(data) print("* done recording") stream.stop_stream() stream.close() p.terminate() wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb') wf.setnchannels(CHANNELS) wf.setsampwidth(p.get_sample_size(FORMAT)) wf.setframerate(RATE) wf.writeframes(b''.join(frames)) def get_file_content(): with open(WAVE_OUTPUT_FILENAME, 'rb') as fp: return fp.read() result = client.asr(get_file_content(), 'wav', 8000, {'dev_pid': 1537, }) result = json.loads(str(result).replace("'", '"')) return result["result"][0]
將識別到人臉後的代碼修改成如下
if matches[best_match_index]: speak("識別到人臉,開始詢問暗號,請回答接下來我說的問題") time.sleep(1) speak("天王蓋地虎") flag = False for times in range(0, 3): content = record() if "小雞燉蘑菇" in content: speak("暗號通過") flag = True break else: speak("暗號不通過,再試一次") if flag: print("解鎖") else: print("發送郵件並將壞人人臉圖片上傳!") error = 1 / 0 name = known_face_names[best_match_index]
運行看看效果,回答電腦 小雞燉蘑菇
,電腦回答暗號通過。這樣功能就基本上完成了。
結語
至於發送郵件的功能和鎖屏解鎖的功能我就不一一去實現了,我想這應該難不倒在座的各位吧。鎖屏功能可以HOOK讓鍵盤時間無效化,然後用窗口再覆蓋整個桌面即可,至於郵箱發送網上文章很多的。
好文章,我 在看 :heart: