背景介绍
**为什么说这个脚本可以全国推广呢?因为在农村的话是有很多的老人留守在家的,现在也确实很多的家庭都在老家装了摄像头,但是那玩意只能偶尔看看,假如真摔倒了啥的,等你发现也太迟了。我有一个亲戚就是老人嘛,在家里睡觉没了,然后都一直没人发现!
**
为了防止家里老人摔倒也好,还是一直不动也好,这个脚本都能给我们预警,当然前提是得装摄像头嘛!
老人监测系统是一种智能检测系统,可以检测老人是否躺在床上或是否跌倒在地。这是一个解决实际问题的程序,可用于在您外出工作或外出时监控家中的老人,以便在出现任何问题时通知您。
实现步骤
【1】导入必要的模块:
在 python 中导入 Numpy、MediaPipe 和 opencv
import cv2import mediapipe as mpimport numpy as np
【2】定义一个计算角度的函数:
由于我们将根据我们使用 OpenCV 获得的角度和坐标来假设一个人是在行走还是跌倒在地上,因此,我们必须计算角度,最简单的方法是定义一个函数,然后调用它在程序中。
def calculate_angle(a,b,c): a = np.array(a) # First b = np.array(b) # Mid c = np.array(c) # End radians = np.arctan2(c[1]-b[1], c[0]-b[0]) - np.arctan2(a[1]-b[1], a[0]-b[0]) angle = np.abs(radians*180.0/np.pi) if angle >180.0: angle = 360-angle return angle
【3】查找坐标:
我们还必须找到坐标,以便我们可以在条件下使用它们,也可以将它们与calculate_angle函数一起使用。
left_eye = [landmarks[mp_pose.PoseLandmark.LEFT_EYE.value].x,landmarks[mp_pose.PoseLandmark.LEFT_EYE.value].y] left_hip= [landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].x,landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].y] left_heel = [landmarks[mp_pose.PoseLandmark.LEFT_HEEL.value].x,landmarks[mp_pose.PoseLandmark.LEFT_HEEL.value].y] right_eye = [landmarks[mp_pose.PoseLandmark.RIGHT_EYE.value].x,landmarks[mp_pose.PoseLandmark.RIGHT_EYE.value].y] right_hip = [landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].x,landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].y] right_heel = [landmarks[mp_pose.PoseLandmark.RIGHT_HEEL.value].x,landmarks[mp_pose.PoseLandmark.RIGHT_HEEL.value].y] right_index = [landmarks[mp_pose.PoseLandmark.RIGHT_INDEX.value].x,landmarks[mp_pose.PoseLandmark.RIGHT_INDEX.value].y] left_index = [landmarks[mp_pose.PoseLandmark.LEFT_INDEX.value].x,landmarks[mp_pose.PoseLandmark.LEFT_INDEX.value].y] # Calculate angle
【4】如何知道主体(老人)是安全的还是跌倒的?
我们将借助从 cv2 和 mediapipe 获得的坐标以及使用上述定义的函数获得的角度来找到这一点。
由于我们正在获取眼睛臀部和脚踝的坐标,因此我们知道当一个人平躺(倒下)时,他的眼睛、臀部和脚踝之间的角度在 170 到 180 度的范围内。因此,我们可以简单地提出一个条件,当角度在 170 -180 度之间时,我们可以说一个人摔倒了。
if angle1 != angle2 and (angle1>170 and angle2>170): if (((right_index[0]<0.70 and right_index[0]>0.20) and (right_index[1]<0.56 and right_index[1]>0.15)) or ((left_index[0]<0.55 and left_index[0]>0.18) and (left_index[1]<0.56 and left_index[1]>0.15))): stage="Hanging on !!" else: stage = "fallen :(" elif angle1 != angle2 and (angle1<140 or angle2<140) : stage = "Trying to Walk" elif angle1!=angle2 and ((angle1<168 and angle1>140) and (angle2<168 and angle2>140)): stage="Barely Walking" else: pass
现在你的脑海中可能会出现一个问题,即如何确定这个人是否真的摔倒了,或者他是否只是躺在床上,因为在这两种情况下,角度都在相同的范围内。
我们也会回答它,所以请继续阅读:)
【5】如何区分床和地板?
我们将再次使用从 OpenCV 获得的坐标,然后使用它来找到床的坐标,然后在检查跌倒条件时引入一个新条件,即当受试者的坐标与床坐标一致时,这意味着一个人在床上时自然是安全的。这种情况将排除跌倒的情况,程序将显示安全。只有当此条件变为假时,才会检查跌倒条件和其他步行和尝试步行条件。
if ((left_eye[0]>=0.41 and left_eye[0]<=0.43) and (left_hip[0]>=0.44 and left_hip[0]<=0.46) and (left_heel[0]>=0.41 and left_heel[0]<=0.43) or (right_eye[0]>=0.41 and right_eye[0]<=0.43) and (right_hip[0]<=0.43 and right_hip[0]>=0.41) and (right_heel[0]>=0.37 and right_heel[0]<=0.39)): if ((left_eye[1]>=0.24 and left_eye[1]<=0.33) and (left_hip[1]<=0.35 and left_hip[1]>=0.45) and (left_heel[1]<=0.74 and left_heel[1]>=0.72) or (right_eye[1]<=0.30 and right_eye[1]>=0.24) and (right_hip[1]<=0.50 and right_hip[1]>=0.32) and (right_heel[1]>=0.71 and right_heel[0]<=0.73)): stage = "safe :)" # Curl counter logic
因此,通过引入带有床坐标的单一条件,我们也解决了上述问题。
【6】让我们在屏幕上打印结果:
现在打印摔倒和安全等的结果;我们可以很容易地使用 cv2 中的 putText 函数来显示保存在变量 stage 中的文本。
该函数的示例用法如下所示:
cv2.putText(image, ‘Condition: ‘, (15,12), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0), 1, cv2.LINE_AA)
【7】添加图形用户界面:
我们还可以添加一点 GUI 来进一步增加整个程序的外观并使其更加用户友好。实现最简单 GUI 的代码片段示例如下:
root = Tk()root.geometry("1920x1080+0+0")root.state("zoomed")root.config(bg="#3a3b3c")root.title("Eldering Monitring") def path_select(): global video_path,cap video_path = filedialog.askopenfilename() cap = cv2.VideoCapture(video_path) text = Label(root,text="Recorded Video ",bg="#3a3b3c",fg="#ffffff",font=("Calibri",20)) text.place(x=250,y=150)# For Live feeddef video_live(): global video_path,cap video_path = 0 cap = cv2.VideoCapture(video_path) text = Label(root,text="Live Video Feed",bg="#3a3b3c",fg="#ffffff",font=("Calibri",20)) text.place(x=250,y=150) live_btn = Button(root, height =1,text='LIVE', width=8, fg='magenta', font=("Calibri", 14, "bold"), command=lambda:video_live())live_btn.place(x=1200,y=20)text = Label(root,text=" For Live Video",bg="#3a3b3c",fg="#ffffff",font=("Calibri",20))text.place(x=1000,y=30) browse_btn = Button(root, height = 1, width=8 ,text='VIDEO',fg='magenta', font=("Calibri", 14, "bold"), command=lambda:path_select())browse_btn.place(x=1200,y=90)text = Label(root,text="To Browse Video",bg="#3a3b3c",fg="#ffffff",font=("Calibri",20))text.place(x=1000,y=90) ttl = Label(root,text="ELDERING MONITERING ",bg="#4f4d4a",fg="#fffbbb",font=("Calibri",40))ttl.place(x=100,y=50) Video_frame = Frame(root, height=720, width=1080, bg="#3a3b3c")Video_Label = Label(root)Video_frame.place(x=15,y=200)Video_Label.place(x=15,y=200)
当然就我一人的话肯定是没有能力去做到全面推广的,可能有些地方有这样的功能了也不一定吧
需要代码可以关注公众号:Python源码 如果感觉博主讲的对您有用,请点个关注支持一下吧,将会对此类问题持续更新……