5.6. Vormen en tekst tekenen¶
Een algoritme dat iets over een afbeelding beslist, moet die beslissing vaak zichtbaar maken. Een blobdetector vindt een gebied waar de toepassing om geeft; de toepassing wil dat gebied op het frame getekend hebben zodat een operator – of de ontwikkelaar die het script uitvoert – kan zien wat er is gevonden. Een coördinatentransformatie zet een invoerpositie om naar een uitvoerpositie; debuggen betekent meestal dat de twee posities op dezelfde afbeelding worden gemarkeerd. Het IDE-voorbeeld leest wat er op het moment van peilen in de framebuffer staat, dus de eenvoudigste manier om algoritme-uitvoer zichtbaar te maken is annotaties in de framebuffer zelf te schrijven. De teken-familie op de klasse Image is de toolkit voor precies dat werk.
5.6.1. De primitieven¶
Elke tekenmethode plaatst één specifieke soort markering op de afbeelding. De catalogus is klein en blijft dicht bij de geometrische primitieven die een annotatie daadwerkelijk nodig heeft:
draw_line()– een recht lijnsegment tussen twee eindpunten.draw_rectangle()– een asgerichte rechthoek, hol of gevuld.draw_circle()– een cirkel rond een middelpunt, hol of gevuld.draw_ellipse()– een ellips met willekeurige rotatie.draw_cross()– een plusteken op een punt, de gebruikelijke markering voor een zwaartepunt of een klikdoel.draw_arrow()– een pijl van een startpunt naar een eindpunt.draw_edges()– de vier zijden van een willekeurige vierhoek, gegeven de vier hoekpunten; de natuurlijke manier om een gedetecteerde tag of een perspectivisch vervormd gebied te omlijnen.draw_string()– tekst uit een ingebouwd bitmaplettertype.
Elk van deze wijzigt de bronafbeelding ter plaatse en retourneert dezelfde afbeelding voor ketening, volgens de eerder vastgelegde conventie van operatiemethoden.
De acht tekenprimitieven, één per paneel. Elke methode maakt één soort markering.¶
5.6.2. Kleur¶
Elke tekenmethode neemt een color-argument dat bepaalt welke waarde in elke geschilderde pixel wordt geschreven. De vorm die dat argument aanneemt, hangt af van het formaat van de afbeelding. Voor een RGB565-afbeelding is de natuurlijke vorm een (r, g, b)-tuple met elk kanaal in 0 – 255; de module pakt dat in tot het 16-bit RGB565-woord voordat het wordt geschreven. Voor een grijswaardenafbeelding is de natuurlijke vorm een enkel geheel getal voor de helderheid van 0 (zwart) tot 255 (wit). De methoden accepteren ook de ruwe opgeslagen waarde van het formaat – een 16-bit ingepakt woord voor RGB565, een 8-bit geheel getal voor grijswaarden – wat de efficiënte vorm is wanneer de kleur elders is berekend en al in de opgeslagen vorm staat.
Het weglaten van het color-argument schildert wit. Die standaard is handig voor grijswaardenwerk, waar wit de maximale waarde is en duidelijk afsteekt tegen de meeste achtergronden. Voor RGB565-debugoverlays is het bijna altijd verkeerd: groen of rood steekt meestal beter af tegen het soort scène dat een camera daadwerkelijk ziet, en een expliciete kleur communiceert intentie.
5.6.3. Dikte en vulling¶
De meeste geometrische methoden nemen twee vlaggen die bepalen hoe de markering wordt getekend:
thickness=Nstelt de lijnbreedte in pixels in. De standaard is1, wat prima is voor de meeste overlays; een grotere waarde is handig wanneer een annotatie zichtbaar moet blijven tegen een drukke scène of nadat een volgende fase van de pijplijn de afbeelding verder wijzigt.fill=Trueschakelt de markering van een omtrek naar een gevulde, waarbij elke binnenpixel met de gekozen kleur wordt geschilderd. De standaard isFalse.
Deze vlaggen zijn niet van toepassing op de primitieven die geen interieur hebben om te vullen – de lijn, het kruis, de pijl, de vierhoek – waar alleen thickness betekenisvol is.
5.6.4. Tekst tekenen¶
draw_string() schrijft tekens uit een ingebouwd bitmaplettertype van 8 bij 10 pixels. x en y zijn de hoek linksboven van de cel van het eerste teken, text is de te tekenen tekenreeks, en color volgt dezelfde conventie als de geometrische methoden. Het lettertype bevat het volledige afdrukbare ASCII-bereik en heeft geen kerning – elk teken neemt dezelfde 8 pixels brede cel in – wat de uitvoer eenvoudig te positioneren maakt.
img.draw_string(10, 10, "blobs: 3", color=(0, 255, 0))
De tekenreeks kan nieuwe regels bevatten (\n); elke nieuwe regel verplaatst het volgende teken naar het begin van een nieuwe regel tien pixels onder de vorige. Het scale-argument tekent elk teken op een groter formaat met een floating-point-factor, en x_spacing en y_spacing voegen opvulling rond elk teken toe. Een kleine set roteer-/spiegel-/omkeervlaggen wordt toegepast op de hele tekenreeks of op elk teken afzonderlijk – genoeg controle om tekst onder een hoek of tegen een niet-horizontale rand uit te leggen wanneer de lay-out dat vereist.
5.6.5. Het canvas wissen¶
Eén methode in de familie tekent geen specifieke markering. Hij zet eenvoudigweg elke pixel van de afbeelding terug op nul:
clear()– zet elke pixel op nul, optioneel beperkt tot een ROI of begrensd via een masker.
clear() is het juiste antwoord wanneer een toepassing elk frame een annotatie helemaal opnieuw samenstelt – begin met een zwart canvas, teken de nieuwe annotaties en geef het resultaat door aan het scherm – in plaats van te overlayen boven op het vastgelegde frame. Het is ook de goedkoopste manier om een tijdelijke afbeelding voor te bereiden voor gebruik als maskerbuffer.
Een net toegewezen afbeelding is al nul vanaf de constructor, dus clear() doet er specifiek toe voor buffers die tussen frames worden hergebruikt.