一、间谍安全🍉
间谍出行保证自己的安全也是第一位。我们可以使用智监系统到达以下目的:
- 智能监测出现在我们电脑前的人。
- 偷偷观察一下有谁会在我们不在场的时候想发现我们在做什么,这个时候我们可能已经被怀疑了!🤫
“ 编程改造世界!”
对于本栏,我们要实现的正是智能防盗监控系统,想要实时监测电脑屏幕与摄像头前的人,我们必须满足以下几个条件:
- 🎈当前屏幕的分辨率,以方便之后调整电脑屏幕截图的尺寸。
- 🎈间隔的获取:(1)屏幕画面的截图(2)开启摄像头捕捉到的一帧图像。
- 🎈将目标截图发送到我们的邮箱。
- 🎈在我们离开自己的电脑后,启动算法。
是不是超级简单呢?接下来,我们将一一实现它们,并将他们整合为一个打包好的类。
二、项目演示🍉
2.1 电脑屏幕截屏🎈
2.2 摄像头截屏🎈
三、一步一步来编程实现它们👑
不着急Copy代码,最后面有一个打包好的类,方便大家使用。这里是拆解代码用于解释各个函数的意思。
3.1 我们需要获取当前屏幕的分辨率,以方便之后调整电脑屏幕截图的尺寸。🎈
def grab_screen(region=None): hwin = win32gui.GetDesktopWindow() if region: left, top, x2, y2 = region width = x2 - left + 1 height = y2 - top + 1 else: width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN) height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN) left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN) top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN) hwindc = win32gui.GetWindowDC(hwin) srcdc = win32ui.CreateDCFromHandle(hwindc) memdc = srcdc.CreateCompatibleDC() bmp = win32ui.CreateBitmap() bmp.CreateCompatibleBitmap(srcdc, width, height) memdc.SelectObject(bmp) memdc.BitBlt((0, 0), (width, height), srcdc, (left, top), win32con.SRCCOPY) signedIntsArray = bmp.GetBitmapBits(True) img = np.frombuffer(signedIntsArray, dtype='uint8') img.shape = (height, width, 4) srcdc.DeleteDC() memdc.DeleteDC() win32gui.ReleaseDC(hwin, hwindc) win32gui.DeleteObject(bmp.GetHandle()) return cv2.cvtColor(img, cv2.COLOR_BGRA2RGB)
2、我们需要间隔的获取,屏幕画面的截图和开启摄像头捕捉到的一帧图像。🎈
def get_screen_size(): import tkinter screen = tkinter.Tk() w = screen.winfo_screenwidth() # 获取当前屏幕的宽 h = screen.winfo_screenheight() # 获取当前屏幕的高 return w, h
3、我们需要将我们获得的截图发送到我们的邮箱。
#! /usr/bin/env python # coding=utf-8 import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.application import MIMEApplication def send_img_to_email(rec_qq, sen_qq, pwd, img_path): receiver = rec_qq + "@qq.com" # 发送邮件的邮箱 sender = sen_qq + "@qq.com" # 接受邮件的邮箱(可以和上面的一样 pwd = pwd # @qq.com邮箱SMTP的授权码 # wquuvpbunfqoeahe msg = MIMEMultipart() msg["Subject"] = "有陌生人来访!" # 邮件的主题 msg["From"] = sender msg["To"] = receiver part = MIMEText("请查收陌生人照片!") # 邮件的正文 msg.attach(part) # 图片 part = MIMEApplication(open(img_path, 'rb').read()) part.add_header('Content-Disposition', 'attachment', filename=img_path) msg.attach(part) try: s = smtplib.SMTP("smtp.qq.com", timeout=30) # 连接smtp邮件服务器,端口默认是25 s.ehlo() s.starttls() s.login(sender, pwd) # 登陆服务器 s.sendmail(sender, receiver, msg.as_string()) # 发送邮件 s.close() print('邮件发送成功!') except smtplib.SMTPException: print('邮件发送失败!') # 使用案例 if __name__ == '__main__': qq = '2642898145' send_img_to_email(qq, qq, 'wquuvpbunfqoeahe', '2.png')
四、打包好的成品类——可设置每隔多久发送一次👑
import time
import cv2
import numpy as np
import win32gui
import win32ui
import win32con
import win32api
# coding=utf-8
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
class computerScreenDetecter(object):
def __init__(self, qq, pwd, img_path, time_cell):
self.qq = qq
self.pwd = pwd
self.img_path = img_path
self.time_cell = time_cell
def get_screen_size(self):
import tkinter
screen = tkinter.Tk()
w = screen.winfo_screenwidth() # 获取当前屏幕的宽
h = screen.winfo_screenheight() # 获取当前屏幕的高
return int(w*1.3), int(h*1.3)
def grab_screen(self, region=None):
hwin = win32gui.GetDesktopWindow()
if region:
left, top, x2, y2 = region
width = x2 - left + 1
height = y2 - top + 1
else:
width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)
height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)
left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)
hwindc = win32gui.GetWindowDC(hwin)
srcdc = win32ui.CreateDCFromHandle(hwindc)
memdc = srcdc.CreateCompatibleDC()
bmp = win32ui.CreateBitmap()
bmp.CreateCompatibleBitmap(srcdc, width, height)
memdc.SelectObject(bmp)
memdc.BitBlt((0, 0), (width, height), srcdc, (left, top), win32con.SRCCOPY)
signedIntsArray = bmp.GetBitmapBits(True)
img = np.frombuffer(signedIntsArray, dtype='uint8')
img.shape = (height, width, 4)
srcdc.DeleteDC()
memdc.DeleteDC()
win32gui.ReleaseDC(hwin, hwindc)
win32gui.DeleteObject(bmp.GetHandle())
return cv2.cvtColor(img, cv2.COLOR_BGRA2RGB)
def pritn_time(self):
import time
time_tuple = time.localtime(time.time())
print("当前时间为: {}年{}月{}日 - {}:{}:{}".format(time_tuple[0], time_tuple[1], time_tuple[2], time_tuple[3],
time_tuple[4],
time_tuple[5]))
def send_img_to_email(self):
sender = self.qq + "@qq.com" # 发送邮件的邮箱(
receiver = self.qq + "@qq.com" # 接受邮件的邮箱 可以和sender的一样
pwd = self.pwd # @qq.com邮箱SMTP的授权码
# wquuvpbunfqoeahe
msg = MIMEMultipart()
msg["Subject"] = "有陌生人来访!" # 邮件的主题
msg["From"] = sender
msg["To"] = receiver
part = MIMEText("请查收陌生人照片!") # 邮件的正文
msg.attach(part)
# 图片
part = MIMEApplication(open(self.img_path, 'rb').read()) # ''和该.py文件在同一个文件夹下
part.add_header('Content-Disposition', 'attachment', filename=self.img_path)
msg.attach(part)
try:
s = smtplib.SMTP("smtp.qq.com", timeout=30) # 连接smtp邮件服务器,端口默认是25
s.ehlo()
s.starttls()
s.login(sender, pwd) # 登陆服务器
s.sendmail(sender, receiver, msg.as_string()) # 发送邮件
s.close()
print('邮件发送成功!')
except smtplib.SMTPException:
print('邮件发送失败!')
def get_creamerImg(self):
cap = cv2.VideoCapture(0)
time_cell = 1
while time_cell:
success, img = cap.read()
cv2.imwrite('screen_img.png', img)
time_cell -= 1
cap.release()
cv2.destroyAllWindows()
def demo(self):
w, h = self.get_screen_size()
start_time = time.time()
while True:
img = self.grab_screen(region=(0, 0, w, h))
end_time = int(time.time() - start_time)
# 间隔60s发送一次
if end_time % self.time_cell == 0:
self.pritn_time()
cv2.imwrite('screen_img.png', img)
print('电脑屏幕检测准备开始!')
self.send_img_to_email()
print('电脑摄像头检测准备开始!')
self.get_creamerImg()
self.send_img_to_email()
# 使用案例
if __name__ == "__main__":
qq = '2642898145' # 发送者和接受者的QQ都用同一个
kwd = 'wquuvpbunfqoeahe' # QQ邮箱SMTP授权码
img_path = 'screen_img.png' # 写入本地图片路径
time_cell = 60 # 时间间隔多久发送一次截屏 单位:秒(s)
sd = computerScreenDetecter(qq, kwd, img_path, time_cell)
sd.demo()
五、补充想法🍉
5.1 人脸识别🎈
我们是不是可以添加一个人脸识别,捕捉到摄像头前人的图片之后识别是否是自己或者自己认识的人,如果不是,那么才发送图片警醒自己,如果是,那么告知是谁?
NOTE:OpenCV的官方GitHub仓库地址是:https://github.com/opencv/opencv
你可以在该仓库中找到相关的文件。具体来说,人脸识别器(CascadeClassifier)所需的级联分类器文件通常位于 data/haarcascades
目录下。而人脸检测器(face_cascade.detectMultiScale)使用的级联分类器文件是 haarcascade_frontalface_default.xml
。
你可以通过以下链接直接访问该文件: https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml
请注意,为了使用人脸识别器和人脸检测器,你需要将级联分类器文件下载到本地,并在代码中指定正确的文件路径。
import cv2
import numpy as np
# 加载OpenCV的人脸识别器
face_cascade = cv2.CascadeClassifier('path/to/haarcascade_frontalface_default.xml')
# 加载训练好的人脸识别模型(如LBPH或Eigenfaces)
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
face_recognizer.read('path/to/trained_model.yml')
# 加载图像
image = cv2.imread('path/to/image.jpg')
# 将图像转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 使用人脸检测器检测人脸
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
# 对每个检测到的人脸进行识别
for (x, y, w, h) in faces:
# 提取人脸区域
face_roi = gray[y:y+h, x:x+w]
# 进行人脸识别
label, confidence = face_recognizer.predict(face_roi)
# 绘制标签和置信度值在图像上
text = f"Label: {label}, Confidence: {confidence}"
cv2.putText(image, text, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 3)
# 显示结果
cv2.imshow('Face Recognition', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
5.2 人脸检测🎈
添加一个人脸检测,每当检测到人脸才进行截图的操作。
NOTE:在下面的代码中,你需要将'path/to/haarcascade_frontalface_default.xml'
替换为OpenCV库中实际的haar级联分类器文件路径。你可以在OpenCV的官方GitHub仓库中找到这个文件(https://github.com/opencv/opencv/tree/master/data/haarcascades)。
import cv2
import numpy as np
# 加载OpenCV的人脸检测器
face_cascade = cv2.CascadeClassifier('path/to/haarcascade_frontalface_default.xml')
# 加载图像
image = cv2.imread('path/to/image.jpg')
# 将图像转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 使用人脸检测器检测人脸
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
# 在图像上绘制人脸矩形框
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 3)
# 显示结果
cv2.imshow('Face Detection', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
完毕!
制作不易,望点赞+关注+收藏(😊(●'◡'●)