Ausschnitt fuer die Sammlung weiter fassen
Christian ueber seine erste Amsel: "Der Zuschnitt der Fotos ist auch etwas merkwuerdig." Er hatte recht -- in der Kachel war nur Gefieder zu sehen, Kopf und Schwanz lagen ausserhalb. URSACHE: Derselbe enge Ausschnitt diente zwei Zwecken. Fuer den Klassifikator ist eng richtig, jedes Stueck Hintergrund verwaessert die Bestimmung. Fuer die Sammlung ist eng falsch: Dort steht das Bild in einer fast quadratischen Kachel, und die schneidet weg, was ueber das Quadrat hinausragt. Bei einem Vogel im Hochformat -- und so sitzt fast jeder -- bleibt die Bauchmitte uebrig, formatfuellend und unscharf. Neu: Box.anzeige_ausschnitt, quadratisch und mit mehr Rand. Was die Kachel abschneidet, ist jetzt Umgebung statt Vogel. `crop` bleibt unveraendert -- die Artbestimmung ist gemessen und soll so bleiben. An Christians echter Amsel geprueft: vorher 446x857 (Verhaeltnis 0,52), nachher 1176x1175. Im Vergleichsbild sitzt der ganze Vogel auf dem First statt einer Nahaufnahme des Bauchs. 5 Tests, auch fuer Voegel am Bildrand (sonst sitzt der Vogel ausserhalb seiner eigenen Kachel). 136 Detector-Tests gruen.
This commit is contained in:
1 parent
f7184d193c
commit
93f209ca12
4 files changed
+124
-2
No files matched your search
@@ -885,3 +885,75 @@ class UebernimmTests(unittest.TestCase):
|
||||
from detector.species_de import catalog
|
||||
|
||||
self.assertEqual(self.pipeline.uebernimm(arten=catalog({"garten"})), [])
|
||||
|
||||
|
||||
class AnzeigeAusschnittTests(unittest.TestCase):
|
||||
"""🔑 Der Klassifikator und das Auge wollen Verschiedenes.
|
||||
|
||||
``crop`` liegt eng am Vogel, weil Hintergrund die Bestimmung verwaessert.
|
||||
In der fast quadratischen Kachel der Sammlung schneidet genau das links
|
||||
und rechts den Vogel weg — bei einem Vogel im Hochformat bleibt die
|
||||
Bauchmitte uebrig. Christian am 14.10.2026: „Der Zuschnitt der Fotos ist
|
||||
auch etwas merkwuerdig."
|
||||
"""
|
||||
|
||||
def bild(self, groesse=(1800, 2400)):
|
||||
from PIL import Image
|
||||
|
||||
return Image.new("RGB", groesse, (120, 160, 200))
|
||||
|
||||
def test_anzeige_ist_quadratisch(self):
|
||||
from detector.classify import Box
|
||||
|
||||
# Ein hochkant sitzender Vogel, schmal und hoch.
|
||||
box = Box(x0=0.40, y0=0.30, x1=0.52, y1=0.62, score=0.9)
|
||||
im = self.bild()
|
||||
eng = box.crop(im)
|
||||
anzeige = box.anzeige_ausschnitt(im)
|
||||
|
||||
self.assertLess(eng.width / eng.height, 0.7, "Testbox ist nicht hochkant")
|
||||
self.assertAlmostEqual(anzeige.width / anzeige.height, 1.0, places=1)
|
||||
|
||||
def test_anzeige_enthaelt_den_ganzen_vogel(self):
|
||||
from detector.classify import Box
|
||||
|
||||
box = Box(x0=0.40, y0=0.30, x1=0.52, y1=0.62, score=0.9)
|
||||
im = self.bild()
|
||||
anzeige = box.anzeige_ausschnitt(im)
|
||||
# Mindestens so hoch wie der Vogel plus Rand.
|
||||
vogel_hoehe = (0.62 - 0.30) * im.height
|
||||
self.assertGreater(anzeige.height, vogel_hoehe)
|
||||
|
||||
def test_crop_bleibt_unveraendert_eng(self):
|
||||
"""Die Artbestimmung ist gemessen und darf sich nicht mitaendern."""
|
||||
from detector.classify import Box
|
||||
|
||||
box = Box(x0=0.40, y0=0.30, x1=0.52, y1=0.62, score=0.9)
|
||||
im = self.bild()
|
||||
eng = box.crop(im)
|
||||
erwartet_breite = (0.52 - 0.40) * im.width * 1.24 # pad 0.12 beidseits
|
||||
self.assertAlmostEqual(eng.width, erwartet_breite, delta=3)
|
||||
|
||||
def test_am_bildrand_bleibt_der_ausschnitt_im_bild(self):
|
||||
"""⚠️ Sonst sitzt ein Vogel am Rand ausserhalb seiner eigenen Kachel."""
|
||||
from detector.classify import Box
|
||||
|
||||
im = self.bild()
|
||||
for box in (
|
||||
Box(x0=0.00, y0=0.00, x1=0.08, y1=0.10, score=0.9),
|
||||
Box(x0=0.92, y0=0.90, x1=1.00, y1=1.00, score=0.9),
|
||||
):
|
||||
with self.subTest(box=box):
|
||||
a = box.anzeige_ausschnitt(im)
|
||||
self.assertGreater(a.width, 0)
|
||||
self.assertLessEqual(a.width, im.width)
|
||||
self.assertLessEqual(a.height, im.height)
|
||||
self.assertAlmostEqual(a.width / a.height, 1.0, places=1)
|
||||
|
||||
def test_winziges_bild_sprengt_nichts(self):
|
||||
from detector.classify import Box
|
||||
|
||||
im = self.bild((60, 40))
|
||||
a = Box(x0=0.3, y0=0.3, x1=0.7, y1=0.7, score=0.9).anzeige_ausschnitt(im)
|
||||
self.assertLessEqual(a.width, 60)
|
||||
self.assertLessEqual(a.height, 40)
|
||||
Reference in new issue
Block a user