Huhu,
gibt es eine Möglichkeit aus einem Video jeden Frame auszulesen ob er grüner, blauer oder roter ist ?
Also quasi wenn Frame mehr grüne Anteile als blaue oder rote hat dann do ...
Meine Idee:
green =100 * channel[1] / (channel[0] + channel[1] + channel[2])
if green > 50:
do...
Oder gibt es da vlt. sogar schon eine Methode welche mir den prozentualen Anteil (RGB) aus einem Frame zurück gibt ?
In der docu bin ich leider nicht fündig geworden.
MfG Felix
OpenCV Frame Farbanteile (channels)
Naja ich hab ein Video wo manchmal auf die "Schultafel" gezoomt wird dementsprechend höherer grün Anteil wenn das der Fall ist soll halt etwas anderes passieren als wenn nicht auf die Tafel gezoomt wird bzw wenn Tafel wird mit openshot ein Clip über die Zeit wo er an der Tafel ist erstellt und wenn das nicht der Fall ist passiert nichts. Dient quasi dazu um ein Video zu analysieren.
wie wäre es mit der Berechnung und Vergleich des mean() über den jeweiligen RGB-Channel?
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Ich würde das so nicht machen. Für Betrachtungen von Farben würde ich in HSV wechseln, und dann mit der passenden Farbe in einem gewissen Bereich filtern. Der entstehende Blob wird dann per kontour extraction ausgemessen in seiner Größe.
Arbeiten auf den RGB-Werten zur Farbbeurteilung ist nahezu nie erfolgreich, weil der Farbraum schlecht Distanzen zu anderen Farben berechenbar macht.
Arbeiten auf den RGB-Werten zur Farbbeurteilung ist nahezu nie erfolgreich, weil der Farbraum schlecht Distanzen zu anderen Farben berechenbar macht.
Huhu deets,
das ganze Problem dabei ist das relativ häufig und umständlich gezoomt wird weshalb es nicht möglich ist einen festen Bereich zu setzen.
(Das hatte ich davor hat auch super geklappt bis ich dann erfahren habe das dort auch gezoomt wird
)
Also so wie ich es jetzt habe klappt es (auch mit zoom) bin natürlich gerne offen für Vorschläge und alternative Ideen.
das ganze Problem dabei ist das relativ häufig und umständlich gezoomt wird weshalb es nicht möglich ist einen festen Bereich zu setzen.
(Das hatte ich davor hat auch super geklappt bis ich dann erfahren habe das dort auch gezoomt wird

Also so wie ich es jetzt habe klappt es (auch mit zoom) bin natürlich gerne offen für Vorschläge und alternative Ideen.

Nun habe ich allerdings gemerkt das nen 90min Video beim "einlesen" echt ewig braucht gibt es dort einen simpleren Weg als das Video in einem Thread "vorzuladen" ?
Nur jeden 2ten Frame oder ähnliches zu nehmen ist leider keine Alternative.
Nur jeden 2ten Frame oder ähnliches zu nehmen ist leider keine Alternative.
Ok ich habe dazu gerade etwas gefunden allerdings verstehe ich von dem ffmpeg Ausdruck fast nichts :/
import subprocess
c = 'ffmpeg -y -i ' + video_input_path + ' -r 30 -s 112x112 -c:v libx264 -b:v 3M -strict -2 -movflags faststart '+video_output_path
subprocess.call(c, shell=True)
Könnte mir dazu vlt. jemand kurz erklären wie ich diese ffmpeg Ausdrücke zu handhaben habe
Letztendlich möchte ich ja nur die fps eines Videos welches ich schon eingelesen habe erhöhen Standard sind 21fps ich würde diese wenn möglich gerne auf 500-1000 fps drücken oder noch höher wenn möglich ohne Verluste.
Danke für eure Antworten
MfG Felix
import subprocess
c = 'ffmpeg -y -i ' + video_input_path + ' -r 30 -s 112x112 -c:v libx264 -b:v 3M -strict -2 -movflags faststart '+video_output_path
subprocess.call(c, shell=True)
Könnte mir dazu vlt. jemand kurz erklären wie ich diese ffmpeg Ausdrücke zu handhaben habe

Letztendlich möchte ich ja nur die fps eines Videos welches ich schon eingelesen habe erhöhen Standard sind 21fps ich würde diese wenn möglich gerne auf 500-1000 fps drücken oder noch höher wenn möglich ohne Verluste.
Danke für eure Antworten

MfG Felix
@Felix92: Du hast also ein Programm, das wir nicht kennen, das zu lange für die Analyse eines Videos braucht. Dann hast Du entweder ein Problem, das lange braucht, oder einen ungeeigneten Algorithmus benutzt, oder diesen ganz einfach ineffizient programmiert.
Da hilft ein schnellerer Rechner, oder in den zwei letzten Fällen, geschickter Programmieren.
Da hilft ein schnellerer Rechner, oder in den zwei letzten Fällen, geschickter Programmieren.
Also hier mal wie ich das Video "erstelle":
Und die Analyse:
In der zweiten Methode würde ich das Video gerne wesentlich schneller "abarbeiten"
Code: Alles auswählen
def large_video_cut(self, fps):
"""
a method to get the part of the speaker from the "main video" and save it in the project folder
and create a object of this
"""
video_file = self.video_data
folder = Path(self.folder_path, self.folder_name)
cap = cv2.VideoCapture(str(video_file))
large_video_name = 'board_video.mp4'
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(os.path.join(folder,str(large_video_name)), fourcc , fps, (938, 530))
if(cap.isOpened() == False):
print("Error opening video stream or file")
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
frame = frame[275:805, 17:955]
out.write(frame)
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
new_large_video_path = Path(folder, large_video_name)
self.files.append(new_large_video_path)
return BoardVideo(out)
Code: Alles auswählen
def board_area(self, clip_prefix):
"""
a method that analyse the video frame per frame and save the Clips (Board) in a list
"""
video = cv2.VideoCapture(str(self.file_path))
try:
times = list()
clip_numbers = count()
for frame_number in count():
is_ok, frame = video.read()
if not is_ok:
break
average = cv2.mean(frame)
sum = average[0] + average[1] + average[2]
percentage_green = (100 * average[1]) / sum
if percentage_green > 40:
times.append(video.get(cv2.CAP_PROP_POS_MSEC) / 1000)
else:
if times:
clip = openshot.Clip(
'{}{}'.format(clip_prefix, next(clip_numbers))
)
clip.Start(times[0])
clip.End(times[-1])
self.subvideos.append(clip)
times.clear()
finally:
video.release()
cv2.destroyAllWindows()
- __blackjack__
- User
- Beiträge: 14044
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Felix92: Bezüglich des `ffmpeg`-Aufrufs: Das ``shell=True`` sollte man nicht verwenden, sondern den Befehl und die Argumente als Liste übergeben:
`video_data` ist kein guter Name für einen Dateinamen/Pfad – da erwartet man die Videodaten selbst oder Daten über ein Video. Und das Attribut dann lokal an einen anderen Namen zu binden ist auch nicht schön. Zumal `video_file` auch etwas verwirrend ist, denn um ein Dateiobjekt handelt es sich ja auch nicht.
Der Zieldateiname in `large_video_cut()` – was eher `cut_large_video()` heissen sollte – wird über die Methode verteilt und zwei mal auf unterschiedliche Arten erstellt. Das sollte nur *einmal* passieren und entweder mit `Path` oder mit `os.path.join()`.
Weder ``if`` noch ``while`` sind Funktionen, also sollte man die auch nicht so schreiben als wären es welche. Die Klammern gehören da nicht hin.
Vergleiche mit literalen Wahrheitswerten macht man nicht. Da kommt nur wieder ein Wahrheitswert heraus, also kann man auch gleich den Wert nehmen mit dem man vergleicht oder mit dessen Negation mit ``not``. Bei `isOpened()` machst Du das ja auch schon einmal richtig. Warum diese Inkonsistenz?
Der Test ob `cap` geöffnet werden konnte, sollte eigentlich stattfinden bevor man mit allem weiteren weiter macht und vor allem auch verhindern das weiter gemacht wird, wenn das Öffnen fehlgeschlagen ist. Die `release()`-Aufrufe sollten durch ``try``:``finally`` sichergestellt werden. Und bei `VideoWriter` prüfst Du gar nicht, ob der funktioniert oder nicht.
Der ``return``-Wert sieht unsinnig aus: Ein `BoardVideo`-Objekt das einen geschlossenes `VideoWriter`-Objekt übergeben bekommt? Was soll denn damit noch angefangen werden?
Zwischenstand (ungetestet):
`board_area()` ist kein guter Name für eine Funktion oder Methode. Solche Namen sollten die Tätigkeit beschreiben und `board_area` beschreibt keine Tätigkeit.
Du machst IMHO zu viel kopieren und einfügen. Hier ist jetzt ein `frame_number` was nicht benötigt wird, was nur da ist, weil diese Methode eine Kopie eines bereits vorhandenen Versuchs ist.
`sum` ist der Name einer eingebauten Funktion, den sollte man nicht an etwas anderes binden. Die Funktion kann man hier sogar verwenden!
Auch in dieser Methode wird nicht sinnvoll darauf reagiert wenn die Videodatei nicht geöffnet werden konnte.
Zwischenstand:
Ich sehe nicht wo diese Methode Zeit vertrödelt. Wenn die zu langsam ist, dann ist das halt so langsam. Sollte es tatsächlich an Python liegen, müsstest Du es in C++ umschreiben. Sowohl OpenCV als auch OpenShot haben da ja eine entsprechende API.
Code: Alles auswählen
command = [
'ffmpeg',
'-y',
'-i', video_input_path,
'-r', '30',
'-s', '112x112',
'-c:v', 'libx264',
'-b:v', '3M',
'-strict', '-2',
'-movflags', 'faststart',
video_output_path,
]
subprocess.run(command)
Der Zieldateiname in `large_video_cut()` – was eher `cut_large_video()` heissen sollte – wird über die Methode verteilt und zwei mal auf unterschiedliche Arten erstellt. Das sollte nur *einmal* passieren und entweder mit `Path` oder mit `os.path.join()`.
Weder ``if`` noch ``while`` sind Funktionen, also sollte man die auch nicht so schreiben als wären es welche. Die Klammern gehören da nicht hin.
Vergleiche mit literalen Wahrheitswerten macht man nicht. Da kommt nur wieder ein Wahrheitswert heraus, also kann man auch gleich den Wert nehmen mit dem man vergleicht oder mit dessen Negation mit ``not``. Bei `isOpened()` machst Du das ja auch schon einmal richtig. Warum diese Inkonsistenz?
Der Test ob `cap` geöffnet werden konnte, sollte eigentlich stattfinden bevor man mit allem weiteren weiter macht und vor allem auch verhindern das weiter gemacht wird, wenn das Öffnen fehlgeschlagen ist. Die `release()`-Aufrufe sollten durch ``try``:``finally`` sichergestellt werden. Und bei `VideoWriter` prüfst Du gar nicht, ob der funktioniert oder nicht.
Der ``return``-Wert sieht unsinnig aus: Ein `BoardVideo`-Objekt das einen geschlossenes `VideoWriter`-Objekt übergeben bekommt? Was soll denn damit noch angefangen werden?
Zwischenstand (ungetestet):
Code: Alles auswählen
def cut_large_video(self, fps):
"""Get the part of the speaker from the "main video" and save it in the
project folder and create an object of this.
"""
capture = cv2.VideoCapture(str(self.video_data))
try:
if not capture.isOpened():
raise RuntimeError('Error opening video stream or file')
new_filename = Path(
self.folder_path, self.folder_name, 'board_video.mp4'
)
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
writer = cv2.VideoWriter(str(new_filename), fourcc, fps, (938, 530))
try:
if not writer.isOpened():
raise RuntimeError('Error opening video stream or file')
while True:
is_ok, frame = capture.read()
if not is_ok:
break
writer.write(frame[275:805, 17:955])
finally:
writer.release()
self.files.append(new_filename)
#
# TODO Passing a closed `VideoWriter` object looks wrong‽
#
return BoardVideo(writer)
finally:
capture.release()
cv2.destroyAllWindows()
Du machst IMHO zu viel kopieren und einfügen. Hier ist jetzt ein `frame_number` was nicht benötigt wird, was nur da ist, weil diese Methode eine Kopie eines bereits vorhandenen Versuchs ist.
`sum` ist der Name einer eingebauten Funktion, den sollte man nicht an etwas anderes binden. Die Funktion kann man hier sogar verwenden!
Auch in dieser Methode wird nicht sinnvoll darauf reagiert wenn die Videodatei nicht geöffnet werden konnte.
Zwischenstand:
Code: Alles auswählen
#
# TODO Come up with a better method name.
#
def board_area(self, clip_prefix):
"""Analyse the video frame by frame and save the Clips (Board) in a
list.
"""
video = cv2.VideoCapture(str(self.file_path))
try:
if not video.isOpened():
raise RuntimeError('Error opening video stream or file')
times = list()
clip_numbers = count()
while True:
is_ok, frame = video.read()
if not is_ok:
break
average = cv2.mean(frame)
percentage_green = 100 * average[1] / sum(average)
if percentage_green > 40:
times.append(video.get(cv2.CAP_PROP_POS_MSEC) / 1000)
else:
if times:
clip = openshot.Clip(
'{}{}'.format(clip_prefix, next(clip_numbers))
)
clip.Start(times[0])
clip.End(times[-1])
self.subvideos.append(clip)
times.clear()
finally:
video.release()
cv2.destroyAllWindows()
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Huhu vielen Dank für deine Antwort 
Das Problem war das die Daten nicht weiter verwendet wurden bis dato und deshalb alles so ewig gebraucht hat (Arbeitsspeicher) jetzt wo sie weiter verarbeitet werden ist die Geschwindigkeit recht angenehm
Vielen Dank nochmal

Das Problem war das die Daten nicht weiter verwendet wurden bis dato und deshalb alles so ewig gebraucht hat (Arbeitsspeicher) jetzt wo sie weiter verarbeitet werden ist die Geschwindigkeit recht angenehm

Vielen Dank nochmal