실제 전투 | Python과 OpenCV를 사용하여 노인 낙상에 대한 지능형 모니터링 시스템 구축(단계 + 소스 코드)

Jiang Hu의 Caigou로 알려진 알려지지 않은 대학생
원작자: jacky Li
이메일: [email protected]

 완료 시간: 2023.2.4
최종 편집: 2023.2.4

가이드

이 기사에서는 Python, OpenCV 및 MediaPipe를 사용하여 노인의 낙상에 대한 지능형 모니터링 시스템을 구축합니다. 앞으로 조용히 넘어지는 것을 방지하기 위해 아무도 돌보지 않을 것입니다.

목차

배경 소개

구현 단계

[1] 필요한 모듈을 가져옵니다.

[2] 각도를 계산하는 함수를 정의합니다.

【3】좌표 찾기:

【4】피험자(노인)가 안전한지 또는 넘어졌는지 어떻게 알 수 있습니까?

【5】침대와 바닥을 구분하는 방법은?

[6] 결과를 화면에 출력해 보겠습니다.

[7] GUI 추가:

작가가 할말이 있다


배경 소개

    노인 모니터링 시스템은 노인이 침대에 누워 있는지, 바닥에 쓰러져 있는지 감지할 수 있는 지능형 감지 시스템이다. 직장에 없거나 외출 중일 때 집에 있는 노인을 모니터링하여 문제가 발생하면 알림을 받을 수 있는 실제 문제 해결 프로그램입니다.

구현 단계

[1] 필요한 모듈을 가져옵니다.

    Python에서 Numpy, MediaPipe 및 opencv 가져오기

import cv2
import mediapipe as mp
import 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】좌표 찾기:

    또한 좌표를 찾아야 조건에서 사용할 수 있고 compute_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 함수를 쉽게 사용할 수 있습니다.

    함수의 사용 예는 다음과 같습니다.

cv2.putText(image, ‘Condition: ‘, (15,12), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0), 1, cv2.LINE_AA)

[7] GUI 추가:

    또한 약간의 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 feed
def 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)

작가가 할말이 있다

코드가 필요한 경우 블로거와 비공개로 채팅하면 블로거가 다시 확인합니다.
블로거가 말한 내용이 유용하다고 생각되면 지원을 클릭하고 이러한 문제를 계속 업데이트할 것입니다...

추천

출처blog.csdn.net/weixin_62075168/article/details/128885743