2025-01-06 ParkExpert Production Task #3Pirmkoda komentāriMagic dictionariesStartup skripti, screensDB optimizationsFFMPEG uzstādījumiMotion detection un resursu taupībaRTSP Worker debugging un server debuggingAI modeļu testēšana iekš workeriemDarbs ar WorkeriemVeids kā atrast problēmas sistēmas rezultātosNeuzmanības kļūdasTODO1. Pārtaisīt login formu ar parastu HTML form method=POST un action login2. Nepieciešams pārtaistīt, ka UX editors strādā stabili, sakārtot DB structure priekš streams (rtsp_connections) un zones3. Nepieciešams vienādot visus video, likvidēt direction lines, ieviest melnās maskas, atļaut vienu kustības masku un salabot UX, lai nebūtu jāpārlādē4. Nepieciešams eksperimentāli noteikt dienā un arī naktī THRESHOLD_MOTION_DETECTION vērtību, jāuzlabo motion detection5. Uzlabot un konfigurēt ARRIVE, LEAVE atpazīšanu izmantojot kustību pa Y asi un license plate area6. Pārbaudīt, ka korekti strādā virzienu un numuru atpazīšana vietās, kur ir 2 virzienu ielas7. Salabot discord botu8. Saglabāt atsevišķos folderos attēlus kur ar zemu pārliecību vai aizdomīgas numura zīmes ir atrastas, vai arī automašīnas ar zemu pārliecību9. Apstrādāt streams disconnections worker_rtsp_streams.py un uzreiz no šī worker nosūtīt POST parkexpert10. Salabot workers tā, lai tos nebūtu jāpārstartē un reizi 5 min tie paši pārbaudītu, vai zonas nav mainījušās.
Pilnīgi visām datu struktūrām pretī ir jābūt seralizējamām datu klasēm, aizliegts lietot magic dicitionaries un magic lists, kuri izraisa bugs.
Pareizs kods
Visi startup skripti tiek definēti šādi un priekša izmantojam skaitli, lai ērtāk pieslēgties screeniem. Ja tiek nokillots kāds screen, var izsaukt startup script un tiks atjaunoti tikai killed streams.
Ļoti svarīgi, ka datubāzē INSERT, UPDATE utt notiek ar vienu CALL nevis FOR loopā!! Arī SELECT jātaisa uzreiz pirms for loop visiem elementiem nevis pa vienam DB connection
Visiem SELECT jabūt SQL indexes, lai optimizētu DB, tos var ērti uzģenerēt ar Cursor IDE
PIL un OpenCV attēlu apstrādei nereti ir lēns, tāpēc ir jāatrod bibliotēkas, katram uzdevumam, lai padarītu ātrākas darbības, piem. JPEG ielāde. Tika atstāts PNG tikai numura zīmēm, kur mazā rezolūcijā saturs, citiem kadriem, nevar atļauties turēt milzīgus datu failus
Kur vien iespējams izmantot jau nokompilētas funkcijas un optimizētas funkcijas ārpus python, jo python ir ļoti lēns.
Multiprocessing
Nekad un nekur neizmantot Python.Therading
tā vietā ir jaizmanto multiprocessing
, kaut arī threading ir ērti izmantot, jo var piekļūt globāliem mainīgajiem, taču tas viss izpildās uz viena CPU ar GIL!
Python un javascript fake “threading”
Kā strādā multiprocessing
Labākais veids kā pārsūtīt datus ir izmantot multiprocessing.Lock un shared memory arrays (man nebija laika to šādi sakodēt, bet tas ir vajadzīgs). Bez tā ļoti daudz CPU laiks aiziet pārsūtot serializētus attēlus uz GPU procesu. Lock ir vajadzīgs, lai CPU un GPU worker vienlaicīgi nelasītu konkrētā apgabalā masīvam, lai lockotu LENGTH mainīgo. Bet ir atļauts rasktīt vienā masīva apagabalā un lasīt otrā vienlaicīgi
https://www.perplexity.ai/search/give-example-sending-data-to-m-8i4KdD5cSE6LEL5YEJK0qw
Ja tiek izmantots queue, kur searializē BINARY datus, svarīgi, ka atpakaļ nesūtam attēlus, tos procesē GPU, un uzstāda kā None
FFMPEG tika nokompilēts ar CUDA un GPU atbalstu, to palaižot uz CUDA CPU noslodze ir 10x mazāka , bet diemžēl viens stream paņem 400MB GPU atmiņu.
Piemērs kā palaist FFMPEG ar CUDA nevis CPU
xxxxxxxxxx
11ffmpeg -loglevel quiet -rtsp_transport tcp -hwaccel cuda -hwaccel_output_format cuda -an -i "{self.rtsp_url}" -an -vcodec h264_nvenc -threads 1 -f segment -vf "fps=10,scale_npp=1280:720" -preset fast -reset_timestamps 1 -sc_threshold 0 -segment_time 10 -strftime 1 "{self.output_file_name}"
Daži no decoder/encoderiem ātri strādā, bet diemžēl neatbalsta lielāko daļu streams piemēram hevc
, bet h264
strādā
Versija, kura beigās tika izmantota
Kur iespējams, jātaupa CPU un RAM resursi, šeit piemēram, motion detection implementēju, samazinot rezolūciju un ielādējot JPEG grayscale
Var atkomentēt pie DEBUG
jāaizkomentē
worker.start()
kurš palaiž ārēju procesu
un atkomentē worker.run()
kas palaidīs vienu procesu un bloķēs esošo priekš debugging,
Serverī no komandrindas var debuggot kodu, ja NAV palaists multiprocessing ar
xxxxxxxxxx
41import pdb
2
3# kods, kur grib apturēt un konsolē debuggot
4pdb.set_trace()
Katrā no AI workeru skriptiem nostrādā IS_LOCAL_DEBUG_AI_MODEL
, ja tiek palaists ne-no linux, jeb servera vides
Šajā daļā var paņemt failus no servera un testēt pa vienam, lai atrastu problēmas
Failus var dabūt no šiem folderiem katram worker tipam
xxxxxxxxxx
11worker_car_detection_camera.py
xxxxxxxxxx
11worker_car_license_plate_detection_camera.py
xxxxxxxxxx
11worker_car_license_plate_reading_camera
⚠️ Lai apturētu workeru, nospiež vienreiz Ctrl+C
un gaida līdz gracefull shutdown. Dažreiz tas nenotiek, tad ļoti svarīgi palaist pkill
komandu, lai apturētu workeru fona procesus, citādi tie noēdīs visu CPU un RAM!
Kad neatpazīst mašinas un kad atpazīst nepareizi mašīnas
Viens risinājums kā veikt debugging ir izmantojot /home/asya/park_expert/recordings
, kurā parādās video, kas notikuši pēc kustības noteikšanas un tās laikā. Jāskatās gan video, gan txt, lai saprastu vai kustība noteikta pareizi un vai ir kādas problēmas.
Otrs risinājums kā monitorēt worker worker_result_in_tasks
pieslēdzoties screen -rd 7_
un apskatīt katru notikumu pēc kārtas klikšķinot uz Video un attēlu un pārliecinoties, ka pareizi noteikts virziens, Ja nepareizi sākt meklēt situāciju pēc task_id
ja nav video tas var būt normāli, kamēr rtsp_worker uzbūvē video, ja ir nesan palaists (ja ilgāku laiku iet jābūt arī video)
Ctrl+A [
scroll mode
Ctrl+C
iziet no scroll mode
⚠️Veicot izmaiņas tās uzmanīgi notestēt lokālā vidē nevis produkcijā. Kad nepieciešams varam izveidot vast.ai pieeju.
Izmaiņas veikt dotajā secībā:
👩🏻🎓Kristianai https://github.com/asya-ai/parkexpert-licenseplate-api/issues/3
Kā iesildīšanās uzdevums izmaiņām pārtaisīt, ka login forma nemaz nezinamnto nekādu JS, bet tā vietā ir parastā HTML form method=POST un action login, kuru otrā pusē nolasa Flask POST datus. Flask pusē jābūt pārbaudēm uz laukiem un try..except.
Pemērs kā sakodēt login: https://codeshack.io/login-system-python-flask-mysql/
Jāapstrādā arī gadījumi, kad nav izdevies login un jāparāda error messages ar Flask Flash palīdzību. Lietotāja user_id jāglabā sessijā un tādā veidā var noteikt vai lietotājs ir ielogojies.
Piemērs: https://www.perplexity.ai/search/give-example-flask-session-dec-0kkG_KlWRB.0wthtdzweBg
👩🏻🎓Kristianai
https://github.com/asya-ai/parkexpert-licenseplate-api/issues/4
Šīs izmaiņas taisīt jaunā branch, jo ir potenciāls salauzt visu kodu. Super uzmanīgi pārskatīt ControllerDatabase, lai visas funkcijas turpinātu strādāt pēc izmaiņām, vai pielāgot kodu workeros.
Ļoti svarīgi netaisīt liekus DB calls, visam jābūt ir ar pēc iespējas mazāk calls!
Testēt datu bāzi uzmanīgi lokāli (datu bāzes var nokopēt un atjaunot ar pg_dump un pg_restore). Zone editorā neizmanot JS, lai komunicētu ar serveri. Poligonus ievietot <input type="hidden">
laukos, kas jāsūta uz serveri kā JSON un servera pusē tos nolasa ar POST.
Atceries pēc POST seko redirect atpakaļ uz to pašu lapu un ar Flask Flash palīdzību parādīt error vai success messages.
Home page atverot “/” atvērt pēc alfabēta pirmo zone ar redirect, ja nav zones, tad, lapu labā pusē kura tukša. Kreisā pusē var pievienot zonas
Jauno formu mockups:
Links izskatās šādi:
/zone/<zone_name>
Jaunas zonas pievienojot atveras augstākais links, kurā var mainīt zonas nosaukumu. Pēc saglabāšanas zonas nosaukumu vairāk nerādīt <input>
laukā, bet gan kā nemaināmu <span>
tekstu. Pēc saglabāšanas “zone_name” nevar mainīt, bet var soft delete is_deleted
DB pašu zonu.
Dzēšot zonas jābūt confirm message JS before clicking on links. https://www.perplexity.ai/search/give-example-href-url-before-c-5uDn5NzOQL.hSP19G7GGiA
Nerādīt popup, iekļaut vienā /add-zone
linkā (var izmantot to pašu html template ko /zone/<zone_name>
)
Uzspiežot uz katrā zonā esošajiem streams atverās zemākais links, kur var visu mainīt saistībā ar stream
/zone/<zone_name>/stream/<stream_name>
Šie lauki var tikt pievienoti augstāk esošajai formai, nedrīkst būt kā JS popup, jabūt caur HTTP POST
Pēc saglabāšanas “stream_name” nevar mainīt, bet var soft delete is_deleted
DB pašu stream.
Datubāzē nopietnas izmaiņas jāveic ieviešot 1:N relācijas nevis N:N, pie tam ir jāizmanto IDs nevis dažadu nosaukumu strings column names
Pilnīgi visām datu struktūrām pretī ir jābūt seralizējamām datu klasēm, aizliegts lietot magic dicitionaries un magic lists, kuri izraisa bugs.
⚠️ Obligāti pārbaudīt gan streams_name, gan connection_name, ka nav duplikāti, lielas problēamas bija, ka bija duplikāti
Sadalīt flask controller daļas pa atseviķiem blueprints katrai daļai /zones
, /user
etc
https://www.perplexity.ai/search/give-example-flask-blueprint-c-maSwBnvJR7.Yy5ceaqBBcQ
Vēlams arī apskatīties nākamo uzdevumu:
👩🏻🎓Kristianai
https://github.com/asya-ai/parkexpert-licenseplate-api/issues/5
Nepieciešams pārtaisīt, ka visas kameras strādā vienādā rezolucijā (ielikt kā konstanti vienā vietā nevis hardcoded 10 vietās). By default 1080p (1920x1080). Nepieciešams nomainīt, ka kameru rezolūcijas ir vienādas UX panelī, masku PNG un Poligonu. Pie reizes var ņemt nost virziena līniju.
Svarīgi, ka worker_results_in_tasks.py
workerī arī tiek nomainīta FFMPEG komanda, ka atgriež vienāda izmēra streams bildes visiem streams
Nepieciešams lietotāja interfeisā applikācijā izveidot iespēju pievienot melnus laukumus ar kuriem aizstāt daļas bildē, kur, piemēram, poligonā ieiet laika zīmoga skaitļi, kuri visu laiku palaiž motion detection.
Formai jāizskatās apmēram šādi:
Piemēri, kur nepieciešams melnais bloks, lai netiktu nepārtraukti fiksētas kustības.
Pēc melnā bloka izveides, to nepieciešams “uzzīmēt” pa virsu ar ffmpeg komandu pēc iespejas mazāk ir jāveic jebkādas operācijas ar cv2, kas patērē daudz resursus
Tāpāt UX nepieciešams nepieļaut vairāk kā viena bounding box ievadi maskai.
Nepieciešams pārtaisīt veidu kādā tiek atpazīts virziens. Direction lines diemžēl nekam neder. Nepieciešams lieotāja interfeisā un datubāzē noņemt direction lines un tā vietā nepieciešams norādīt tikai sakarību starp to vai mašīna tuvojas nozīme ARRIVE vai LEAVE. Jābūt ARRIVE: [Moving closer, Moving away] (dropdown) un šī informācija jāglabā datubāzē pie rtsp_connections. Un jāizmanto worker_results_in_tasks.py.
Šobrīd detection mask tiek bounding box tiek iegūts šādi, bet nepieciešams šo strukturēti kolonās un dataclasses saglabāt iekš rtsp_connections
tabulas jeb streams.
Melnos apgabalus gan ir jābglabā atsevišķā tabulā stream_black_boxes
vai ja nav pārsauktas tabulas tad rtsp_connection_black_boxes
ar atsauci uz rtsp_connection_id
vai ja pārsaukts stream_id
🧑🎓 Artūrs Uldis
https://github.com/asya-ai/parkexpert-licenseplate-api/issues/6
Veicot eksperimentus tos veikt atsevišķā vast instancē (nav nepieciešams liels GPU). Izmantot testa DB uz asya-4 (asya-3 DB tiks izveidota kā produkcijas DB)
Nepieciešams eksperimentāli noteikt dienā un arī naktī THRESHOLD_MOTION_DETECTION vērtību worker_rtsp_streams.py
Kur iespējams, jātaupa CPU un RAM resursi, šeit piemēram, motion detection implementēju, samazinot rezolūciju un ielādējot JPEG grayscale. Bet jāpārbauda vai motion detection nevar uzlabot arī ar blur. ir ieviests arī is_image_same_color
, kas ir svarīgi itīpaši naktī vai arī, ja kamera uzkaras nevis melnā krāsā bet kādā citā.
Jāņem vērā arī sekojošais, jāsamazina ietekme
Vairākām kamerām pa nakti parādas defekts, ka iet viļveidīgas līnijas uz ekrāna:
CAMUPI2 - “melnie viļņi” - šīs kameras nevajadzīgi triggero motion detection ēd resursus
MED1 - “melnie viļņi” - šīs kameras nevajadzīgi triggero motion detection ēd resursus
Vairākām kamerām tumšajā diennakts laikā ievērojami samazinās rezulūcijas kvalitāte
B75B1 - tumšajā laikā mevar salasīt numura zīmes par 1080p rezolūcijā
MFK5 - tumšajā laikā mevar salasīt numura zīmes par 1080p rezolūcijā
Dažām kamerām krīt virsū sniegs un dažas kustās vējā
CAMWOW - aizsnieg kamera - varbūt var uzlikt kādu jumtiņu priekšā?
DAT - aizsnieg kamera - varbūt var uzlikt kādu jumtiņu priekšā? https://share.yellowrobot.xyz/quick/2025-1-6-54F5880A-2C59-4941-A146-E646C4313DC1.mp4
🧑🎓 Artūrs Uldis https://github.com/asya-ai/parkexpert-licenseplate-api/issues/7
Uzlabot un konfigurēt ARRIVE, LEAVE atpazīšanu izmantojot kustību pa Y asi un license plate area. Izmēģināju
ar worker_car_detection_camera.py debug code pārbaudīt is_dark, is_fully_dark (super bīstami mainīt citu histogrammu kodu, jāseko līdzi CPU usage)
Izmaiņas jāveic worker_results_in_tasks.py
Nepieciešams eksperimentāli noteikt DELTA_PERCENT_FOR_LEAVING
un DELTA_PIXELS_FOR_CROSSING_DIRECTION
Risinājums kā monitorēt worker worker_result_in_tasks
pieslēdzoties screen -rd 7_
un apskatīt katru notikumu pēc kārtas klikšķinot uz Video un attēlu un pārliecinoties, ka pareizi noteikts virziens, Ja nepareizi sākt meklēt situāciju pēc task_id
ja nav video tas var būt normāli, kamēr rtsp_worker uzbūvē video, ja ir nesan palaists (ja ilgāku laiku iet jābūt arī video)
Ctrl+A [
scroll mode
Ctrl+C
iziet no scroll mode
Piemēram šeit DAT Y ass minimāli mainījās, bet numura zīme palika mazāka.
Nevis ARRIVE, bet leave aizbraucot tālumā https://share.yellowrobot.xyz/quick/2025-1-6-F5957223-78D3-463A-94E0-AD036534E7A8.mp4
Wrong direction
https://share.yellowrobot.xyz/quick/2025-1-6-616D9DD9-8FBE-4A95-8BD0-0AD90F1A9B4E.mp4
RCE3 https://share.yellowrobot.xyz/quick/2025-1-5-3C6DF9B3-3095-4C26-BE2A-6F1E1E898612.mp4
Paskatīties cik CPU tiek ēsts, ja pamēģinam izmantot opencv atpazīšanu pagrieztām un perspektīvām numura zīmēm, lai aprēķinātu to laukumu
https://github.com/asya-ai/parkexpert-licenseplate-api/issues/8
🧑🎓 Artūrs Uldis
Pārbaudīt, ka korekti strādā virzienu un numuru atpazīšana vietās, kur ir 2 virzienu ielas. Jāpārbauda situācijas, kur ir abpusēju virzienu kameras (vajadzētu strādāt, bet jāpārbauda) - EK2 camera, Atrast vēl kurās kamerās ir šāda situācija, zinu, ka ir vairākas šādas. Dokumentēt uzmanīgi rezultātus - vajadzēs atskaiti.
Salabot discord botu, izmantojot visus iepriekš minētos koda komentārus. Jāziņo, ja ilgstoši neatpazīst kādā no features rezultātus.
Saglabāt atsevišķos folderos attēlus kur ar zemu pārliecību vai aizdomīgas numura zīmes ir atrastas, vai arī automašīnas ar zemu pārliecību. Savākt datu kopu un atskaiti. Izdomāt kādas augmentācijas un labelling nepieciešams
xxxxxxxxxx
11os.makedirs("training_data/photos", exist_ok=True)
Apstrādāt streams disconnections worker_rtsp_streams.py un uzreiz no šī worker nosūtīt POST parkexpert. JSON jābūt ar dataclass. sūtīt gan, kad pazūd savienojums, gan, kad izveidojas.
Pirmāri šis attiecas uz worker_rtsp_streams.py un worker_results_in_tasks.py, bet mainoties zonām jāatceļ iepriekšējie uzdevumi konkrētai zonai. Izmaiņas var būt masku izmaiņas. Ja izmainās callback_url vai arrive direction to jānomaina, bet nav jādzēš taski.