Traffic Safety-Kun: Erkennung von Verkehrszeichen in Python

Die Ausführungsumgebung für diesen Artikel ist kollaborativ.


** Dieses Mal ist das Ziel **

  1. Erkennen Sie diesmal das rote Licht, das grüne Licht, den Stopp und kein Eintrittsschild.
  2. Seien Sie vorsichtig mit der Stimme, wenn rotes Licht, Stopp oder keine Eingabe.

Schauen Sie sich zunächst das fertige Produkt an, das auf YouTube hochgeladen wurde. Verkehrssicherheitskun


Inhaltsverzeichnis

  1. Vorbereitung vorbereiten
  2. Verkehrszeichen Deep Learning
  3. Analysieren Sie das Video und erkennen Sie rotes Licht, Stopp und Bild ohne Eingabe
  4. Legen Sie Audio in den erkannten Frame

** 1, Vorbereitungen ** ① Nehmen Sie ein Video mit Ihrem Smartphone an einem Ort mit einem Verkehrszeichen auf. Der Effekt einer hohen Bildqualität ist gut. (1920 * 1080, 30 FPS in meinem Fall) ** Achten Sie beim Aufnehmen von Videos auf die Verkehrssicherheit! ** ** ** ② Erstellen Sie Warnstimmen für "Stopp", "Rotes Licht" und "Kein Eintrag". Ich habe es mit gTTS erstellt, natürlich können Sie Ihre eigene Stimme aufnehmen.

makeAudio_halt.ipynb


from gtts import gTTS #Google Text to Speech
from google import colab

#Mounten Sie Google Drive
colab.drive.mount('/content/gdrive')

path="gdrive/My Drive/make_video/"
word="Hör auf"
tts = gTTS(word,lang='ja') #Provide the string to convert to speech
tts.save(path+'STOP_2.wav') #save the string converted to speech as a .wav file
Audio(path+'STOP_2.wav') 

③ Bereiten Sie Bilder von Verkehrszeichen vor (rotes Licht, grünes Licht, Stopp, kein Eingang, blauer Himmel). (2, verwendet für Deep Learning von Verkehrszeichen)

Laden Sie Bilder von der Bildsuche von Google herunter.

python:1.getImage_STOP.ipynb


#Machen Sie ein Bild von einem Stopp
!apt-get update
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
!pip install selenium

import urllib.request as req
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
from selenium.webdriver.common.keys import Keys 

from google import colab
colab.drive.mount('/content/gdrive')

#Starten Sie den Browser im Headless-Modus und zeigen Sie die Website an
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver',options=options)
driver.implicitly_wait(10)

count=1
tempImageCount=0

#Angabe der Ziel-URL
driver.get("https://www.google.com/search?rlz=1C1CAFC_enJP862JP870&biw=1366&bih=657&tbm=isch&sxsrf=ACYBGNSNeQ5IaB9V8b-6pc6q9gOtbrY4Uw%3A1577968008026&sa=1&ei=iOENXoiRAfCSr7wP-8ee0As&q=%E6%AD%A2%E3%81%BE%E3%82%8C%E6%A8%99%E8%AD%98&oq=%E6%AD%A2%E3%81%BE%E3%82%8C%E6%A8%99%E8%AD%98&gs_l=img.3..0l2j0i24l8.144019.154252..155304...3.0..0.429.5395.0j1j5j10j1......0....1..gws-wiz-img.......0i4i37j35i39j0i23j0i4i37i24.zXhLgCDtIBY&ved=0ahUKEwiI9db09OTmAhVwyYsBHfujB7oQ4dUDCAc&uact=5")
time.sleep(3)

while True:
    #Bilderlistenerfassung
    image_list = driver.find_elements_by_class_name('rg_ic')
    print(len(image_list))
    
    #ScrollBar unten
    driver.find_element_by_tag_name('body').send_keys(Keys.END)

    if len(image_list) > tempImageCount:
        tempImageCount = len(image_list)
        print('------------------- go to next page --------------------------')
        try:
            #Schaltfläche "Weitere Ergebnisse anzeigen" anzeigen
            driver.find_element_by_id('smb').click()
            print('------------------- click success --------------------------')
        except:
            driver.find_element_by_tag_name('body').send_keys(Keys.END)
            print('------------------- KEY END --------------------------')
    else:
        break

#Bilderlistenerfassung
image_list = driver.find_elements_by_class_name('rg_ic')
print(len(image_list))
for image in image_list:
        #Bild-URL abrufen
        image_url = image.get_attribute('src')
        
        #Bild speichern
        try:
            image = req.urlopen(image_url).read()
            with open('gdrive/My Drive/image/Verkehrssicherheit/halt/'+str(count)+'.jpg',mode='wb') as f:
                f.write(image)
            print('download - {}'.format(count))
            count += 1
        except:
            print('cant open url')

driver.quit()

Wählen wir aus den aufgenommenen Bildern ein gutes aus. (So viele wie möglich, 20 oder mehr) Gutes Beispiel: (ohne Hintergrund) 2.jpg NG Beispiel: 205.jpg


** 2, Verkehrszeichen Deep Learning **

① Konvertieren Sie die Bilddatei in das Numpy-Format

Die Daten im Datensatz "MNIST" sind ein Array von (28,28), wie unten gezeigt. image.png Ändern Sie durch Imitieren von ↑ zunächst die Größe der Bilddatei auf ein Quadrat von 50 * 50 und konvertieren Sie sie dann in das Numpy-Format. Da es sich um einen RGB-Farbmodus handelt, handelt es sich um ein Array von (50,50,3).

to_Dat.ipynb


import cv2
import os
from sklearn.model_selection import train_test_split
from PIL import Image
import os,glob
import numpy as np

from google import colab
colab.drive.mount('/content/gdrive')
!ls 'gdrive/My Drive'

#Wählen Sie eine Klassifizierungskategorie
root_dir = 'gdrive/My Drive/image/Verkehrssicherheit-Kun 2/'
train_dir = 'gdrive/My Drive/data/'
groups = ['Grünes Licht','Einweg','halt','Kein Einlass','Rotlicht','blauer Himmel']
nb_classes = len(groups)
image_size = 50

#Konvertieren Sie Bilddaten in das Numpy-Format
#Lesen Sie die Bilddaten für jeden Ordner
X = []
Y = []
#Da es nur wenige Bilder gibt, lassen Sie sie das gleiche Bild 20 Mal studieren. Menschen erinnern sich immer wieder an Dinge. Ist Deeplearning dasselbe?
for i in range(0,20,1):
  for idx,group in enumerate(groups):
      image_dir = root_dir + group
      files = glob.glob(image_dir+'/*.jpg')
      for i,f in enumerate(files):
          img = Image.open(f)
          img = img.convert('RGB') #Wechseln Sie in den RGB-Modus
          img = img.resize((image_size,image_size))#50*Ändern Sie die Größe auf 50
          data = np.asarray(img)
          X.append(data)
          Y.append(idx)
X = np.array(X)
Y = np.array(Y)

X_train,X_test,y_train,y_test = train_test_split(X,Y,random_state=0)
xy = (X_train,X_test,y_train,y_test)
np.save('gdrive/My Drive/data/Verkehrssicherheit-Kun 2.npy', xy)
print(X_train.shape[1:])
print('ok',len(Y))

② Deeplearning mit neuronalen Netzen Unter der folgenden URL wird die Technik der "Faltung" vorgestellt. Was ist ein Faltungsnetzwerk? Die Vorgehensweise wird ebenfalls sorgfältig erklärt Nachdem Sie einen zweidimensionalen Filter auf die Bilddaten angewendet haben, wie in ↑ gezeigt, können Sie horizontale und vertikale Linien hervorheben, wodurch die Erfolgsrate erheblich verbessert werden kann.

deeplearning.ipynb


!pip install keras==2.2.4
import keras

from google import colab
colab.drive.mount('/content/gdrive')
!ls 'gdrive/My Drive'

import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils

#Lesen Sie die im Prozess gespeicherten Daten ①
x_train,x_test,y_train,y_test = np.load('gdrive/My Drive/data/Verkehrssicherheit-Kun 2.npy', mmap_mode=None, allow_pickle=True , fix_imports=True, encoding='ASCII')

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
num_classes = 10
y_train = np_utils.to_categorical(y_train, num_classes)
y_test = np_utils.to_categorical(y_test, num_classes)

#neurales Netzwerk
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import Adam
import time

model = Sequential()
model.add(Conv2D(50, (3, 3), 
          input_shape=(50, 50, 3), activation='relu'))       #Falten ①
model.add(Conv2D(32, (3, 3), activation='relu'))          #Falten ②
model.add(MaxPooling2D(pool_size=(2, 2)))                
model.add(Conv2D(64, (3, 3), activation='relu'))         ##Falten ③
model.add(MaxPooling2D(pool_size=(2, 2)))                
model.add(Dropout(0.25))                                 
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.25))                                 
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss='categorical_crossentropy',
              optimizer=Adam(),
              metrics=['accuracy'])

startTime = time.time()

history = model.fit(x_train, y_train, batch_size=3000, epochs=20,
                    verbose=1, validation_data=(x_test, y_test))

score = model.evaluate(x_test, y_test, verbose=0)
#loss
print('loss:', score[0])
#Erfolgsrate
print('accuracy:', score[1])
#Lernzeit
print("Computation time:{0:.3f} sec".format(time.time() - startTime))

#Speichern Sie das trainierte Modell
model.save('gdrive/My Drive/model/Verkehrssicherheit.h5')

Die Erfolgsquote beträgt 0,98, was ein gutes Gefühl ist. loss: 0.11440953898268777 accuracy: 0.9878378378378379 Computation time:46.734 sec


** 3, Video analysieren und rotes Licht erkennen, anhalten, Rahmen ohne Eintrag **

① Wie schneidet man das Bild des Schildes aus dem tatsächlichen Foto aus und identifiziert es mit dem trainierten Modell? 止まれ.jpg

Ich bezog mich auf Folgendes. [Python / OpenCV] Erkennung sich bewegender Objekte durch Farbverfolgung

Holen Sie sich den größten Blob.ipynb


#Blob-Analyse
def analysis_blob(binary_img):
    #Beschriftungsprozess für binäre Bilder
    label = cv2.connectedComponentsWithStats(binary_img)

    #Extrahieren Sie die Blob-Informationen Element für Element
    n = label[0] - 1
    data = np.delete(label[2], 0, 0)
    center = np.delete(label[3], 0, 0)
    if len(center) <= 0:
        return
    #Index mit dem größten Blob-Bereich
    max_index = np.argmax(data[:, 4])

    return center[max_index]

Vorhersagemethode.ipynb (Argumente sind Bilddatei und Koordinaten)


def predictWithModel(image_file, x_from, y_from, x_to, y_to):
    image_size = 50

    X1 = []
    #Trimmen
    img_crop = image_file[y_from : y_to, x_from: x_to]
    img_crop = cv2.cvtColor(img_crop, cv2.COLOR_BGR2RGB)
    img_crop = cv2.resize(img_crop, (image_size,image_size))#Bildgröße ändern
    
    X1.append(img_crop)#Bild als Vektor
    X1 = np.array(X1)

    x_test = X1.astype('float32')
    x_test /= 255

    y = model.predict(x_test)  #Prognose

    wk = y[0, :]
    wk_sort = np.sort(wk)
    wk_sort = wk_sort[::-1]
    max_indx = -1
    max_pcnt = -1
    if float(wk_sort[0]) > 0.9 and np.argmax(wk) != 5 and np.argmax(wk) != 0:
        max_pcnt = float(wk_sort[0])
        max_indx = np.argmax(wk)
        #print(max_indx)
        #print(max_pcnt)
    
    return max_indx, max_pcnt

Koordinatenanpassungsmethode.ipynb (rotes Licht ist rechteckig, Stopp und kein Eintrag ist quadratisch)


def adjustSize(height, width, center_x, center_y, div_size, div_size_w, kbn):
    if kbn == 1:
        #Rechteck
        x_from = center_x - div_size_w*3//4
        x_to = x_from + div_size_w
        y_from =  center_y - div_size//2
        y_to = y_from + div_size
    else:
        #Quadrat
        x_from = center_x - div_size//2
        x_to = x_from + div_size
        y_from =  center_y - div_size//2
        y_to = y_from + div_size

    if x_from < 0:
        x_from = 0
    if y_from < 0:
        y_from = 0
    if x_to >= width:
        x_to = width
    if y_to >= height:
        y_to = height
    
    return x_from, y_from, x_to, y_to

Bilddateianalyse.ipynb


def predictImage3(argimg):

    #Laden Sie das Bild.
    height, width, channels = argimg.shape[:3]

    #Bildausschnitt (Verkehrszeichen befindet sich in der oberen Hälfte, daher wird nur die obere Hälfte analysiert)
    img = argimg[0:height//2,0:width//2,::]
    #In HSV-Farbraum konvertieren.
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    #Extrahieren Sie den roten Rand durch Binarisierung.
    binary = cv2.inRange(hsv, (145, 70, 0), (180, 255, 255))
    if len(binary) <= 0:
        return argimg,-1

    #Schalten Sie das Geräusch mit OPENING aus.
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    eroded = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)

    #Blob-Analyse des Maskenbildes (Erhalten von Blob-Informationen der maximalen Fläche)
    center = analysis_blob(eroded)
    if center is None:
        return argimg,-1

    #Holen Sie sich die Mittelkoordinaten
    center_x = int(center[0])
    center_y = int(center[1])

    #Erstes rechteckig
    x_from, y_from, x_to, y_to = adjustSize(height, width, center_x, center_y, 60, 100, 1)
    max_indx, max_pcnt = predictWithModel(img, x_from, y_from, x_to, y_to)

    #Forschungsplatz
    x_from2, y_from2, x_to2, y_to2 = adjustSize(height, width, center_x, center_y, 50, 100, 0)    max_indx2, max_pcnt2 = predictWithModel(img, x_from2, y_from2, x_to2, y_to2)

    #Rechteck 2 (Größe anpassen)
    x_from3, y_from3, x_to3, y_to3 = adjustSize(height, width, center_x, center_y, 40, 80, 1)
    max_indx3, max_pcnt3 = predictWithModel(img, x_from3, y_from3, x_to3, y_to3)

    pcnt = [max_pcnt, max_pcnt2, max_pcnt3]
    indx = [max_indx, max_indx2, max_indx3]
    max = np.argmax(pcnt)

    max_index = -1

    if indx[max] == 2:
        text="halt"
    elif indx[max] == 4:
        text="Rotlicht"
    elif indx[max] == 3:
        text="Kein Einlass"
    else:
        text=""

    if indx[max] > 0:
        #Zeichnen Sie einen Kreis um die Mitte des maximalen Blobs auf dem Rahmen
        cv2.circle(argimg, (center_x, center_y), 80, (0, 200, 0),thickness=3, lineType=cv2.LINE_AA)
        fontpath ='gdrive/My Drive/font/MSMINCHO.TTC' #Schriftart
        font = ImageFont.truetype(fontpath, 128) #Schriftgröße
        img_pil = Image.fromarray(argimg) #8bit jeder Wert des Arrays(1byte)Ganzzahliger Typ(0~255)Zum PIL-Bild.

        draw = ImageDraw.Draw(img_pil) #Zeichnungsinstanz erstellen

        position = (center_x, center_y + 100) #Position der Textanzeige
        draw.text(position, text, font = font , fill = (0,0,255,0) ) #Schreiben Sie Text in Draw Fill:Farbe BGRA(RGB)
        max_index = indx[max]
        return np.array(img_pil),max_index #PIL in Array konvertieren
    
    return argimg,max_index

Analysieren Sie nach der Vorbereitung der obigen Methode das vorbereitete Video

Video analysieren.ipynb


import cv2
from google.colab.patches import cv2_imshow
from PIL import ImageFont, ImageDraw, Image

target_dir = 'gdrive/My Drive/target/Verkehrssicherheit-Kun 2/'
files = glob.glob(target_dir+'/src_*.mp4')

target_avi_file = target_dir + "output.avi"
output_file = target_dir + "output.mp4"
#Erstellen Sie einen VideoWriter.
fourcc = cv2.VideoWriter_fourcc(*"DIVX")
writer = cv2.VideoWriter(target_avi_file, fourcc, 30, (1920, 1080))
    
frame_cnt=0

fame_index_result=np.empty((0,2), int)

for i,f in enumerate(files):
    #Erstellen Sie eine VideoCapture.
    cap = cv2.VideoCapture(f)
    temp=np.empty((0,2), int)

    while True:
        #Holen Sie sich Frame für Frame.
        ret, frame = cap.read()
        if not ret:
            break  #Wenn die Bildaufnahme fehlschlägt oder das Ende des Videos erreicht ist
        frame_cnt+=1

        frame,index = predictImage3(frame)
 
        if index > 0:
            temp = np.append(temp, np.array([[frame_cnt,index]]), axis=0)
        writer.write(frame)  #Schreiben Sie einen Rahmen.

    #Verkehrszeichen Zeichnen Sie den ersten erkannten Frame auf (= Zeitpunkt zum Einfügen der Stimme)
    index_cnt = [np.count_nonzero(temp[:,1] == 2),np.count_nonzero(temp[:,1] == 3),np.count_nonzero(temp[:,1] == 4)]
    max_index = [2,3,4][np.argmax(index_cnt)]
    fame_index_result = np.append(fame_index_result, np.array([(temp[temp[:,1] == max_index])[0]]), axis=0)

writer.release()
cap.release()

** 4, Audio in den erkannten Frame einfügen **

Audio hinzufügen.ipynb


!pip -q install pydub
!apt install libasound2-dev portaudio19-dev libportaudio2 libportaudiocpp0 ffmpeg
!pip install pyaudio
import cv2
import pyaudio
import sys
import time
import wave
import pydub
from pydub import AudioSegment
import moviepy.editor as mp
import datetime

temp_file = target_dir + "temp.mp4"

# Add audio to output video.
clip_output = mp.VideoFileClip(target_avi_file).subclip()
clip_output.write_videofile(temp_file, audio=mp3_file)

cap = cv2.VideoCapture(target_avi_file)
video_frame = cap.get(cv2.CAP_PROP_FRAME_COUNT) #Holen Sie sich die Anzahl der Frames
video_fps = cap.get(cv2.CAP_PROP_FPS)           #Holen Sie sich FPS
video_len_sec = video_frame / video_fps         #Länge berechnen (Sekunden)
print(video_len_sec)
video = mp.VideoFileClip(temp_file).subclip(0,video_len_sec)
video.write_videofile(output_file)

mp3_stop_file_2="gdrive/My Drive/mp3/stop_2.wav"
mp3_stop_file_3="gdrive/My Drive/mp3/stop_3.wav"
mp3_stop_file_4="gdrive/My Drive/mp3/stop_4.wav"
videos = np.empty((0), mp.VideoFileClip)

startSec=0
temp_file2 = target_dir + "temp2.mp4"

#Fügen Sie für jeden Verkehrszeichenrahmen eine Stimme ein
for idx in range(fame_index_result.shape[0]):

    if  fame_index_result[idx][1] == 2:
        mp3_stop_file = mp3_stop_file_2
    elif  fame_index_result[idx][1] == 3:
        mp3_stop_file = mp3_stop_file_3
    elif  fame_index_result[idx][1] == 4:
        mp3_stop_file = mp3_stop_file_4
    
    base_sound = AudioSegment.from_file(mp3_stop_file)
    length_seconds = base_sound.duration_seconds  #Überprüfen Sie die Länge der Stimme

    #Schneiden Sie zuerst von 0 bis zum Rahmen des Verkehrszeichens aus
    video_len_sec_temp = fame_index_result[idx][0] / video_fps
    videos = np.append(videos, np.array([mp.VideoFileClip(temp_file).subclip(startSec,video_len_sec_temp)]), axis=0)

    #Passen Sie die Länge des Audios an, schneiden Sie ein Video mit der gleichen Länge aus und fügen Sie das Audio ein
    clip_output = mp.VideoFileClip(temp_file).subclip(video_len_sec_temp, video_len_sec_temp+length_seconds)
    clip_output.write_videofile(temp_file2, audio=mp3_stop_file)
    
    #Verbleibendes Video
    videos = np.append(videos, np.array([mp.VideoFileClip(temp_file2).subclip()]), axis=0)
    if idx == fame_index_result.shape[0] - 1:
        last_sec =  video_len_sec
    else:
        last_sec = fame_index_result[idx+1][0] / video_fps
    if video_len_sec_temp+length_seconds < last_sec:
        videos = np.append(videos, np.array([mp.VideoFileClip(temp_file).subclip(video_len_sec_temp+length_seconds, last_sec)]), axis=0)
    startSec = last_sec

#Verkettete Videos verketten
final_clip = mp.concatenate_videoclips(videos)
final_clip.write_videofile(output_file)

Recommended Posts

Traffic Safety-Kun: Erkennung von Verkehrszeichen in Python
Spracherkennung mit Python
Objektäquivalenzbeurteilung in Python
Implementierung der schnellen Sortierung in Python
Zahlenerkennung in Bildern mit Python
Bildpixel-Manipulation in Python
Zeitdelta in Python 2.7-Serie teilen
Umgang mit JSON-Dateien in Python
Implementierung eines Lebensspiels in Python
Audio-Wellenform-Anzeige in Python
Das Gesetz der Zahlen in Python
Implementierung der ursprünglichen Sortierung in Python
Reversibles Verwürfeln von Ganzzahlen in Python
Handschriftliche Zeichenerkennung mit KNN in Python
Python: Grundlagen der Bilderkennung mit CNN
Konvertierung der Zeichenfolge <-> Datum (Datum, Datum / Uhrzeit) in Python
Überprüfen Sie das Verhalten des Zerstörers in Python
Übung, dies in Python zu verwenden (schlecht)
Allgemeine Relativitätstheorie in Python: Einführung
Ausgabebaumstruktur von Dateien in Python
Zeigen Sie eine Liste der Alphabete in Python 3 an
Vergleich japanischer Konvertierungsmodule in Python3
Python: Anwendung der Bilderkennung mit CNN
Einfache Einführung der Spracherkennung mit Python
Das Ergebnis der Installation von Python auf Anaconda
Gang of Four (GoF) -Muster in Python
Grundlagen zum Ausführen von NoxPlayer in Python
Massenersatz von Zeichenfolgen in Python-Arrays
Projekt Euler # 16 "Summe der Kräfte" in Python
Zusammenfassung der integrierten Methoden usw. der Python-Liste
Nicht logische Operatorverwendung von oder in Python
Auf der Suche nach dem schnellsten FizzBuzz in Python
Praktisches Beispiel für hexagonale Architektur in Python
Projekt Euler # 17 "Anzahl der Zeichen" in Python
Doppelte Pendelbewegungsgleichung in Python
Entfernen Sie DICOM-Bilder in Python
Status jedes Python-Verarbeitungssystems im Jahr 2020
Projekt Euler # 1 "Vielfaches von 3 und 5" in Python
Szenenerkennung nach GIST-Feature-Quantität in Python
Quadtree in Python --2
Python in der Optimierung
Geben Sie die Anzahl der CPU-Kerne in Python aus
Metaprogrammierung mit Python
Zeichnen Sie in Python ein Diagramm einer quadratischen Funktion
Python 3.3 mit Anaconda
Geokodierung in Python
SendKeys in Python
[Python] Sortieren Sie die Liste von pathlib.Path in natürlicher Reihenfolge
Erhalten Sie einen Websocket der kabu station ® API in Python
Metaanalyse in Python
Unittest in Python
Projekt Euler # 10 "Summe der Primzahlen" in Python
Unbeaufsichtigter Betrieb von Google Spreadsheets (usw.) in Python
Holen Sie sich den Aufrufer einer Funktion in Python
Passen Sie die Verteilung jeder Gruppe in Python an
Zeigen Sie das Ergebnis der Geometrieverarbeitung in Python an
Lernen der Mustererkennung im Video Teil 1 Bereich der Mustererkennung
Epoche in Python
Zwietracht in Python