einzelne .py in Cython kompilieren

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.
Antworten
Felix92
User
Beiträge: 79
Registriert: Mittwoch 7. November 2018, 17:57

Mittwoch 12. Juni 2019, 18:03

Huhu und zwar wollte ich mal nachfragen ob es möglich ist eine einzelne .py-Datei aus einem Projekt in Cython zu kompilieren um die Performance zu erhöhen !?
Und wenn ja wie das geht :roll:
Ich hatte mir die Doku durchgelesen bin allerdings nicht so schlau daraus geworden für meine Zwecke.
In Anaconda und für ein einzelnes Skript ist das ja kein Problem (Doku) aber geht das auch für einzelne Methoden bzw. eine einzelne Klasse in einem größeren Projekt ?
Hintergrund: das Projekt wird mit fbs gestartet und auch gefreezt

Hier die Klasse:

Code: Alles auswählen

import os
import skvideo.io
import cv2

from pathlib import Path
from moviepy.editor import AudioFileClip
from model.data import VisualizerVideo, BoardVideo, Audio, SlideVideo, SpeakerVideo


class VideoSplitter:
    """
    This class handles the video and audio splitting
    """

    def __init__(self, folder_path, folder_name, video_data):
        """
        Constructor of the class

        @param folder_path: the path to the project folder
        @param folder_name: the name of the project folder
        @param video_data: the path of the video file
        """

        self.folder_path = folder_path
        self.folder_name = folder_name
        self.video_data = video_data
        self.files = []
        self.audio_files = []
        self.frame = 0
        self.number_frames = 0

    def cut_video(self, update_progress):
        """
        a method which cut the modivideos from the "main" video

        @param update_progress: a function which handles the progressbar countprocess
        """
        self.frame = 0
        reader = skvideo.io.FFmpegReader(self.video_data, {}, {})
        videometadata = skvideo.io.ffprobe(self.video_data)
        self.frame_rate = videometadata['video']['@avg_frame_rate']
        self.number_frames = int(videometadata['video']['@nb_frames'])
        folder = Path(self.folder_path, self.folder_name)

        board_filename = os.path.join(folder, 'board.mp4')
        slide_filename = os.path.join(folder, 'slides.mp4')
        visualizer_filename = os.path.join(folder, 'visualizer.mp4')

        board_out = skvideo.io.FFmpegWriter(board_filename, inputdict={
            "-r": self.frame_rate
        })

        slide_out = skvideo.io.FFmpegWriter(slide_filename, inputdict={
            "-r": self.frame_rate
        })

        visualizer_out = skvideo.io.FFmpegWriter(visualizer_filename, inputdict={
            "-r": self.frame_rate
        })

        # iterate through the frames
        for frame in reader.nextFrame():
            board_out.writeFrame(frame[183:537, 11:637])
            slide_out.writeFrame(frame[183:537, 720:1187])
            visualizer_out.writeFrame(frame[183:537, 640:1280])
            self.frame += 1
            if self.frame % 30 == 0:
                update_progress((int)(self.frame/self.number_frames*100))
        board_out.close()
        slide_out.close()
        visualizer_out.close()
        self.files.append(board_filename)
        self.files.append(slide_filename)
        self.files.append(visualizer_filename)
        self.__board_video = BoardVideo(board_filename)
        self.__slide_video = SlideVideo(slide_filename)
        self.__visualizer_video = VisualizerVideo(visualizer_filename)

    def get_board_video(self):
        return self.__board_video

    def get_slide_video(self):
        return self.__slide_video

    def get_visualizer_video(self):
        return self.__visualizer_video

    def get_speaker_video(self):
        return self.__speaker_video

    def cut_audio_from_video(self):
        """
        a method to get the audio from a video and save it in the project folder
        and create a object of this

        @return: a audio object which contains the path
        """

        folder = Path(self.folder_path, self.folder_name)
        audio_from_video = 'audio.mp3'
        audio = AudioFileClip(self.video_data)
        audio.write_audiofile(os.path.join(folder, audio_from_video), verbose=False, logger=None)
        extracted_audio = Path(folder, audio_from_video)
        self.audio_files.append(extracted_audio)
        return Audio(extracted_audio)
    
    def cut_zoom_video(self):
        """
        a method which track the speaker in the video and cut a video from this
        """

        folder = Path(self.folder_path, self.folder_name)
        speaker_filename = os.path.join(folder, 'speaker.mp4')
        video = self.get_board_video()

        cap = cv2.VideoCapture(str(video))
        #fgbg = cv2.createBackgroundSubtractorMOG2()
        fgbg = cv2.bgsegm.createBackgroundSubtractorMOG()

        is_ok, frame = cap.read()

        r, h, c, w = 180, 400, 400, 550
        track_window = (c,r,w,h)
        roi = frame[r:h, c:w]

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

        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
        out = cv2.VideoWriter(speaker_filename, fourcc , 21, (150, 220))

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

            if is_ok == True:
                is_ok, track_window = cv2.meanShift(gmask, track_window, term_crit)
                r, h, c, w = track_window
                #rect = cv2.rectangle(frame, track_window, 255, 2)
                out.write(track_window)    
            else:
                break

        cap.release()
        out.release()
        self.files.append(speaker_filename)
        self.__speaker_video = SpeakerVideo(speaker_filename)
Btw: ist der Bug immer noch nicht behoben, dass der cv2.VideoWriter aus OpenCV fehlerhafte Dateien schreibt wenn sie zu groß sind ( 1h 30m) oder mache ich einfach etwas falsch ? :D
PS: cut_zoom_video wird noch mit skvideo umgeschrieben (durch diesen Fehler)

Danke für eure Hilfe :)
MfG Felix
Sirius3
User
Beiträge: 9893
Registriert: Sonntag 21. Oktober 2012, 17:20

Mittwoch 12. Juni 2019, 18:06

Die ganzen get_-Methoden sind überflüssig und die __-Unterstriche der Attribute daher falsch, weil es sich ja doch um öffentliche Attribute handelt. Zudem sollten alle Attribute in __init__ angelegt werden.

Der gesamte Code enthält nichts, was Cython, oder irgend ein anderer "Optimierer" wesentlich schneller machen könnte. Es lohnt sich nicht.
Felix92
User
Beiträge: 79
Registriert: Mittwoch 7. November 2018, 17:57

Mittwoch 12. Juni 2019, 18:46

Dann muss ich mal so direkt fragen wie dann ?
Der Videoprozess dauert ewig und ich hatte halt gesehen das Cython das lesen und schreiben extrem beschleunigt in Anaconda
Sirius3
User
Beiträge: 9893
Registriert: Sonntag 21. Oktober 2012, 17:20

Mittwoch 12. Juni 2019, 19:01

Was hast Du da gesehen?
Benutzeravatar
noisefloor
User
Beiträge: 2684
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Mittwoch 12. Juni 2019, 19:05

Hallo,
Der Videoprozess dauert ewig und ich hatte halt gesehen das Cython das lesen und schreiben extrem beschleunigt in Anaconda
Da sind zwei Fehler drin: Cython beschleunigt wenn (Be-)Rechnungen, nicht I/O. Bei I/O ist das Laufwerk bzw. dessen Controller der geschwindigkeitsbestimmende Faktor. Und Anaconda hat damit auch nichts zu tun, Anaconda ist "nur" eine Python-Distribution.

Soweit ich das sehe, erledigt alles rechenintensive andere Python-Module, die du importierst. Heißt: wenn du optimieren willst, muss du da ansetzen. Wenn du deinen Code mit Cypthon kompilieren würdest, würden die externen Module dadurch _nicht_ automagisch schneller.
Dann muss ich mal so direkt fragen wie dann ?
Mehr CPU-Power. Bei der Audio-Video Kodierung hilfst das halt immer noch.

Gruß, noisefloor
Felix92
User
Beiträge: 79
Registriert: Mittwoch 7. November 2018, 17:57

Mittwoch 12. Juni 2019, 19:13

Also würdet ihr sagen rein vom Code ist keine Optimierung möglich ?
Felix92
User
Beiträge: 79
Registriert: Mittwoch 7. November 2018, 17:57

Mittwoch 12. Juni 2019, 19:17

Sirius3
User
Beiträge: 9893
Registriert: Sonntag 21. Oktober 2012, 17:20

Mittwoch 12. Juni 2019, 19:31

@Felix92: und wenn Du den Artikel gelesen hast, merkst Du, dass die unsinnige Funktion nicht auf magische Weise schneller wird, sondern, dass man da viel Wissen reinstecken muß, und die Funktion dafür auch geeignet sein muß. Videoverarbeitung ist schon hochoptimiert, dauert aber trotzdem eine Weile.
Benutzeravatar
noisefloor
User
Beiträge: 2684
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Mittwoch 12. Juni 2019, 19:34

Hallo,
Also würdet ihr sagen rein vom Code ist keine Optimierung möglich ?
Streich aus deinem Code mal alles raus, was Methoden / Funktionen aus importierten Modulen sind und alles, was I/O ist. Dann schau mal, was übrig bleibt. Dann siehst du relativ schnell, warum das nichts bringt.

In dem von dir verlinkten Artikel _enthält_ der _selbstgeschriebene_ Code den rechenintensiven Teil. Das ist bei dir nicht der Fall.

Gruß, noisefloor
Felix92
User
Beiträge: 79
Registriert: Mittwoch 7. November 2018, 17:57

Mittwoch 12. Juni 2019, 20:47

Ok da muss ich euch Recht geben :) Gibt es vlt. sonst eine Idee den Prozess zu beschleunigen über Threading, "vorladen" der Videos etc ?
Antworten