Wir begleiten Sie bei der Entwicklung eines videodynamischen Gestenerkennungsmodells

Dieser Artikel wurde von der Huawei Cloud Community „ CNN-VIT Video Dynamic Gesture Recognition [Playing with Huawei Cloud] “ geteilt, Autor: HouYanSong.

Dynamische Gestenerkennung für CNN-VIT-Videos

RC.gif

Die Entwicklung der künstlichen Intelligenz verändert sich von Tag zu Tag und hat auch die Entwicklung des Bereichs der Mensch-Computer-Interaktion tiefgreifend beeinflusst. Gesten als natürliche und schnelle Art der Interaktion werden häufig in Bereichen wie intelligentem Fahren und virtueller Realität eingesetzt. Die Aufgabe der Gestenerkennung besteht darin, dass der Computer schnell und genau die Art der Geste bestimmen kann, wenn der Bediener eine bestimmte Geste ausführt. In diesem Artikel wird ModelArts verwendet, um ein Algorithmusmodell für die dynamische Video-Gestenerkennung zu entwickeln und zu trainieren, um dynamische Gestenkategorien wie Wischen nach oben, Wischen nach unten, Wischen nach links, Wischen nach rechts, Öffnen, Schließen usw. zu erkennen und eine Funktion zu erreichen, die der Luft ähnelt Gesten auf Huawei-Handys.

Einführung in den Algorithmus

Der dynamische Video-Gestenerkennungsalgorithmus von CNN-VIT verwendet zunächst das vorab trainierte Netzwerk InceptionResNetV2, um Bild für Bild Video-Action-Clip-Funktionen zu extrahieren, und gibt dann den Transformer Encoder zur Klassifizierung ein. Wir verwenden den Beispieldatensatz für die dynamische Gestenerkennung, um den Algorithmus zu testen, der insgesamt 108 Videos enthält. Der Datensatz enthält Videos von 7 Gesten, einschließlich ungültiger Gesten, Wischen nach oben, Wischen nach unten, Wischen nach links, Wischen nach rechts, Öffnen, Schließen, usw. Der spezifische Betriebsablauf ist wie folgt:

Präsentation 1_edit_569379046802172.png

Zuerst dekodieren wir die aufgenommene Videodatei, um Schlüsselbilder zu extrahieren, speichern sie alle 4 Bilder und führen dann einen zentrierten Zuschnitt und eine Vorverarbeitung des Bildes durch. Der Code lautet wie folgt:

def Load_Video(Dateiname):
    cap = cv2.VideoCapture(file_name)
    # Alle paar Frames extrahieren
    Frame_Interval = 4
    Frames = []
    Anzahl = 0
    während True:
        rechts, Frame = cap.read()
        wenn nicht ret:
            brechen
        
        # Speichern Sie jeden Frame_Intervall-Frame
        wenn count % frame_interval == 0:
            #Mittelzuschnitt    
            Frame = Crop_center_square(Frame)
            # Zoomen
            Frame = cv2.resize(Frame, (IMG_SIZE, IMG_SIZE))
            # BGR -> RGB [0,1,2] -> [2,1,0]
            Frame = Frame[:, :, [2, 1, 0]]
            Frames.append(Frame)
        zählen += 1
        
    np.array(frames) zurückgeben

Dann erstellen wir einen Bildmerkmalsextraktor und verwenden das vorab trainierte Modell InceptionResNetV2, um Bildmerkmale zu extrahieren. Der Code lautet wie folgt:

def get_feature_extractor():
    feature_extractor = keras.applications.inception_resnet_v2.InceptionResNetV2(
        Gewichte = 'imagenet',
        include_top = Falsch,
        pooling = 'avg',
        input_shape = (IMG_SIZE, IMG_SIZE, 3)
    )
    
    preprocess_input = keras.applications.inception_resnet_v2.preprocess_input
    
    Eingaben = keras.Input((IMG_SIZE, IMG_SIZE, 3))
    preprocessed = preprocess_input(Eingaben)
    Ausgänge = feature_extractor (vorverarbeitet)
    
    model = keras.Model(Eingaben, Ausgaben, Name = 'feature_extractor')
    
    Rückgabemodell

Extrahieren Sie dann den Video-Feature-Vektor. Wenn das Video weniger als 40 Frames hat, erstellen Sie ein Array mit nur Nullen zum Auffüllen:

def load_data(videos, labels):
    
    video_features = []

    für Video in tqdm(videos):
        Frames = Load_Video(Video)
        counts = len(frames)
        # Wenn die Anzahl der Frames kleiner als MAX_SEQUENCE_LENGTH ist
        wenn counts < MAX_SEQUENCE_LENGTH:
            # Füller
            diff = MAX_SEQUENCE_LENGTH – zählt
            #Erstellen Sie ein Numpy-Array aller Nullen
            padding = np.zeros((diff, IMG_SIZE, IMG_SIZE, 3))
            # Array-Verkettung
            Frames = np.concatenate((Frames, Padding))
        # Holen Sie sich den vorherigen MAX_SEQUENCE_LENGTH-Frame
        Frames = Frames[:MAX_SEQUENCE_LENGTH, :]
        # Features stapelweise extrahieren
        video_feature = feature_extractor.predict(frames)
        video_features.append(video_feature)
        
    return np.array(video_features), np.array(labels)

Erstellen Sie abschließend das VIT-Modell mit dem folgenden Code:

#Positionskodierung
Klasse PositionalEmbedding(layers.Layer):
    def __init__(self, seq_length, output_dim):
        super().__init__()
        #Erstellen Sie eine Liste von 0~MAX_SEQUENCE_LENGTH
        self.positions = tf.range(0, limit=MAX_SEQUENCE_LENGTH)
        self.positional_embedding = Layers.Embedding(input_dim=seq_length, output_dim=output_dim)
    
    def call(self,x):
        #Positionskodierung
        positions_embedding = self.positional_embedding(self.positions)
        # Eingaben hinzufügen
        gib x + positions_embedding zurück

# Encoder
Klasse TransformerEncoder(layers.Layer):
    
    def __init__(self, num_heads, embed_dim):
        super().__init__()
        self.p_embedding = PositionalEmbedding(MAX_SEQUENCE_LENGTH, NUM_FEATURES)
        self.attention = Layers.MultiHeadAttention(num_heads=num_heads, key_dim=embed_dim, dropout=0.1)
        self.layernorm = Schichten.LayerNormalization()
    
    def call(self,x):
        # positionelle Einbettung
        positional_embedding = self.p_embedding(x)
        # Selbstaufmerksamkeit
        Attention_out = self.attention(
            query = positional_embedding,
            value = positional_embedding,
            key = positional_embedding,
            Attention_mask = Keine
        )
        # Ebenennorm mit Restverbindung        
        Ausgabe = self.layernorm(positional_embedding + Attention_out)
        Ausgabe zurückgeben

def video_cls_model(class_vocab):
    #Anzahl der Kategorien
    class_num = len(class_vocab)
    # Modell definieren
    Modell =keras.Sequential([
        Schichten.InputLayer(input_shape=(MAX_SEQUENCE_LENGTH, NUM_FEATURES)),
        TransformerEncoder(2, NUM_FEATURES),
        Schichten.GlobalMaxPooling1D(),
        Schichten.Dropout(0.1),
        Schichten.Dense(classes_num, Aktivierung="softmax")
    ])
    # Modell kompilieren
    model.compile(optimizer = keras.optimizers.Adam(1e-5),
                  loss = keras.losses.SparseCategoricalCrossentropy(from_logits=False),
                  metrics = ['accuracy']
    )
    Rückgabemodell

Modelltraining

Für ein umfassendes Erlebnis können Sie in ModelArts auf „Ausführen“ klicken, um das von mir veröffentlichte Notebook mit einem Klick auszuführen :

Screenshot 28.04.2024 133611_edit_572368136181552.pngDie endgültige Genauigkeit des Modells für den gesamten Datensatz erreichte 87 %, was bedeutet, dass beim Training mit einem kleinen Datensatz relativ gute Ergebnisse erzielt wurden.

Video-Argumentation

Laden Sie zunächst das VIT-Modell und rufen Sie das Videokategorie-Index-Tag ab:

Zufällig importieren
#Modell laden
model = tf.keras.models.load_model('saved_model')
# Kategorie-Tags
label_to_name = {0:'Ungültige Geste', 1:'Nach oben wischen', 2:'Nach unten schieben', 3:'Nach links schieben', 4:'Nach rechts schieben', 5:'Öffnen', 6:'Schließen', 7:'vergrößern', 8:'verkleinern'}

Verwenden Sie dann den Bildfeature-Extraktor InceptionResNetV2, um Videofeatures zu extrahieren:

# Holen Sie sich Videofunktionen
def getVideoFeat(frames):
    
    frames_count = len(frames)
    
    # Wenn die Anzahl der Frames kleiner als MAX_SEQUENCE_LENGTH ist
    Wenn Frames_Count < MAX_SEQUENCE_LENGTH:
        # Füller
        diff = MAX_SEQUENCE_LENGTH – Frames_Count
        #Erstellen Sie ein Numpy-Array aller Nullen
        padding = np.zeros((diff, IMG_SIZE, IMG_SIZE, 3))
        # Array-Verkettung
        Frames = np.concatenate((Frames, Padding))

    # Holen Sie sich den vorherigen MAX_SEQ_LENGTH-Frame
    Frames = Frames[:MAX_SEQUENCE_LENGTH,:]
    # Berechnen Sie die Videofunktionen N, 1536
    video_feat = feature_extractor.predict(frames)

    return video_feat

Schließlich wird der Merkmalsvektor der Videosequenz zur Vorhersage in den Transformer Encoder eingegeben:

#Videovorhersage
def testVideo():
    test_file = random.sample(videos, 1)[0]
    label = test_file.split('_')[-2]

    print('Dateiname: {}'.format(test_file) )
    print('Echte Kategorie:{}'.format(label_to_name.get(int(label))) )

    # Lesen Sie jedes Bild des Videos
    Frames = Load_Video (Testdatei)
    #Wählen Sie den vorherigen Frame MAX_SEQUENCE_LENGTH zur Anzeige aus
    Frames = Frames[:MAX_SEQUENCE_LENGTH].astype(np.uint8)
    # Als GIF speichern
    imageio.mimsave('animation.gif', Frames, Dauer=10)
    # Holen Sie sich Funktionen
    feat = getVideoFeat(frames)
    # Modellinferenz
    prob = model.predict(tf.expand_dims(feat, axis=0))[0]
    
    print('Vorhergesagte Kategorie: ')
    für i in np.argsort(prob)[::-1][:5]:
        print('{}: {}%'.format(label_to_name[i], Round(prob[i]*100, 2)))
    
    return display(Image(open('animation.gif', 'rb').read()))

Ergebnisse der Modellvorhersage:

Dateiname:hand_gesture/woman_014_0_7.mp4
Echte Klasse: Ungültige Geste
Prognosekategorie:
Ungültige Gesten: 99,82 %
Rückgang: 0,12 %
Schlusskurs: 0,04 %
Nach links wischen: 0,01 %
Offen: 0,01 %

 

Klicken Sie hier, um zu folgen und so schnell wie möglich mehr über die neuen Technologien von Huawei Cloud zu erfahren~

 

Ich beschloss , auf Open-Source -Industriesoftware zu verzichten – OGG 1.0 wurde veröffentlicht, das Team von Ubuntu 24.04 LTS wurde offiziell entlassen ". Fedora Linux 40 wurde offiziell veröffentlicht. Ein bekanntes Spieleunternehmen veröffentlichte neue Vorschriften: Hochzeitsgeschenke von Mitarbeitern dürfen 100.000 Yuan nicht überschreiten. China Unicom veröffentlicht die weltweit erste chinesische Llama3 8B-Version des Open-Source-Modells. Pinduoduo wird zur Entschädigung verurteilt 5 Millionen Yuan für unlauteren Wettbewerb. Inländische Cloud-Eingabemethode – nur Huawei hat keine Sicherheitsprobleme beim Hochladen von Cloud-Daten
{{o.name}}
{{m.name}}

Ich denke du magst

Origin my.oschina.net/u/4526289/blog/11062248
Empfohlen
Rangfolge