Përmbajtje:

Njohja e yjeve duke përdorur vizionin kompjuterik (OpenCV): 11 hapa (me fotografi)
Njohja e yjeve duke përdorur vizionin kompjuterik (OpenCV): 11 hapa (me fotografi)

Video: Njohja e yjeve duke përdorur vizionin kompjuterik (OpenCV): 11 hapa (me fotografi)

Video: Njohja e yjeve duke përdorur vizionin kompjuterik (OpenCV): 11 hapa (me fotografi)
Video: Computer Vision with Python! Grayscaling Images 2024, Nëntor
Anonim
Njohja e yjeve duke përdorur vizionin kompjuterik (OpenCV)
Njohja e yjeve duke përdorur vizionin kompjuterik (OpenCV)

Ky udhëzues do t'ju përshkruajë se si të krijoni një program vizioni kompjuterik për të identifikuar automatikisht modelet e yjeve në një imazh. Metoda përdor bibliotekën OpenCV (Open-Source Computer Vision) për të krijuar një grup kaskadash të trajnuara HAAR që mund të përdoren për të njohur modele të veçanta yjesh. Edhe pse ky udhëzues është në kontekstin e njohjes së modelit të yjeve, procesi i OpenCV që përshkruaj mund të zbatohet edhe në aplikacione të tjera - kështu që me shpresë do të jetë i dobishëm!

Projekti përmblidhet në këtë video:

Pse e shkrova këtë udhëzues?

  1. Metoda e identifikimit të modelit të yllit që po zhvilloj besoj se ka potencial të zbatohet në një gamë të gjerë të projekteve astronomike amatore - pavarësisht nëse është orientimi teleskopik, klasifikimi automatik i imazhit, apo edhe përfundimisht një sensor yll në një burim të hapur ose amator CubeSat.
  2. Ka shumë udhëzime të mira OpenCV këtu, por edhe kështu e kam parë një proces shumë të vështirë për të mësuar fillimisht, kështu që shpresoj se ky udhëzues do të jetë një referencë e mirë për njerëzit e tjerë që kërkojnë të trajnojnë klasifikuesit HAAR për OpenCV (jo domosdoshmërisht për të bërë me astronomi ndoshta!).
  3. Unë nuk jam një programues i trajnuar vetë, kështu që ky projekt me të vërtetë më shtyu të kuptoj. Shpresojmë se duke shkruar këtë udhëzues, krijuesit e tjerë, më me përvojë, do të frymëzohen për të punuar në këtë koncept dhe për të kontribuar në GitHub dhe këtë të udhëzueshëm përmes komenteve në këtë faqe.
  4. Astronomia amatore dhe metodat e orientimit janë një interes i madh i imi, shikoni udhëzimet e mia të mëparshme që përmban një Arduino Star-Finder për Teleskopët.

Fotografia e kopertinës e këtij Instructable është e një koncepti të modelit 3U CubeSat në të cilin kam marrë pjesë në hartimin e tij. Unë e përdor atë për të ilustruar këtë udhëzues pasi aplikimi origjinal i sistemit të njohjes së yjeve të vizionit kompjuterik do të ishte për një sensor orientimi për CubeSats të bërë nga amatorët, duke përdorur një Kamera Raspberry Pi V2. Ka shumë aplikacione të tjera të mundshme të njohjes së yjeve të shikimit kompjuterik besoj, por mendoj se kjo është më e lezetshmja!

Një fjalor i vogël:

Mësimi rreth vizionit kompjuterik bëhet më i ngadalshëm nga sasia e trashë e termave specialistë të përdorur, kështu që unë do të përcaktoj disa për ne këtu:

Kaskada - Një klasifikues i trajnuar për të identifikuar një objekt specifik të synuar.

Shënuesi Fiducial - Një shënues që shton një pikë referimi vizual në një imazh.

HAAR - Karakteristikat e ngjashme me Haar janë një lloj karakteristike e imazhit që përdoren për trajnimin e klasifikuesve.

OpenCV - Vizioni kompjuterik me burim të hapur, një bibliotekë e mjeteve të vizionit kompjuterik.

Stellarium - Softuer astronomie me burim të hapur.

Hapi 1: Kërkesat

OpenCV është një bibliotekë e bazuar në Linux, kështu që megjithëse supozohet se është e mundur ta përdorni mirë në Windows, do ta keni më të lehtë ta përdorni në një mjedis Linux (hiqeni këtë nga unë dhe shumë ditë duke u përpjekur që ta punoni plotësisht Windows!). Si një eksperiment, unë shkarkova dhe drejtova OpenCV në Raspberry Pi 3B+, i cili ishte i suksesshëm, megjithëse trajnimi i klasifikuesit është një proces shumë intensiv i RAM -it, kështu që nëse dëshironi ta bëni atë me çdo shpejtësi, rruga e rekomanduar është të punësoni një Linux Virtual Server (e cila mund të jetë çuditërisht e lirë në të vërtetë) për disa ditë/javë/muaj dhe përdorni atë si një mjedis të dedikuar në të cilin të drejtoni trajnimin e klasifikuesit. Ju do të jeni në gjendje të kontrolloni serverin nga një kompjuter Windows duke përdorur një klient SSH siç është Putty. Pasi kaskadat të trajnohen duke përdorur VPS, ato mund të shkarkohen në kompjuterin tuaj Windows dhe Python mund të përdoret për të drejtuar programin e njohjes së imazhit në një mjedis Windows.

Server Virtual Linux:

Një Server Virtual Linux (VPS) nevojitet për të kryer proceset e trajnimit të kaskadës HAAR. Fillimisht punësova një server me 8 GB RAM dhe Ubuntu 16.04.6 (LTS) x64, dhe më vonë një të dytë për të dyfishuar shkallën me të cilën mund të stërvitja kaskada, edhe pse do t'ju duhet vetëm një minimum

Softuer:

  • Stellarium - ky është program planetarium/astronomi virtual, i disponueshëm lirshëm. Do të përdoret për të mbledhur imazhe të simuluara të yjeve për përdorim në testim.
  • Stuko - Ky është një klient SSH që përdoret për të kontrolluar VPS përmes vijës së komandës.
  • WinSCP - kjo përdoret për të kryer transferimin e skedarëve nga kompjuteri Windows.

Hapi 2: Konfigurimi i VPS

Ekziston një proces i vogël konfigurimi për të vënë në funksion VPS. Herën e parë mund të duhet pak kohë për ju, por nuk është shumë e ndërlikuar nëse ndiqni hapat nga afër. Ky tutorial ishte një referencë e shkëlqyeshme për mua, unë do t'ju rekomandoja ta lexoni edhe këtë ndërsa punoni përmes këtij udhëzuesi. Ai mbulon specifikat e komandave linux rresht pas rreshti, e cila është e nevojshme të ndiqet me shkronjë.

Afërsisht, procesi përfshin:

  1. Krijimi i serverit Linux me versionin e duhur të Ubuntu.
  2. Përditësimi dhe azhurnimi i serverit.
  3. Krijimi i një drejtorie të hapësirës së punës, në të cilën është instaluar OpenCV.
  4. Instalimi i disa gjërave thelbësore, përkatësisht një përpiluesi, bibliotekave të ndryshme dhe lidhjeve Python.

Pas kësaj faze, ju jeni gati për të filluar përgatitjen për procesin e trajnimit.

Hapi 3: Procesi

I gjithë procesi i vizionit kompjuterik duke përdorur kaskadat HAAR është mjaft konfuze në fillim, kështu që ky hap përshkruan logjikën në më shumë detaje:

Procesi Bazë

  1. Ekziston një grup i dhënash negativ i imazhit, i përbërë nga disa mijëra imazhe që nuk përmbajnë objektin e interesit. Kjo do të duhet të ngarkohet në VPS.
  2. Krijohet një imazh i vetëm pozitiv që përmban objektin e interesit. Kjo gjithashtu do të duhet të ngarkohet në VPS.
  3. Imazhi i vetëm pozitiv shtrembërohet, shtrembërohet, rrotullohet, etj., Nga një grup parametrash të zgjedhur dhe mbivendoset mbi një përzgjedhje të imazheve negative. Kjo është një mënyrë artificiale për të krijuar një grup të dhënash të madh pozitiv nga një imazh i vetëm. (Për aplikimet e tjera të botës reale, të tilla si identifikimi i një mace, thjesht mund të përdorni disa mijëra imazhe të maceve, por kjo metodë nuk është gjithmonë e përshtatshme nëse nuk keni një grup kaq të madh të imazheve pozitive. Qasja artificiale e përdorur këtu do të jetë më pak efektiv, por është opsioni i vetëm për një rast përdorimi si ky).
  4. Drejtohet një proces trajnimi, i cili funksionon në faza. Çdo fazë do të trajnojë një kaskadë për të identifikuar tipare të ndryshme të tipit HAAR brenda imazheve. Çdo fazë kërkon eksponencialisht më shumë kohë për tu përfunduar, dhe efektiviteti i klasifikuesit rritet çdo herë (është gjithashtu e mundur të stërviteni tej mase vetëm për ta ditur!).
  5. Një kaskadë e vetme e trajnuar do të jetë në gjendje të kërkojë një objekt të vetëm objektiv. Nëse dëshironi të identifikoni objekte të shumta unike, do t'ju duhet një kaskadë e trajnuar për secilën. Në këtë rast, unë trajnova rreth 50 kaskada të ndryshme për modele unike yjesh, për të krijuar një grup që mund të mbulonte hemisferën qiellore veriore.
  6. Së fundmi, përdoret një program zbulimi që drejton çdo kaskadë të një grupi kundër një imazhi hyrës. Kaskada do të kërkojë objektin e saj të caktuar të synuar brenda imazhit hyrës.
  7. Nëse është i suksesshëm, objekti i synuar do të identifikohet brenda imazhit hyrës.

n.b. nëse përdoret në kontekstin e orientimit satelitor për shembull, një imazh do të kapet duke përdorur një aparat fotografik në bord. Yjet më të ndritshëm në atë imazh do të identifikohen dhe shënuesit mbivendosen në ato pozicione. Ky imazh më pas paraqitet në grupin e kaskadave të stërvitura, të cilat do të testojnë për të parë nëse imazhi hyrës përmban ndonjë nga objektet e synuara. Nëse zbulohet një pozitiv i vërtetë, atëherë pozicioni këndor i një plejade të njohur zbulohet në lidhje me akset e trupit satelitor.

Hapi 4: Negativët dhe Pozitivët

Negative

Një aspekt vërtet kyç i trajnimit të kaskadës është të kesh një grup të madh të imazheve negative sa të jetë e mundur. Ne po flasim për mijëra, në mënyrë ideale dhjetëra mijëra imazhe. Nuk ka shumë rëndësi se çfarë përmbajnë ato, qëllimi është vetëm të sigurojmë një larmi informacioni vizual. Dosja e Trajnimit të Klasifikuesit përmban një sërë grupesh të ndryshme të të dhënave negative të imazheve që kam përpiluar. Fillimisht këto ishin të përbërë vetëm nga imazhe të simuluara të fushës së yjeve të grumbulluara nga Stellarium, por më vonë e shtova bazën e të dhënave me sa më shumë imazhe të rastësishme që mund të gjeja (po, përfshirë fotografitë e mia të pushimeve …). Grupi më i madh i të dhënave përfshin pothuajse 9000 imazhe, i cili ishte më i madhi që kam krijuar deri më tani. Duke e përdorur këtë do t'ju kursejë duke përpiluar tuajin.

Pozitive

Imazhi pozitiv (ky është modeli yll i synuar që kaskada do të trajnohet të njohë) fillon si një pamje e ekranit të një modeli ylli në Stellarium. Një program python më pas identifikon yjet më të ndritshëm në imazh dhe mbivendos shënuesit (shpjeguar më vonë në këtë udhëzues) në këto pozicione yjesh. Ky imazh më pas zvogëlohet në 50x50 piksele. Kjo është e vogël, por koha e trajnimit e kërkuar për kaskadat do të rritet në mënyrë eksponenciale me rritjen e kësaj madhësie, dhe kështu ky është një kompromis i mirë midis cilësisë dhe kohës.

Hapi 5: Kontrolli Stellarium

Kontrolli Stellarium
Kontrolli Stellarium
Kontrolli Stellarium
Kontrolli Stellarium

Dosja Stellarium Scripts e depove GitHub përmban tre programe që kam shkruar për të kontrolluar përdorimin e Stellarium. Për t'i përdorur ato, vendosini ato në dosjen e skripteve në dosjen tuaj të instalimit Stellarium. Për t'i ekzekutuar ato, mund të hapni dritaren e skripteve nga menyja Stellarium, ose thjesht duke klikuar dy herë mbi programin në dosjen e skripteve, i cili do të nisë Stellarium dhe menjëherë do të ekzekutojë programin e zgjedhur.

thesis_4 dhe thesis_5 kapin rreth 2000 imazhe secila nga hemisferat qiellore përkatësisht veriore dhe jugore. Këto u përdorën për të formuar bazat e të dhënave të imazheve negative, për të trajnuar imazhin pozitiv kundër. Dallimi midis veriut dhe jugut ishte një mënyrë e thjeshtë për të siguruar që modeli i synuar (pozitiv) i yjeve nuk do të ishte i pranishëm në grupin e të dhënave negative duke trajnuar modelet e yjeve të hemisferës veriore kundër grupit të të dhënave të imazhit të hemisferës qiellore jugore dhe anasjelltas. (Nëse një imazh pozitiv është gjithashtu i pranishëm brenda grupit të të dhënave të imazhit negativ, ai do të ndikojë në cilësinë e klasifikuesit).

thesis_setup është gjithashtu i dobishëm - kjo vendos që Stellarium të jetë i përshtatshëm për kapjen e imazheve - imazhet e përdorura për të simuluar një pamje nga Hapësira. Ai bën veprime të tilla si fshehja e menutë, linjat e rrjetit, etiketat etj. Automatikisht për t'ju shpëtuar që keni nevojë për çdo herë që dëshironi të kapni një imazh.

Hapi 6: Njeriu raketë

Njeriu raketë
Njeriu raketë

Kaskadat e para që trajnova nuk ishin në gjendje të identifikonin saktë ndonjë model yjesh. Ata ishin shumë të pabesueshëm dhe ishin shumë të prirur ndaj pozitivëve të rremë. Supozimi im ishte se në mënyrë efektive imazhet e fushës së yjeve nga Stellarium (në thelb vetëm pika të bardha në një sfond të zi) thjesht nuk përmbajnë informacion vizual të mjaftueshëm për të përmbajtur mjaft tipare të tipit HAAR për trajnime të suksesshme të klasifikuesve. Unë mendoj se ishte vonë natën, por vendosa të provoj idenë e shkrimit të një programi për të vendosur automatikisht një imazh të vogël të vogël mbi vendndodhjen e secilit yll të ndritshëm në një imazh të fushës së yllit.

Elton

Ky ishte një test budalla, por duke shtuar një fotografi të vogël të fytyrës së Elton John në çdo vend yll të ndritshëm, duke trajnuar klasifikuesin kundër këtij imazhi pozitiv, dhe më pas duke kaskadat kundër imazhit origjinal, ishte shumë më efektive në gjetjen e saktë të modeli i duhur. E dija që po merresha me diçka!

Hapi 7: Shënuesit besimtarë

Shënuesit besimtarë
Shënuesit besimtarë

Edhe pse 'Eltonët' vërtetuan teorinë, më duhej një shënues që kishte simetri të plotë rrotulluese, në mënyrë që modeli i yllit të shfaqet i njëjtë pavarësisht se në çfarë orientimi është paraqitur. Unë testova një sërë llojesh shënues dhe zbulova se lloji në pjesën e poshtme të djathtë ishte më efektivi, me unazat e kundërta bardh e zi. Programi python i paraqitur në dosjen pozitive të repos GitHub tregon se si identifikohen yjet më të ndritshëm në një imazh të caktuar, dhe këta shënues mbivendosen automatikisht në ato pozicione. Ne tani kemi krijuar një përfaqësim të modeleve kryesore të yjeve që mund të stërviten kundër.

Hapi 8: Përdorimi i Kaskadave

Duke përdorur Kaskadat
Duke përdorur Kaskadat

Kur keni trajnuar një sërë kaskadash, duhet të dini se si t'i përdorni ato për të identifikuar një objekt në një imazh!

Shikoni dosjen Star Identification të GitHub, ku do të gjeni programin cascade_test19.py. Ky program me emër tërheqës merr një sërë kaskadash nga një dosje e caktuar dhe i drejton të gjitha kundër një imazhi hyrës dhe raporton për zbulimet e bëra. Funksioni "deteMultiScale" është thelbi i kësaj dhe kërkon një sërë argumentesh që përcaktojnë procesin e zbulimit. Ndryshimi i këtyre është thelbësor për performancën e klasifikuesit të kaskadës, dhe më shumë diskutim për këtë mund të gjendet në hapin vijues, ku ne shikojmë se si të eliminojmë pozitivët e rremë.

Kjo mund të aplikohet në një sistem orientimi satelitor duke e ndërlidhur vlerën e pikselit në qendër të kutisë kufizuese me koordinatën qiellore Ra/Dec të yllit të identifikuar, dhe pastaj ta lidhni këtë me zhvendosjen këndore nga qendra e imazhit (kamera boshti). Nga kjo, duke përdorur një kuptim të shtrembërimit të lenteve (të përafruara me një projeksion gnomonik), këndi i satelitit mund të gjendet vetëm nga dy identifikime pozitive.

Hapi 9: Si të qëndroni pozitivë për pozitivët e rremë

Si të qëndroni pozitivë për pozitivët e rremë
Si të qëndroni pozitivë për pozitivët e rremë
Si të qëndroni pozitivë për pozitivët e rremë
Si të qëndroni pozitivë për pozitivët e rremë

Këto dy imazhe tregojnë rezultatet e testimit të kaskadës të vendosur kundër një imazhi identik, por me parametra të ndryshëm. Shtë e qartë se imazhi i parë përmban identifikimin e vërtetë, por edhe një numër të madh pozitivësh të rremë, ndërsa imazhi i dytë përmban vetëm identifikimin e saktë.

Programi cascade_test19.py brenda dosjes Star Identification të repos GitHub përdor dy metoda për të renditur rezultatet. Së pari, funksioni deteMultiScale përcakton një masë minimale dhe maksimale të rezultatit që mund të gjendet, e cila është e arsyeshme, si madhësia e përafërt e modelit të yllit të synuar brenda dritares (për lentet dhe zmadhimin e dhënë - imazhet e mia të simuluara Stellarium përdorin vetitë e Kamera Raspberry Pi V2) është e njohur. Së dyti, kodi do të zgjedhë rezultatin me kutinë më të madhe kufizuese (brenda kufijve të mëparshëm). Në testimin, kjo u zbulua se ishte pozitive e vërtetë. Së treti, programi përcakton një 'Pesha të nivelit' (efektivisht 'vlerë besimi') që kërkohet për ta trajtuar këtë ID si një pozitiv të vërtetë. Me këtë metodë, kaskadat ishin efektive në gjetjen e rezultatit të saktë.

Përveç imazheve të fushës së yjeve, unë gjithashtu e testova atë kundër fotografive të tavolinës sime, për shembull, duke trajnuar kaskada për të identifikuar fletoren time, filxhanin tim, etj, për të praktikuar eliminimin e pozitivëve të rremë. Metodat e mësipërme funksionuan mirë në të gjitha rrethanat që ishin inkurajuese.

Hapi 10: Diskutim

Diskutimi
Diskutimi
Diskutimi
Diskutimi
Diskutimi
Diskutimi

Fushat për Përmirësim

Ky ka qenë një projekt kompleks për mua, dhe me të vërtetë më shtyu të kuptoj temën. Ai ka përfshirë një total prej disa muajsh punë pothuajse me kohë të plotë për ta çuar projektin në këtë pikë kur mund ta ndaj me ju, por ka shumë punë për të bërë për të përmirësuar performancën e metodës. Siç qëndron, mund të funksionojë mirë brenda kufizimeve të caktuara. Unë kam punuar për të identifikuar se cilat fusha kanë nevojë për punë shtesë dhe shpresoj se do të jem në gjendje të kaloj kohë duke i trajtuar këto në muajt në vijim. Ata janë:

Këndi - Kjo është një zonë komplekse, ideja se rezultatet e klasifikuesve duhet të jenë të pandryshueshme nga ana rrotulluese, domethënë, duhet të identifikojë besueshmërinë modelin e yllit të synuar pavarësisht nga këndi në të cilin paraqitet imazhi që përmban yllin e synuar. Një kaskadë e trajnuar duke përdorur një imazh hyrës në një orientim të vetëm nuk do të jetë në gjendje ta identifikojë atë imazh në orientime të rastësishme, kështu që ndryshimi i këndit pozitiv të figurës duhet të futet në procesin e trajnimit për të trajnuar kaskada që mund të pranojnë një gamë në këndet e hyrjes. Parametri 'maxzangle' në komandat e trajnimit të kaskadës merr një argument në radian, që kontrollon një kufi të këndit që imazhi pozitiv i hyrjes do të mbivendoset në imazhet negative të ofruara, kështu që grupi i imazhit pozitiv që rezulton do të përmbajë një sërë orientimesh të imazhi pozitiv. Sidoqoftë, me rritjen e këtij këndi të madh, raporti i pranimit (në përgjithësi, cilësia) i kaskadës do të ulet ndjeshëm. Unë besoj se zgjidhja është të stërvitësh kaskadat duke përdorur një bazë të dhënash dukshëm më të madhe të imazheve negative sesa ajo që kam përdorur për të siguruar që një klasifikues kaskade me cilësi të mirë mund të krijohet edhe duke përfshirë një përhapje të madhe orientimi.

Një zgjidhje tjetër e mundshme do të ishte trajnimi i një numri kaskadash për një objektiv specifik, secila kaskadë që qeveris një pjesë të caktuar të një rrotullimi të plotë 360 gradë. Në atë mënyrë cilësia e secilës kaskadë mund të ruhet në një nivel të lartë, por nga ana tjetër kjo do të rezultojë në shumë më shumë kaskada, dhe kështu procesi i identifikimit do të jetë më i ngadalshëm.

Parametri 'levelWeight', i cili është një vlerë e siguruar nga funksioni 'deteMultiScale', është analog me një vlerë besimi në zbulimin që është bërë. Duke studiuar këtë, u krijua grafiku i mësipërm, i cili tregon se si besimi në identifikimin pozitiv zvogëlohet ndjeshëm ndërsa orientimi i figurës rritet në secilin drejtim, duke konfirmuar mendimet se kjo është një pikë e dobët.

Vendosja e pikselëve - Një pikë shumë më e thjeshtë, por edhe problematike është ajo e vendosjes së pikselëve, e ilustruar nga dy imazhet e mëposhtme, që tregojnë një pamje të zmadhuar të një imazhi të yllit, në mënyrë që pikselët individualë të dy yjeve të mund të shihen qartë. Procesi i erozionit i përdorur në program për të pastruar të gjithë përveç yjeve më të shndritshëm nga imazhi do të mbajë yllin e parë dhe do ta hedhë të dytin, pavarësisht se ata kanë shkëlqim të barabartë. Arsyeja për këtë është se ylli i parë është i përqendruar në një piksel, ndërsa i dyti nuk është i tillë. Funksioni i erozionit i heq unazat koncentrike të pikselëve nga pikseli qendror i një grupi, dhe kështu ylli i parë do të ketë pikselin qendror të mbijetojë nga funksioni i erozionit, por ylli i dytë do të hiqet plotësisht nga imazhi. Prandaj shënuesit fiducialë do të vendosen vetëm në yllin e parë, dhe jo të dytin. Kjo do të shkaktojë mospërputhje në lidhje me atë se yjet e ndritshëm në një fushë të caktuar yjesh do të marrin shënues (dhe kështu krahasohen me klasifikuesit e trajnuar) - prandaj është e mundur që një vëzhgim i saktë pozitiv të mos jetë i mundur.

Hapi 11: Fjala e fundit

Fjala e fundit
Fjala e fundit

Faleminderit që lexuat udhëzimet e mia, shpresoj se ju duket ky projekt intrigues. Ka qenë një proces shumë interesant duke punuar në të, ka më shumë se një vit që kam filluar të punoj në koncept, dhe jam i inkurajuar nga rezultatet deri në këtë pikë. Nga literatura që kam lexuar, ky është një koncept mjaft origjinal, dhe me më shumë zhvillim sigurisht që mund të aplikohet në një sërë aplikimesh për astronominë amatore ose më shumë.

Ky projekt ishte një kurbë e madhe e të mësuarit për mua, dhe kështu shpresoj që disa lexues me më shumë përvojë programimi mund të frymëzohen për të kontribuar në vazhdimin e projektit përmes faqes GitHub, dhe ne mund të vazhdojmë të zhvillojmë këtë mjet me burim të hapur. Mezi pres të lexoj çdo koment që mund të keni, por ju lutem mos bëni shumë pyetje të vështira!

Sfida Hapësinore
Sfida Hapësinore
Sfida Hapësinore
Sfida Hapësinore

Vrapues në Sfidën Hapësinore

Recommended: