[Fußgängerverfolgung und Sturzerkennung und -alarm (YOLO V3 Tiny, Deepsort, ST-GCN)]

Vorwort

Verwenden Sie die Methoden YOLO V3 Tiny, Deepsort und ST-GCN zur Fußgängerverfolgung und Sturzerkennung. Unter anderem wird YOLO V3 Tiny zur Fußgängererkennung, DeepSort zur Verfolgung und ST-GCN zur Verhaltenserkennung verwendet.

Projekteinführung

Für das Sturzerkennungsprojekt gibt es eine direkte Unterscheidung durch den YOLO-Erkennungsrahmen und eine Erkennung durch Openpose, aber die
Anforderungen an die Richtung der Kamera sind sehr hoch, und der Winkelerkennungseffekt der Seite ist ideal, aber die Winkelerkennung von Die Kamera befindet sich an einer hohen Stelle oder auf der Rückseite. Der Effekt ist schlecht. Die Verwendung von ST-GCN in diesem Projekt hat eine bessere Wirkung auf die Sturzerkennung aus verschiedenen Winkeln.

Verwenden Sie Tiny YOLO oneclass, um jede Person im Frame zu erkennen, und verwenden Sie AlphaPose, um die Skelettpose zu erhalten. Verwenden Sie dann das ST-GCN-Modell, um die Aktion in allen 30 von jeder Person verfolgten Frames vorherzusagen.

Dieses Projekt trainiert ein neues TinyYOLO-Einzelklassenmodell, um nur menschliche Objekte zu erkennen, und reduziert die Größe des Modells. Trainiert unter Verwendung des rotationsergänzten COCO-Personenschlüsselpunktdatensatzes für eine robustere Personenerkennung in verschiedenen Winkelposen.

Verwenden Sie zur Aktionserkennung die Daten im Le2i-Sturzerkennungsdatensatz (Kaffeeraum, Zuhause), um Skelettposen über AlphaPose zu extrahieren, und markieren Sie jeden Aktionsrahmen manuell für das Training des ST-GCN-Modells.

Unterstützt jetzt 7 Aktionen: Stehen, Gehen, Sitzen, Hinlegen, Aufstehen, Hinsetzen, Fallen.

Einführung in ST-GCN

Fügen Sie hier eine Bildbeschreibung ein
Konstruieren Sie anhand der Gerüstsequenzinformationen eines Actionvideos zunächst eine Diagrammstruktur, die die Gerüstsequenzinformationen darstellt. Die Eingabe von ST-GCN ist der gemeinsame Koordinatenvektor auf dem Diagrammknoten. Anschließend wird eine Reihe von raumzeitlichen Diagrammfaltungsoperationen durchgeführt, um die hoch- Ebenenfunktionen; schließlich verwenden Sie den SofMax-Klassifikator, um die entsprechende Aktionsklassifizierung zu erhalten. Der gesamte Prozess realisiert eine End-to-End-Schulung.

GCN hilft uns, lokale Merkmale benachbarter Gelenke im Raum zu lernen. Auf dieser Grundlage müssen wir die lokalen Besonderheiten der Gelenkveränderungen im Laufe der Zeit erlernen. Die Überlagerung von Timing-Funktionen für Graphen ist eines der Probleme, mit denen Graph-Faltungsnetzwerke konfrontiert sind. Es gibt zwei Hauptideen für die Forschung in diesem Bereich: Time Convolution (TCN) und Sequence Model (LSTM).

ST-GCN verwendet TCN. Aufgrund der festen Form kann die Zeitfaltungsoperation mit herkömmlichen Faltungsschichten abgeschlossen werden. Zum besseren Verständnis kann die Faltungsoperation eines Bildes verglichen werden. Die Form der letzten drei Dimensionen der Feature-Map von ST-GCN ist (C, V, T), was der Form (C, W, H) der Bild-Feature-Map entspricht.

Die Kanalnummer C des Bildes entspricht der Merkmalsnummer C des Gelenks.
Die Breite W des Bildes entspricht der Anzahl V der Keyframes.
Die Höhe H des Bildes entspricht der Anzahl T der Gelenke.

Bei der Bildfaltung beträgt die Größe des Faltungskerns „w“ × „1“, und die Faltung von w Pixelreihen und 1 Pixelspalte wird jedes Mal abgeschlossen. „Schritt“ ist s, dann jedes Mal s Pixel verschieben und dann nach Abschluss einer Zeile eine Faltung der nächsten Pixelzeile durchführen.

Bei der zeitlichen Faltung beträgt die Größe des Faltungskerns „temporal_kernel_size“ × „1“, und die Faltung von 1 Knoten und temporal_kernel_size-Keyframes wird jedes Mal abgeschlossen. Wenn „Schritt“ 1 ist, wird jeweils ein Frame verschoben, ein Knoten vervollständigt und die Faltung des nächsten Knotens durchgeführt. Hier ist die Ausbildung:

Fügen Sie hier eine Bildbeschreibung ein

Die Eingabedaten werden zunächst stapelweise normalisiert, dann durch 9 ST-GCN-Einheiten geleitet, gefolgt von einem globalen Pooling, um den 256-dimensionalen Merkmalsvektor jeder Sequenz zu erhalten, und schließlich mit der SoftMax-Funktion klassifiziert, um die endgültige Bezeichnung zu erhalten.

Jeder ST-GCN übernimmt die Struktur von Resnet. Die Ausgabe der ersten drei Schichten hat 64 Kanäle, die mittleren drei Schichten haben 128 Kanäle und die letzten drei Schichten haben 256 Kanäle. Nach jedem Durchlaufen der ST-CGN-Struktur mit Eine Wahrscheinlichkeit von 0,5 setzt zufällig den Feature-Dropout und die Schritte der 4. und 7. zeitlichen Faltungsschicht auf 2. Beim Training mit SGD beträgt die Lernrate 0,01 und alle 10 Epochen sinkt die Lernrate um 0,1.
Link zum ST-GCN-Papier: https://arxiv.org/abs/1801.07455

Codekörper

import os
import cv2
import time
import torch
import argparse
import numpy as np

from Detection.Utils import ResizePadding
from CameraLoader import CamLoader, CamLoader_Q
from DetectorLoader import TinyYOLOv3_onecls

from PoseEstimateLoader import SPPE_FastPose
from fn import draw_single

from Track.Tracker import Detection, Tracker
from ActionsEstLoader import TSSTG

# source = '../Data/test_video/test7.mp4'
# source = '../Data/falldata/Home/Videos/video (2).avi'  # hard detect ./output/test5.mp4
source = './output/test4.mp4'


# source = 2


def preproc(image):
    """preprocess function for CameraLoader.
    """
    image = resize_fn(image)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    return image


def kpt2bbox(kpt, ex=20):
    """Get bbox that hold on all of the keypoints (x,y)获取保持所有关键点(x,y)的bbox
    kpt: array of shape `(N, 2)`,
    ex: (int) expand bounding box,
    """
    return np.array((kpt[:, 0].min() - ex, kpt[:, 1].min() - ex,
                     kpt[:, 0].max() + ex, kpt[:, 1].max() + ex))


if __name__ == '__main__':
    par = argparse.ArgumentParser(description='Human Fall Detection Demo.')
    par.add_argument('-C', '--camera', default=source,  # required=True,  # default=2,
                     help='Source of camera or video file path.')
    par.add_argument('--detection_input_size', type=int, default=384,
                     help='Size of input in detection model in square must be divisible by 32 (int).')
    par.add_argument('--pose_input_size', type=str, default='224x160',
                     help='Size of input in pose model must be divisible by 32 (h, w)')
    par.add_argument('--pose_backbone', type=str, default='resnet50', help='Backbone model for SPPE FastPose model.')
    par.add_argument('--show_detected', default=False, action='store_true', help='Show all bounding box from detection.')
    par.add_argument('--show_skeleton', default=True, action='store_true', help='Show skeleton pose.')
    par.add_argument('--save_out', type=str, default='./output/output7.mp4', help='Save display to video file.')
    par.add_argument('--device', type=str, default='cuda', help='Device to run model on cpu or cuda.')
    args = par.parse_args()

    device = args.device

    # DETECTION MODEL.检测模型
    inp_dets = args.detection_input_size
    detect_model = TinyYOLOv3_onecls(inp_dets, device=device)

    # POSE MODEL.姿势模型
    inp_pose = args.pose_input_size.split('x')
    inp_pose = (int(inp_pose[0]), int(inp_pose[1]))
    pose_model = SPPE_FastPose(args.pose_backbone, inp_pose[0], inp_pose[1], device=device)

    # Tracker.跟踪器
    max_age = 30
    tracker = Tracker(max_age=max_age, n_init=3)

    # Actions Estimate.
    action_model = TSSTG()

    resize_fn = ResizePadding(inp_dets, inp_dets)

    cam_source = args.camera
    if type(cam_source) is str and os.path.isfile(cam_source):
        # Use loader thread with Q for video file.
        cam = CamLoader_Q(cam_source, queue_size=1000, preprocess=preproc).start()
    else:
        # Use normal thread loader for webcam.
        cam = CamLoader(int(cam_source) if cam_source.isdigit() else cam_source,
                        preprocess=preproc).start()

    # frame_size = cam.frame_size
    # scf = torch.min(inp_size / torch.FloatTensor([frame_size]), 1)[0]

    outvid = False
    if args.save_out != '':
        outvid = True
        codec = cv2.VideoWriter_fourcc(*'mp4v')
        print((inp_dets * 2, inp_dets * 2))
        writer = cv2.VideoWriter(args.save_out, codec, 25, (inp_dets * 2, inp_dets * 2))

    fps_time = 0
    f = 0
    while cam.grabbed():
        f += 1
        frame = cam.getitem()
        image = frame.copy()

        # Detect humans bbox in the frame with detector model.使用检测器模型检测帧中的人类bbox
        detected = detect_model.detect(frame, need_resize=False, expand_bb=10)

        # Predict each tracks bbox of current frame from previous frames information with Kalman filter.从先前帧信息预测当前帧的每个轨迹bbox
        tracker.predict()
        # Merge two source of predicted bbox together.将两个预测bbox源合并在一起
        for track in tracker.tracks:
            det = torch.tensor([track.to_tlbr().tolist() + [0.5, 1.0, 0.0]], dtype=torch.float32)
            detected = torch.cat([detected, det], dim=0) if detected is not None else det

        detections = []  # List of Detections object for tracking.用于跟踪的检测对象列表
        if detected is not None:
            # detected = non_max_suppression(detected[None, :], 0.45, 0.2)[0]
            # Predict skeleton pose of each bboxs.预测每个BBOX的骨骼姿势。
            poses = pose_model.predict(frame, detected[:, 0:4], detected[:, 4])

            # Create Detections object.创建对象的检测。
            detections = [Detection(kpt2bbox(ps['keypoints'].numpy()),
                                    np.concatenate((ps['keypoints'].numpy(),
                                                    ps['kp_score'].numpy()), axis=1),
                                    ps['kp_score'].mean().numpy()) for ps in poses]

            # VISUALIZE.可视化
            if args.show_detected:
                for bb in detected[:, 0:5]:
                    frame = cv2.rectangle(frame, (bb[0], bb[1]), (bb[2], bb[3]), (0, 0, 255), 1)

        # Update tracks by matching each track information of current and previous frame or通过匹配当前帧和前一帧的每个轨迹信息来更新轨迹
        # create a new track if no matched.如果不匹配,则创建新轨迹。
        tracker.update(detections)

        # Predict Actions of each track.预测每个轨道的动作
        for i, track in enumerate(tracker.tracks):
            if not track.is_confirmed():
                continue

            track_id = track.track_id
            bbox = track.to_tlbr().astype(int)
            center = track.get_center().astype(int)

            action = 'pending..'
            clr = (0, 255, 0)
            # Use 30 frames time-steps to prediction.使用30帧时间步长进行预测
            if len(track.keypoints_list) == 30:
                pts = np.array(track.keypoints_list, dtype=np.float32)
                out = action_model.predict(pts, frame.shape[:2])
                action_name = action_model.class_names[out[0].argmax()]
                action = '{}: {:.2f}%'.format(action_name, out[0].max() * 100)
                if action_name == 'Fall Down':
                    clr = (255, 0, 0)
                elif action_name == 'Lying Down':
                    clr = (255, 200, 0)

            # VISUALIZE.可视化
            if track.time_since_update == 0:
                if args.show_skeleton:
                    frame = draw_single(frame, track.keypoints_list[-1])
                frame = cv2.rectangle(frame, (bbox[0], bbox[1]), (bbox[2], bbox[3]), (0, 255, 0), 1)
                frame = cv2.putText(frame, str(track_id), (center[0], center[1]), cv2.FONT_HERSHEY_COMPLEX, 0.4, (255, 0, 0), 2)
                frame = cv2.putText(frame, action, (bbox[0] + 5, bbox[1] + 15), cv2.FONT_HERSHEY_COMPLEX, 0.4, clr, 1)

        # Show Frame.
        frame = cv2.resize(frame, (0, 0), fx=2., fy=2.)
        frame = cv2.putText(frame, '%d, FPS: %f' % (f, 1.0 / (time.time() - fps_time)), (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
        frame = frame[:, :, ::-1]
        fps_time = time.time()

        if outvid:
            writer.write(frame)

        cv2.imshow('frame', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    # Clear resource.
    cam.stop()
    if outvid:
        writer.release()
    cv2.destroyAllWindows()

Erkennungseffekt

Fügen Sie hier eine Bildbeschreibung ein

Referenz

AlphaPose: https://github.com/Amanbhandula/AlphaPose
ST-GCN: https://github.com/yysijie/st-gcn

Zusammenfassen

Im Vergleich zu anderen Sturzerkennungsalgorithmen hat dieser Algorithmus einen besseren Erkennungseffekt und kann sieben Zustände erkennen. Wenn sich jedoch viele Personen auf dem Erkennungsbildschirm befinden, verringert sich die Bildrate. Verwenden Sie stattdessen YOLO + Mediapipe zur Erkennung, und die Bildrate erhöht sich nicht wesentlich. Das Problem der Bildratenreduzierung kann auch durch ein Upgrade der Hardwarekonfiguration verbessert werden.

Ich denke du magst

Origin blog.csdn.net/qq_64605223/article/details/127143548
Empfohlen
Rangfolge