Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Wangarad 02. 08. 2019, 12:31:56
-
Zdravim.
Snazim sa zrychlit moj program ktory detekuje objekty. Pouzivam Python 3.7 , opencv. Chcel som vytvorit novy thread pre nacitanie videa skrz vstup a druhy ktory by ho spracovaval. V povodnom by bezalo GUI. Neviem ci to robim dobre ale cele je to o dost pomalsie (bez threadingu = 0.03 s 0.7). Co robim zle? Pripadne ako to zrychlit?
#Camera Theard
class VideoWriterWidget(object):
def __init__(self, video_file_name, src=0):
# Create a VideoCapture object
self.frame_name = str(src)
self.video_file = video_file_name
self.video_file_name = video_file_name + '.avi'
self.cap = cv2.VideoCapture(src)
# Default resolutions of the frame are obtained (system dependent)
self.frame_width = int(self.cap.get(3))
self.frame_height = int(self.cap.get(4))
# Set up codec and output video settings
self.codec = cv2.VideoWriter_fourcc('M','J','P','G')
self.output_video = cv2.VideoWriter(self.video_file_name, self.codec, 30, (self.frame_width, self.frame_height))
# Start the thread to read frames from the video stream
self.thread = Thread(target=self.update, args=())
self.thread.daemon = True
self.thread.start()
# Start another thread to show/save frames
self.start_recording()
print('initialized {}'.format(self.video_file))
time.sleep(0.2)
def update(self):
# Read the next frame from the stream in a different thread
while True:
if self.cap.isOpened():
(self.status, self.frame) = self.cap.read()
def show_frame(self):
# Display frames in main program
globals().update(global_frame_for_process = self.frame)
def save_frame(self):
if self.status:
# Save obtained frame into video output file
#Tu volam druhu funckiu ktora riesi processing
self.output_video.write(self.frame)
def start_recording(self):
# Create another thread to show/save frames
def start_recording_thread():
while True:
try:
self.show_frame()
self.save_frame()
except AttributeError:
pass
self.recording_thread = Thread(target=start_recording_thread, args=())
self.recording_thread.daemon = True
self.recording_thread.start()
cele to potom volam s GUI video_writer_widget1 = VideoWriterWidget('Camera 1 start', src1)
Nie je mi jasne ci sa GUI spusta v tom istom threade alebo sa vytvara nove? Tiez ten thread vyzera akoby bezal "davkovo" teda spracuje 20 framov a na milisenku sa sekne a znova...
Ako to spravit tak aby to bezalo rychlejsie? Idem na to dobre alebo cele zle?
-
Python má GIL, v jednu dobu může běžet jen jeden thread, pokud teda funkce (musí to bejt knihovní, nenapsaná, v Pythonu) ten GIL explicitně "neuvolní" na nějakou déle trvající operaci, na kteoru ho nepotřebuje (např. při čekání na IO).
Jen hádám, ale tuším, že problém bude tady - že ty knihovny co používáš si drží GIL a pak se jen ztrácí čas při přepínání kontextu. Jednoduše to zjistíš, když se koukneš (např. top), jestli to vůbec někdy využije více než jedno jádro.
Další možnost je ta, že někdy (vlastně jsem moc nezjišťoval kdy, prostě jsem ji při paralelním výpočtu pro jistotu zrušil vždy) python automaticky nastavuje processu afinitu na jedno jádro. Takže také zkus také zkontrolovat todle (ale myslím, že to problém nebude).
-
No, totiž, opravdu nejlepší odpověď, kterou teď můžete dostat je: Musíte se to učit postupně od základů.
Takže např. ten čtecí thread přečte 1000 framů, strašně rychle, jeden po druhým. Takže chvilku
běžel, a do proměnných self.status, self.frame uložil ten poslední frame.
No a nějakým způsobem zároveň s tím běží ten druhej thread na to zobrazování. Te v cyklu
zpracovává self.frame, že? Takže si zase třeba velice rychle (např. 1000x za sebou) zpracuje
mnohokrát po sobě pořád tu stejnou fotku.
Takže Vy musíte přijít se způsobem, jak jeden thread řekne druhýmu: Hele mám snímek, tady
ho máš, tak ho zpracuj. Úplně ideálně je dávat do nějaké fronty.
Teprve potom přijde na řadu ten zmíněný GIL. Tak se mějte hezky...
-
Logik a existuje cesta ako vyriesit ten threading? Na nete je xyz prikladov ale viac menej to iste dookola. Skusam sa s tym zabavat ale neviem sa dopatrat toho ako definovat thread1 a thread2. Musi to nieako fungovat
Petr Blahos:
Ale ja by som praveze chcel aby to na jednom threade len zapisovalo a na druhom len spracovavalo. Viem ze tam budem volat len jednu funkciu ale neviem ako "nastartovat" novy separatny thread len pre spracovanie.
-
No, jak píšu: Musíte se to učit postupně od základů.
Hledejte úlohy typu producer - consumer. Producer je ten thread, který čte a např. ukládá
do fronty, consumer je ten, který konzumuje z fronty, a dál s tím pracuje. Ale tohle není
na thread na rootu.
-
Dobre.
Tak idem na to od zakladov. Ono je celkom tazke najst rozumny manual alebo tutorial kde by to bolo vysvetelne po lopate.
Otazka: Ak spustam loop pre GUI a s neho volam thread na dalsiu ulohu, je tento thread novy? Teda GUI ide samostatne a nova uloha v novo threade alebo je to v jednom? Teda je efektivnejsie zavolat thread GUI a samostatne thread uloha? Nie je mi to celkom jasne. Tiez mi nie je jasne ako zavolat thread 1 a thread 2
-
No jo, ono totiž dělat UI přímo v OpenCV je přinejmenším nepohodlné. Spíš bych doporučil
jinej framework (např. já v Pythonu používám wxPython, a na lze začít třeba tady
http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/ nebo
https://wiki.wxpython.org/WorkingWithThreads). Když to pochopíte v něm, tak získané
znalosti přenesete i na OpenCV.
https://lmgtfy.com/?q=producer+consumer+threads+python