5.6. Crtanje oblika i teksta

Algoritam koji nešto odluči o slici često treba da ta odluka bude vidljiva. Detektor mrlja pronalazi područje do kojeg je aplikaciji stalo; aplikacija želi da se to područje nacrta na sličici kako bi operater – ili razvojni programer koji pokreće skriptu – mogao vidjeti što je pronađeno. Koordinatna transformacija preslikava ulazni položaj u izlazni; otklanjanje pogrešaka u njoj obično znači označavanje dvaju položaja na istoj slici. Pretpregled u IDE-u čita što god se nalazi u međuspremniku slike u trenutku kada ga ispituje, pa je najjednostavniji način da izlaz algoritma postane vidljiv upisivanje napomena u sam međuspremnik slike. Skupina za crtanje u klasi Image upravo je alat za taj posao.

5.6.1. Primitivi

Svaka crtaća metoda postavlja jednu određenu vrstu oznake na sliku. Katalog je malen i drži se blizu geometrijskih primitiva koji su napomeni zapravo potrebni:

  • draw_line() – ravni segment linije između dviju krajnjih točaka.

  • draw_rectangle() – pravokutnik poravnat s osima, prazan ili ispunjen.

  • draw_circle() – kružnica oko središta, prazna ili ispunjena.

  • draw_ellipse() – elipsa s proizvoljnom rotacijom.

  • draw_cross() – znak plus u nekoj točki, uobičajena oznaka za težište ili metu klika.

  • draw_arrow() – strelica od početne do krajnje točke.

  • draw_edges() – četiri stranice proizvoljnog četverokuta, zadane četirima kutnim točkama; prirodan način za ocrtavanje detektirane oznake ili perspektivno iskrivljenog područja.

  • draw_string() – tekst iz ugrađenog bitmapnog fonta.

Svaka od ovih mijenja izvornu sliku na mjestu i vraća istu sliku radi ulančavanja, slijedeći konvenciju operativnih metoda uspostavljenu ranije.

Mreža malih ploča koja prikazuje svaki od osam crtaćih primitiva primijenjen jednom. Svaka ploča sadrži liniju, pravokutnik, kružnicu, elipsu, križić, strelicu, četverokut ili kratak tekstualni niz, s imenom metode koja ga je proizvela označenim ispod.

Osam crtaćih primitiva, jedan po ploči. Svaka metoda stvara jednu vrstu oznake.

5.6.2. Boja

Svaka crtaća metoda prima argument color koji odlučuje koju vrijednost upisati u svaki oslikani piksel. Oblik koji taj argument poprima ovisi o formatu slike. Za RGB565 sliku prirodan je oblik n-torka (r, g, b) sa svakim kanalom u rasponu 0255; modul to pakira u 16-bitnu RGB565 riječ prije upisivanja. Za sliku u sivim tonovima prirodan je oblik jedan cijeli broj svjetline od 0 (crno) do 255 (bijelo). Metode također prihvaćaju sirovu pohranjenu vrijednost formata – 16-bitnu pakiranu riječ za RGB565, 8-bitni cijeli broj za sive tonove – što je učinkovit oblik kada je boja izračunata drugdje i već je u pohranjenom obliku.

Izostavljanje argumenta color oslikava bijelo. Ta je zadana postavka prikladna za rad sa sivim tonovima, gdje je bijelo najveća vrijednost i jasno se čita na većini pozadina. Za RGB565 preklope za otklanjanje pogrešaka gotovo je uvijek pogrešna: zelena ili crvena obično se bolje čitaju na vrsti scene koju kamera zapravo vidi, a eksplicitna boja prenosi namjeru.

5.6.3. Debljina i ispuna

Većina geometrijskih metoda prima dvije zastavice koje odlučuju kako se oznaka crta:

  • thickness=N postavlja širinu linije u pikselima. Zadana vrijednost je 1, što je u redu za većinu preklopa; veća vrijednost korisna je kada napomena mora ostati vidljiva na užurbanoj sceni ili nakon što sljedeća faza cjevovoda dodatno izmijeni sliku.

  • fill=True prebacuje oznaku iz obrisa u punu, oslikavajući svaki unutarnji piksel odabranom bojom. Zadana vrijednost je False.

Te se zastavice ne primjenjuju na primitive koji nemaju unutrašnjost za ispunu – liniju, križić, strelicu, četverokut – gdje je smislena samo thickness.

5.6.4. Crtanje teksta

draw_string() ispisuje znakove iz ugrađenog bitmapnog fonta veličine 8 puta 10 piksela. x i y su gornji lijevi kut ćelije prvog znaka, text je niz koji se crta, a color slijedi istu konvenciju kao geometrijske metode. Font nosi cijeli ispisivi ASCII raspon i nema podrezivanja (kerning) – svaki znak zauzima istu ćeliju širine 8 piksela – što olakšava pozicioniranje izlaza.

img.draw_string(10, 10, "blobs: 3", color=(0, 255, 0))

Niz može sadržavati nove retke (\n); svaki novi redak pomiče sljedeći znak na početak novog retka deset piksela ispod prethodnog. Argument scale crta svaki znak u većoj veličini prema decimalnom faktoru, a x_spacing i y_spacing dodaju razmak oko svakog znaka. Mali skup zastavica za rotaciju / zrcaljenje / preokretanje primjenjuje se ili na cijeli niz ili na svaki znak zasebno – dovoljno kontrole za raspoređivanje teksta uzduž kuta ili uz nehorizontalni rub kada raspored to zahtijeva.

5.6.5. Čišćenje platna

Jedna metoda u skupini ne crta nikakvu određenu oznaku. Samo poništava svaki piksel slike na nulu:

  • clear() – ponuli svaki piksel, neobavezno ograničeno na ROI ili obuhvaćeno maskom.

clear() je pravi odgovor kada aplikacija slaže napomenu iznova za svaku sličicu – počni s crnim platnom, nacrtaj nove napomene, predaj rezultat zaslonu – umjesto preklapanja povrh snimljene sličice. To je također najjeftiniji način za pripremu privremene slike za korištenje kao međuspremnik maske.

Tek alocirana slika već je nula iz konstruktora, pa je clear() bitan posebno za međuspremnike ponovno korištene između sličica.