5.6. Desenarea formelor și a textului¶
Un algoritm care decide ceva despre o imagine are adesea nevoie ca acea decizie să fie vizibilă. Un detector de blob găsește o regiune care interesează aplicația; aplicația dorește ca regiunea să fie desenată pe cadru, astfel încât un operator – sau dezvoltatorul care rulează scriptul – să poată vedea ce a fost găsit. O transformare de coordonate mapează o poziție de intrare la una de ieșire; depanarea ei înseamnă de obicei marcarea celor două poziții pe aceeași imagine. Previzualizarea din IDE citește orice se află în tamponul de cadre (frame buffer) în momentul în care interoghează, așa că modul cel mai simplu de a face vizibilă ieșirea algoritmului este să scrii adnotările chiar în tamponul de cadre (frame buffer). Familia de metode de desenare de pe clasa Image este setul de instrumente exact pentru această treabă.
5.6.1. Primitivele¶
Fiecare metodă de desenare plasează un anumit tip de marcaj pe imagine. Catalogul este restrâns și rămâne aproape de primitivele geometrice de care o adnotare are de fapt nevoie:
draw_line()– un segment de linie dreaptă între două capete.draw_rectangle()– un dreptunghi aliniat la axe, gol sau plin.draw_circle()– un cerc în jurul unui centru, gol sau plin.draw_ellipse()– o elipsă cu rotație arbitrară.draw_cross()– un semn plus la un punct, marcajul obișnuit pentru un centroid sau o țintă de clic.draw_arrow()– o săgeată de la un punct de început la un punct de sfârșit.draw_edges()– cele patru laturi ale unui patrulater arbitrar, având cele patru puncte de colț; modul natural de a contura o etichetă detectată sau o regiune deformată în perspectivă.draw_string()– text dintr-un font bitmap încorporat.
Fiecare dintre acestea modifică imaginea sursă pe loc și returnează aceeași imagine pentru înlănțuire, urmând convenția metodelor de operare stabilită mai devreme.
Cele opt primitive de desenare, câte una pe panou. Fiecare metodă creează un tip de marcaj.¶
5.6.2. Culoare¶
Fiecare metodă de desenare primește un argument color care decide ce valoare să scrie în fiecare pixel pictat. Forma pe care o ia acel argument depinde de formatul imaginii. Pentru o imagine RGB565, forma naturală este un tuplu (r, g, b) cu fiecare canal în 0 – 255; modulul îl împachetează în cuvântul RGB565 pe 16 biți înainte de a-l scrie. Pentru o imagine în tonuri de gri, forma naturală este un singur întreg de luminozitate de la 0 (negru) până la 255 (alb). Metodele acceptă, de asemenea, valoarea brută stocată a formatului – un cuvânt împachetat pe 16 biți pentru RGB565, un întreg pe 8 biți pentru tonurile de gri – care este forma eficientă atunci când culoarea a fost calculată în altă parte și se află deja în forma stocată.
Omiterea argumentului color pictează cu alb. Această valoare implicită este convenabilă pentru lucrul în tonuri de gri, unde albul este valoarea maximă și se citește clar pe fundalul majorității fundalurilor. Pentru suprapunerile de depanare RGB565 este aproape întotdeauna greșită: verdele sau roșul se citesc de obicei mai bine pe genul de scenă pe care o cameră o vede de fapt, iar o culoare explicită comunică intenția.
5.6.3. Grosime și umplere¶
Majoritatea metodelor geometrice primesc doi indicatori care decid cum este desenat marcajul:
thickness=Nsetează lățimea liniei în pixeli. Valoarea implicită este1, care este potrivită pentru majoritatea suprapunerilor; o valoare mai mare este utilă când o adnotare trebuie să rămână vizibilă pe o scenă aglomerată sau după ce o etapă ulterioară a fluxului modifică imaginea și mai mult.fill=Truecomută marcajul de la un contur la unul plin, pictând fiecare pixel interior cu culoarea aleasă. Valoarea implicită esteFalse.
Acești indicatori nu se aplică primitivelor care nu au interior de umplut – linia, crucea, săgeata, patrulaterul – unde doar thickness are sens.
5.6.4. Desenarea textului¶
draw_string() scrie caractere dintr-un font bitmap încorporat de 8 pe 10 pixeli. x și y sunt colțul stânga-sus al celulei primului caracter, text este șirul de desenat, iar color urmează aceeași convenție ca metodele geometrice. Fontul acoperă întregul interval ASCII imprimabil și nu are crenelare – fiecare caracter ocupă aceeași celulă de 8 pixeli lățime – ceea ce face ieșirea ușor de poziționat.
img.draw_string(10, 10, "blobs: 3", color=(0, 255, 0))
Șirul poate include caractere de linie nouă (\n); fiecare caracter de linie nouă mută următorul caracter la începutul unei noi linii, cu zece pixeli mai jos decât cea precedentă. Argumentul scale desenează fiecare caracter la o dimensiune mai mare printr-un factor în virgulă mobilă, iar x_spacing și y_spacing adaugă spațiere în jurul fiecărui caracter. Un set mic de indicatori de rotire / oglindire / răsturnare se aplică fie întregului șir, fie fiecărui caracter în parte – suficient control pentru a aranja textul de-a lungul unui unghi sau pe o muchie neorizontală atunci când dispunerea o cere.
5.6.5. Curățarea pânzei¶
O metodă din familie nu desenează niciun marcaj anume. Pur și simplu resetează fiecare pixel al imaginii la zero:
clear()– pune la zero fiecare pixel, opțional restrâns la un ROI sau limitat printr-o mască.
clear() este răspunsul corect atunci când o aplicație compune o adnotare de la zero pentru fiecare cadru – pornește cu o pânză neagră, desenează noile adnotări, predă rezultatul afișajului – în loc să suprapună peste cadrul capturat. Este, de asemenea, cea mai ieftină modalitate de a pregăti o imagine temporară pentru utilizare ca tampon de mască.
O imagine proaspăt alocată este deja zero de la constructor, așa că clear() contează în mod specific pentru tampoanele reutilizate între cadre.