schwankende Werte bei Videoerstellung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Huhu und zwar stehe ich gerade etwas auf dem Schlauch vlt. kann mir ja jmd einen Denkanstoß geben :D
Ich tracke in einem Video eine Person und schneide diesen Bereich allerdings schwanken diese Werte was es natürlich verhindert daraus ein Video zu erstellen wie könnte ich diese schwankenden Werte umgehen ? So das um die Person immer eine feste Box quasi ist um daraus ein Video erstellen zu können?

Code: Alles auswählen

for frame in reader.nextFrame():
                gmask = fgbg.apply(frame)
                is_ok, track_window = cv2.meanShift(gmask, track_window, term_crit)

                r, h, c, w = track_window
                k1 = round(w)
                print(k1)
                k2 = round(c+w+60)
                print(k2)
                l1 = round(r)
                print(l1)
                l2 = round(r+h+60)
                print(l2)
                speaker_out.writeFrame(frame[k1:k2, l1:l2])
Werte-Ausschnitt:
174
460
400
640
174
460
400
640
174
460
400
640
174
460
301
541
174
460
324
535

MfG Felix
__deets__
User
Beiträge: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

Pro-Tipp: wenn du in einer Schleife mehrere print-statements hast, ist es von grossem Vorteil, nicht nur den Wert auszugeben, sondern auch WAS dieser Wert ist. Also k1, k2, l1, l2. Oder sogar Bezeichner, die etwas bedeuten. Denn so sehe ich eine Reihe von ganz vielen Zahlen und habe keine Ahnung, was was ist.

Und wenn du eine feste Box willst, dann mach doch eine feste Box. Was hindert dich daran? Du musst doch nur den Ort kennen, an dem die Person steht. Niemand zwingt dich, das umschreibende Rechteck unveraendert zu nutzen. Wenn Breite und Hoehe fest sind, zentrierst du halt.
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Felix92: Was meinst Du mit schwankenden Werten? `track_window` sollte doch eine feste Box sein‽
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
__deets__
User
Beiträge: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

@blackjack: man sieht schwankende Werte. Ich kann nur spekulieren, dass das zB der Bildschirmrand ist, kann aber auch genauso eine Seitenansicht der Person vs. Frontal sein (hab meanshift gerade nicht mehr im Kopf).
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@__deets__: Meanshift verschiebt laut Tutorial nur eine gegebene Box und hat das Problem, das die immer gleich gross bleibt, auch wenn das Auto näher kommt und damit grösser wird. Dieses Problem wird im Tutorial dann im nächsten Schritt mit Camshift gelöst.

@Felix92: Ergänzend zum Tipp von __deets__ bezüglich der Ausgabe: Es würde sicher auch schon helfen wenn man die Werte nicht alle untereinander ausgibt wenn jeweils vier davon zusammengehören. Man muss sich so ja jeden vierten Wert beim vergleichen anschauen, und ich finde das erfordert mehr Konzentration als ich bereit bin aufzubringen, wenn ich daran denke das man die wesentlich leichter vergleichen kann wenn die sinnvoller formatiert ausgegeben werden.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

ja sry da gebe ich dir recht ^^

Code: Alles auswählen

if is_ok == True:
            #hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
            #dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
            gmask = fgbg.apply(frame)
            is_ok, track_window = cv2.meanShift(gmask, track_window, term_crit)

            r, h, c, w = track_window
            
     
            img2 = cv2.rectangle(frame, track_window, 255, 2)
            print(track_window)
r h c w
(400, 180, 226, 174)
(400, 180, 226, 174)
(345, 118, 226, 174)
(326, 152, 226, 174)
(327, 155, 226, 174)
(333, 149, 226, 174)
(332, 151, 226, 174)
(334, 149, 226, 174)
(335, 151, 226, 174)
(335, 154, 226, 174)
(336, 159, 226, 174)
(337, 164, 226, 174)
(337, 165, 226, 174)


Das sind die Werte die mir track_window liefert

frame[w:c+w, r:r+h]
1 Frame : 174:400, 400:580
3 Frame : 174:400, 118:463
das wäre das Fenster welches ich "ausschneiden möchte

PS: die Werte verändern sich im Verlauf des Videos alle und mein Problem ist halt quasi eine feste Box daraus zu machen die "mitläuft" damit ich das Video schneiden kann
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Felix92: Ich sehe da keine schwankenden Werte aber Du machst komische Sachen mit den komisch benannten Werten. Was sollen denn die Namen ``r, h, c, w`` bedeuten? Mach da mal ``x, y, width, height`` draus und überlege ob Deine Rechnungen richtig sind/Sinn machen. Die Box ist bei Dir immer 226 Pixel breit und 174 Pixel hoch. Die Position ändert sich natürlich weil das getrackte Objekt und/oder die Kamera sich bewegen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Und genau da liegt mein Problem
bei dem schwankenden x und y Wert ich muss ja an (x,y) ansetzen und dann die Roi "zeichen" natürlich kommen dabei unterschiedliche Werte raus :/

Code: Alles auswählen

x, y, width, height = track_window

speaker_out.writeFrame(frame[x:x+width, y:y+height]) 
__deets__
User
Beiträge: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich verstehe dein Problem nicht. Wenn du etwas tracken willst, und das haette immer die gleichen x/y-Koordinaten, dann musst du doch nichts tracken. Und das was du da zeigst liefert dir doch einen immer gleich grossen Ausschnitt. Ok, du mast fuer mein dafuerhalten x und y im Frame vertauscht, denn bei Matritzen/numpy-arrays ist die erste Achse ja die y-Achse/Zeilen. Und wenn du in die Randbereiche kommst, dann verkleinert sich der Auschschnitt natuerlich, dagegen muss man was tun. Ist das dein Problem?
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

ich habe es gerade nochmal getestet genau dass ist das Problem :/

Hier mal der komplette Code:
(Ist nur zum testen erstmal)

import cv2
import numpy as np
import time
import skvideo.io

Code: Alles auswählen

def main():
    video_data = "/home/felix/Schreibtisch/Testvideos/splitted_video/board_7637.mp4"
    cap = cv2.VideoCapture(str(video_data))
    reader = skvideo.io.FFmpegReader(video_data, {}, {})
    #fgbg = cv2.createBackgroundSubtractorMOG2()
    fgbg = cv2.bgsegm.createBackgroundSubtractorMOG()

    is_ok, frame = cap.read()

    x, y, width, height = 180, 400, 400, 550
    track_window = (width,x,height,y)
    print(track_window)
    videometadata = skvideo.io.ffprobe(video_data)
    frame_rate = videometadata['video']['@avg_frame_rate']

    term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 5 , 1)

    speaker_out = skvideo.io.FFmpegWriter("speaker.mp4", inputdict={
            "-r": frame_rate
        })

    while True:
        is_ok, frame = cap.read()

        if is_ok == True:
        
            gmask = fgbg.apply(frame)
            is_ok, track_window = cv2.meanShift(gmask, track_window, term_crit)

            
     
            img2 = cv2.rectangle(frame, track_window, 255, 2)

            #for frame in reader.nextFrame():
            #    gmask = fgbg.apply(frame)
            #    is_ok, track_window = cv2.meanShift(gmask, track_window, term_crit)

            #    x, y, width, height = track_window
            #    print(track_window)
            #    print(x)
            #    print(y)
            #    print(width)
            #    print(height)

            #    speaker_out.writeFrame(frame[x:x+width, y:y+height]) 
            
            cv2.imshow('roi2', gmask)
            
            cv2.imshow('roi3', img2)

            k = cv2.waitKey(60) & 0xff
            if k == 27:
                break
            
        else:
            break

    cap.release()
    out.release()


if __name__== "__main__":
  main()
__deets__
User
Beiträge: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

Aber dann musst du doch einfach nur feststellen, an welcher Stelle die Bereichsueberschreitung erfolgt, und ein entsprechendes padding des Arrays machen. Also indem du dir zB einen schwarzen Frame mit den richtigen Dimensionen erzeugst, und deinen extrahierten Frame entsprechen darin plazierst.
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Anscheind liegt es eher daran das track_window nicht den Bereich innerhalb des Rechtecks beinhaltet sondern irgend etwas anderes weil wenn ich mir diesen anzeigen lasse wird mir nur ein weißes Fenster angezeigt das ganze Video lang.
Das Rechteck macht allerdings das was es soll und verfolgt die Person.
Gibt es eine simple Möglichkeit den Bereich innerhalb des Rechtecks auszuschneiden ?
__deets__
User
Beiträge: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ja, so wie du es doch oben selbst zeigst. Du hast x, y, breite, hoehe, und daraus kannst du aus einem numpy-array den entsprechenden Bereich ausschneiden. Das ist wieder ein numpy-array, und das kannst du mit imshow anzeigen.
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Naja aber img2 beinhaltet ja den kompletten Frame und nicht nur das Rechteck samt "Inhalt" !?
Und ich müsste ja irgendwie das Rechteck ausschneiden egal an welche Position es "wandert"
__deets__
User
Beiträge: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich weiss nicht, was da genau wo ist, weil ich deinen Code so sehr gar nicht nachvollziehen will. Der Punkt ist: ein OpenCV-Frame ist ein numpy-Array. Und die Frage, wie man aus einem numpy-Array einen Teilausschnitt erhaelt, ist wirklich in jedem Grundlagentutorial zu sehen, und auch von dir selbst oben in Code beschrieben worden: array[a:a+b,c:c+d]. Was daran ist dir unklar?
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Ok ich probiere es nochmal :)

Ich habe ein Video in welchem sich eine Person bewegt diese wird durch

Code: Alles auswählen

is_ok, track_window = cv2.meanShift(gmask, track_window, term_crit)
img2 = cv2.rectangle(frame, track_window, 255, 0)
getrackt wobei track_window das Fenster in dem Rechteck ist (dachte ich zumindest)
Allerdings scheint genau dort der Fehler zu liegen siehe Bilder(Fenster track_window):

Bild
Bild
Bild

Ich möchte nun den Inhalt aus dem Rechteck als extra Video speichern/schreiben einen festen Wert in der ROI kann ich nicht nutzen da das Rechteck ja von Frame zu Frame unterschiedlich positioniert ist und die Werte variieren. x, y, width, height = track_window liefert mir die richtigen Werte (vermutlich) wenn ich dann allerdings schreibe cv2.imshow('test', frame[x:x+width, y:y+height) bekomme ich nur einen Fehler:

Code: Alles auswählen

File "track_person.py", line 72, in main
    cv2.imshow('test', frame[x:x+width, y:y+height])
cv2.error: OpenCV(4.1.0) /io/opencv/modules/highgui/src/window.cpp:352: error: (-215:Assertion failed) size.width>0 && size.height>0 in function 'imshow'
(Das Rechteck geht nicht aus dem Frame)

Nun weiß ich nicht so recht wie ich dieses Problem lösen soll da ich absolut nicht verstehe weshalb das Rechteck korrekt angezeigt wird und ich es über die Werte

Code: Alles auswählen

x, y, width, height = 220, 400, 400, 650
track_window = (width,x,height,y)
auch verändern kann aber halt diesen Bereich nicht aus dem Frame schneiden kann.....meine Idee war aus

Code: Alles auswählen

img2 = cv2.rectangle(frame, track_window, 255, 0)
print(img2)
die x, y,width , height Werte des Rechtecks zu ermitteln um damit dann den Bereich abzugrenzen allerdings wird das Rechteck ja nur eingezeichnet und print(img2) liefert mir das numpy array des kompletten Frames.
Ich hoffe mein Problem ist jetzt etwas verständlicher und sry für den grauenvollen Testcode ^^
MfG Felix
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Matrizen werden frame[zeilen, spalten] referenziert.
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Kannst du vlt ein wenig genauer erklären wo mir das an der Stelle weiterhelfen soll ? :)
Danke
Benutzeravatar
Felix92
User
Beiträge: 133
Registriert: Mittwoch 7. November 2018, 17:57

Also ja ich könnte vermutlich das ganze img2 ablaufen jedes mal und nach den Pixeln des Rechtecks suchen aber das muss doch auch einfacher gehen
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Naja, Du hast Zeilen und Spalten vertauscht.
Antworten