Blokezko selfieak

Galdera-eragilea

Selfieak eguneroko kontua dira dagoeneko, mainstream dira. Eragin-sortzaileek edo influencerrek arrakasta handiarekin zabaldu ohi dituzte sare sozialetan. Nork bere buruari ateratako irudi-bildumak dira, baliabide grafikoak asteburuetan eta lagun artean egindakoa, ikusitakoa, jandakoa zein jantzitakoa erakusteko. Handinahi horretan, zergatik ez erakutsi selfie horiek Minecraften ere? Blokeetan adierazteak ez ote ditu kaltetuko irudi panpoxo horiek...

Aurrekariak

Pi Camera argazki-makina erabiliz ikasiko dugu bereizmen baxuko argazkiak ateratzen eta programatzen. Gailu merkea izan arren, argazkiak telefonoarekin atera daitezke, eta, ondoren, softwarea erabili bereizmena jaisteko. Gainontzekoa Pythoni dagokio: blokezko baliokidea sortzeko irudia bihurtzea, alegia.

Eskema

Pi Camerak etengailurik ez duenez, aurretik programatu behar da selfiea ateratzeko une zehatzaren agindua. Pythonek, era berean, irudia bihurtu egiten du eta blokeekin adierazten da Minecrafteko horma erraldoi batean. Hala ere, RGB koloreak asko direnez eta Minecrafteko blokeak gutxi, komeni da kolore antzekoena duten blokeekin adierazteko baliokidea bilatzea; hau da, pixel bakoitza osatzeko, batez besteko kolorea antzerakoena duen blokearekin ordeztu behar da. Aldendu eta begiratzean lortu nahi da jatorrizkoaren ahalik eta antzik handiena izatea; itxura ematea beste aukerarik ez dago, blokeak baitira Minecraften adierazteko unitate txikiena.

Aukeratzen den teknika aukeratzen dela, alderatu egiten dira jatorrizko RGB koloreen balioak eta Minecrafteko bloke bakoitzaren batez besteko kolorearen RGB balioak. Mapatzea deitzen zaio horri, koloreak eskema zehatzean kokatzen baitira.

Softwarea instalatzea

Irudiekin lan egiteko behar diren elementuak instalatzeko, idatzi honako hau terminalean (administratzaile kontuko pasahitza eskatzen du; gogoratu raspberry dela lehenetsitako pasahitz hori):

sudo pip3 install python3-skimage

Beste liburutegiekiko mendekotasunak

Liburutegiak dira antzerako helburuak dituzten funtzioak, aldagaiak, konstanteak eta bestelakoak dituzten biltegiak. Izenez bereizten dira eta barruan dutena berrerabiltzeko aukera emateaz gain, erronka berriei ekiteko denbora irabazten da eta ez dago hutsetik programatzen hasi beharrik.

Liburutegiak erabiltzen hasteko, izenak programaren goiburuan aipatu behar dira. Hala, idatzitakoa exekutatzean, lerroz lerro aginduak irakurtzen dituen exekuzio-fluxua iturburuko fitxategira zuzendu daiteke (salto egiten duela ere esaten zaio), eta, gainera, kanpoko funtzioa bete dezake dagoen lekuan bertan eskatutako kodea irakurrita (erreferentzia egindako liburutegian). Hori guztia betetzean, fluxua hasierako fitxategira itzultzen da, utzitako lekuari heldu eta exekuzioarekin jarraitzeko. Izan ere, erreferentzia hori gabe, fluxuak ez du jakiten non bilatu eta programa bertan behera uzten du unean bertan, akatsa adierazita. Horregatik esaten da liburutegiak erabiltzen dituzten kodeek liburutegi horiekiko menpekotasuna dutela.

Proiektu honetan ere moduluak inportatu behar dira. Raspbianek instalatuta dakartza denak, bat izan ezik, eta hortaz, nahikoa da erreferentzia zehaztearekin. Falta den modulua, skimage izenekoa, aurretik instalatu behar da.

Honezkero garaia da fitxategi berri bat sortu eta arestian aipatutako moduluekin lanean hasteko: ireki Python 3 (IDLE), menuan Programazioa atalean bilatuta. Sortu fitxategi berri bat File > New File aukerari sakatuta, eta erantsi lerro hauek:

from picamera import PiCamera
from mcpi.minecraft import Minecraft
from time import sleep
from skimage import io, colora

Gorde fitxategia minecraft_selfies.py izenarekin eta exekutatu (egin menutik edo F5 sakatu botoia). Hala egiaztatzen da behar direnr modulu guztiak daudelall,. Oraindik egin ez baduzu, garaiz zabiltza Git atala irakurtzeko eta hemen aplikatzen hasteko!

Selfien sasoia: pa-ta-ta!

Pi Camerarekin selfie bat ateratzeko, xehetasun guztiekin programatzeko agindua eman behar da (gogoratu ez duela etengailurik): halako edo bestelako bereizmena ezarri, aurrebista erakutsi edo ez, zenbat itxaron, sistemako zein lekutan gorde emaitza...

Arestian hasitako kodean erantsi behar dira beste bi lerro hauek ere. Kamerarekin egin daitezkeen eragiketak objektu batean gordetzen dira (kamera). Hainbat kamera sor litezke, ezarpen desberdinekin doituta eta izenez bereizita: "kamera1", "kamera2"... Objektuaren instantziak deitzen zaie:

kamera = PiCamera()
kamera.resolution = (80,60)

Bereizmen handiagoaz erabiltzerik ere badago (80 x 60 pixel oso txikia da), baina astunegia izan daiteke Raspberry makina apalak Minecraftera bihurtzeko.

Hurrena da kamerari nola jardun agintzea, eta, horretarako, idatzi beste hau ere programan:

kamera.start_preview()
sleep(5)
kamera.capture('selfie.jpg')
kamera.close()

Bukatzeko, gorde, jarri scripta martxan eta atera selfieak taldean edo banaka. Idatzitakoaren arabera eginez gero, script fitxategia dagoen leku berean agertuko da. Ez harritu txiki-txikia bada, nahita agindu baitzaio.

Koloredun pixeletatik blokeetara mapatzea

Deskargatu irudi hau eta gorde Python fitxategiaren leku berean. Irudi izugarri txikia da (7 x 7 pixel baino ez), baina hurbilduz gero, honako itxura hau dauka:

Kolore-mapako pixel bakoitzak adierazten du Minecrafteko bloke baten batez besteko kolorea. Esate baterako, goiko ezkerrekoak adierazten du lokatz blokearena. Hona hemen horietako bakoitzaren baliokideak nola ezarri diren:

Bi irudiak kargatu behar dira programan, selfiea zein kolore-mapa. Baina nola liteke irudi bat testu gisa sartzea? Bihurketa hori egiteko instalatzen da skimage modulua. Hau txertatu eta hura konpon dadila:

selfie_rgb = io.imread("selfie.jpg")
mapa_rgb = io.imread("colour_map.png")

Orain arte idatzitakoa exekutatzean ikusten dira objektu horiek gordetzen dituzten irudien zenbakizko baliokideak. Egin deia aldagaiari izenetik deituz:

>>> mapa_rgb

Hona hemen ikusten denaren lagin bat:

array([[[ 86,  74,  46],
        [ 93,  69,  49],
        [ 90,  87,  87],
        [ 99,  84,  65],
        [ 74,  73,  68],
        [108, 105,  95],
        [106,  95,  87]],

Zenbaki multzo hori (matrizea, matematikan) kolore-mapako koloreen adierazpen bat baino ez da. Esaterako, lehen lerroak adierazten du 86, 74, 46 kolore-mapako aurreneko pixela. Izan ere, erreferentziak egiteko hiru zenbaki erabiltzen dira, bakoitzak kolore baten kopurua adierazten du eta hiruren nahasketatik sortzen den kolorea adierazten dute. Ezkerretik eskuinera, gorria, berdea eta urdina (RGB edo Red, Green, Blue). Kasu horretan eta neurri horietan, emaitza marroia da.

Era berean, selfieak dituen pixelen koloreak ikus daitezke, IDLE agindu-lerroan honela idatzita:

>>> selfie_rgb

Hasteko, aintzat hartu behar da Minecrafteko blokeek ez dituztela edozein irudik izan ditzakeen koloreak, blokeak gutxi eta koloreak asko direlako. Horregatik, gogoan izan kolore-mapa erabiltzen dela Minecraften sortu nahi dugun irudi baliokidea osatuko duten blokeak zein izango diren aukeratzeko. Beste modu batera esanda, banan-banan hartzen dira selfie_rgb aldagaiak dituen RGB koloreak eta kolore-mapako kolorerik antzerakoena egokitzen zaie. Hala hautatzen da blokezko pixelak sortzeko baliokidea Minecraften bloke batekin haren lekuan jartzeko.

Antzeko koloreen bila

Azpiatal honetan dagoenari nondik heldu ez badakizu edo zailegia egiten bazaizu, egin jauzi hurrengora. Egiten dena zergatik egiten den jakin ezean, guztia da magikoagoa, baina tira.

Kolore bakoitza, esanda bezala, hiru zenbakik adierazten dute. Hortaz, grafiko batean adieraz daiteke kolore baten kokapena, ardatz bakoitza RGB hirukotetik eskuratzean. Hona hemen hiru ardatzeko edo 3D grafiko batean adierazita R-137, G-164, B-123 kolorea:

Minecrafteko blokeen koloreak grafiko berean adierazteak lagundu egiten du kolore hori zein blokerekin ordezkatu aukeratzen: modurik arruntena da grafikoan gertuen duen beste puntu batekoarekin adieraztea. Baina, hala ere, ikusi grafiko hau (puntu txikiagoekin blokeen mapa koloreak adierazi dira, eta lodiz, jatorrizkoa):

RGB balioak koloreak adierazteko oso erabilgarriak diren arren, tamalez, ez dute hainbeste laguntzen balioak konparatzen. Bestela, erreparatu adibide honi:

Grafiko horretan ikusten da elkarrengandik urruti daudela puntu gris argia eta gris iluna (173 unitatera), eta, aldiz, biak ala biak gorritik gertuago daudela (bakoitzetik 150 unitatera). Nabarmena denez, eta koloreei begiratuta soilik, grisek elkarrengandik gertuago behar lukete gorritik baino. Hortaz, RGB balioak 3D grafikoetan adieraztean, gertu dauden balioek oso itxura desberdina izan dezakete errealitatean, nahiz eta adierazpen matematikoan antzekoenak izan.

Hori dela eta, Lab kolore-espazioa erabiltzen da: RGB bidez adierazitako koloreak eskema berrira itzultzean, sumatzen ditugun eran ordenatzen dira, eta, bihurtu ostean, antzerakoak izaten dira grafikoan bata bestearengandik gertu dauden koloreak.

Lab kolore-espaziora bihurtzea

skimage moduluak (hots, liburutegiak) laguntzen du RGB balioak Lab kolore-espaziora moldatzen. Horretarako, gehitu kodean bi lerro hauek, eta kito:

selfie_lab = color.rgb2lab(selfie_rgb)
map_lab = color.rgb2lab(map_rgb)

Hala, zuzen alderatzen dira bi aldagai berri horietan gordetako balioak, eta behingoz, grafikoan gertuen dauden balioak hautatu daitezke antzerako blokeekin ordezkatzeko.

Selfiea bloketan mapatzea

Heldu da kolore-mapako pixelak Minecrafteko blokeekin mapatzeko garaia. Matrize bat erabiltzen da gordailu edo euskarri gisa.

Minecrafteko blokeak balio birekin definitzen dira. Lokatza, esate baterako, honela adierazten da: 2,0. Koma osteko balioak blokearen egoera adierazten du (kasu honetan, lokatza era bakarrean egoten da). Artilearen kasuan, besteak beste, bigarren balio horren bidez adierazten da kolorea: 35,0tik hasi eta 35,15eraino dauden artile motak zehazten dira.

Lan nekeza arintzearren, eskura dago kolore-maparen pixel bakoitzaren adierazpena, dagokion Minecrafteko blokearekin mapatuta. Hots, aurreko pixeldun irudiaren baliokide matematikoa da honako hau. Kopiatu eta erantsi programan hemengo matrize hau:

koloreak={(0,0):(2,0),(0,1):(3,0),(0,2):(4,0),(0,3):(5,0),(0,4):(7,0),(0,5):(14,0),(0,6):(15,0),(1,0):(16,0),(1,1):(17,0),(1,2):(21,0),(1,3):(22,0),(1,4):(24,0),(1,5):(35,0),(1,6):(35,1),(2,0):(35,2),(2,1):(35,3),(2,2):(35,4),(2,3):(35,5),(2,4):(35,6),(2,5):(35,7),(2,6):(35,8),(3,0):(35,9),(3,1):(35,10),(3,2):(35,11),(3,3):(35,12),(3,4):(35,13),(3,5):(35,14),(3,6):(35,15),(4,0):(41,0),(4,1):(42,0),(4,2):(43,0),(4,3):(45,0),(4,4):(46,1),(4,5):(47,0),(4,6):(48,0),(5,0):(49,0),(5,1):(54,0),(5,2):(56,0),(5,3):(57,0),(5,4):(58,0),(5,5):(60,0),(5,6):(61,0),(6,0):(73,0),(6,1):(79,0),(6,2):(80,0),(6,3):(82,0),(6,4):(89,0),(6,5):(103,0),(6,6):(246,0)}

Dagoeneko funtzionamendua ikusi daiteke. Egikaritu kodea, eta sakatu hau agindu-lerroan:

>>> koloreak[(0, 0)]

(2,0) jaso behar luke, hau da, lokatz-blokea. Beste honekin, aldiz, artile marroia (35, 12):

>>> koloreak[(3, 3)]

Minecrafteko horma-irudia

Bukatzeko, Minecraften blokeak ezartzea baino ez da falta. Hasieran, jarri erreferentzia Minecrafteko APIra sarbidea eskatzeko, eta jaso honela jokalariaren uneko kokapena:

mc = Minecraft.create()
x, y, z = mc.player.getPos()

Nahas-mahaskeria garbitzen hasteko, arestiko selfie_lab aldagaia osorik zeharkatu eta balio bakoitzaren posizioa gordetzen da enumerate funtzioaren bidez. Ondoren, honela berreraikitzen da selfiea:

for i, selfie_zutabe in enumerate(selfie_lab):
     for j, selfie_pixel in enumerate(selfie_zutabe):
         distantzia = 300

Batetik, jatorrizko selfiearen pixel bakoitzetik igarotzen da exekuzioan interpretatzailea eta selfie_pixel aldagaian gordetzen ditu ondoren alderatzeko koloreen balioak. Beste modu batera esanda, matrizeko balioak banaka aztertzen dira eta, sekuentzia bat bailitzan, balio bakoitzetik banaka igarotzen da exekuzio-fluxua. Begiztaren buelta edo iterazio bakoitzean, gehienezko distantzia 300 unitatera hasieratzen du (hasieran atera den argazkiaren arabera, betiere). Eta bestetik, i eta j aldagaietan gordetzen ditu pixel bakoitzaren koordenatuak.

Horixe bera egiten da kolore mapako pixel bakoitzarekin:

         for k, map_zutabe in enumerate(map_lab):
             for l, map_pixel in enumerate(map_zutabe):

Azkenik, bateko zein besteko koloreen arteko distantziak kalkulatzen dira:

                 delta = color.deltaE_ciede2000(selfie_pixel,map_pixel)

Balioak alderatu behar dira hurrena: delta txikiagoa bada uneko distantzia baino, distantzia aldagaiak haren balioa jasotzen du eta, bide batez, ezarri beharreko blokearen balioa jasotzen da aurretik sortutako matrizean begiratuta:

                 if delta < distantzia:
                     distantzia = delta
                     blokea = koloreak[(k,l)]

Bukatzeko, ezarri bloke baliokidea egiteko agindua azken begiztaren eraginetik kanpo. Alexen buru gainean eta lurretik urruti jarri, ondo ikusteko eran. Adibidez:

        mc.setBlock(x-j, y-i+60, z+5, blokea[0], blokea[1])

Beraz, honela jaso behar dira aurreko pusketa guztiak batera:

for i, selfie_zutabe in enumerate(selfie_lab):
     for j, selfie_pixel in enumerate(selfie_zutabe):
         distantzia = 300
         for k, map_zutabe in enumerate(map_lab):
             for l, map_pixel in enumerate(map_zutabe):
                 delta = color.deltaE_cie76(selfie_pixel,map_pixel)
                 if delta < distantzia:
                     distantzia = delta
                     blokea = koloreak[(k,l)]
         mc.setBlock(x-j, y-i+60, z+5, blokea[0], blokea[1])

Abiatu kodea eta ikusi zer jasotzen den. Ez da bizkorra izango, pazientzia izan! Blokeak agertu ahala osatuko da irudia.

Bertsio berriak: hobekuntzak

    • Doitu kodea irudia sortzeko, baina RGB koloreekin alderaketak eginda (utzi Lab kolore-espazioa alde batera). Alde handia al dago? Zergatik?