5.25. Noktaları bulma

Eşikleme, yakalanan çerçeveyi ikili bir maskeye dönüştürdü: her piksel ya eşik testini geçer ya da geçmez. Bu, uygulamanın önemsediği renklerin sahnede görünüp görünmediği sorusunu yanıtlar, ancak nerede olduğunu değil – maske yalnızca 1’lerden ve 0’lardan oluşan bir denizdir. Bir sonraki adım nokta (blob) tespitidir: maskede gezinmek, geçen piksellerden oluşan bitişik bölgeleri bulmak ve her birini bir konum, bir boyut, bir yönelim ve bir uygulamanın üzerine işlem yapabileceği diğer özelliklere sahip bir nesne olarak döndürmek.

find_blobs(), bu adımın iş gücü metodudur ve image modülünün sonuç-nesnesi dünyasına en yaygın giriş noktasıdır. Renkli bir topu izlemek, zemine boyanmış bir çizgiyi takip etmek, bir termal sensörün gördüğü parlak nokta sayısını saymak, mavi bir LED’in açık mı kapalı mı olduğuna karar vermek – aynı çağrı bunların hepsini kapsar. Girdiler değişir (eşikler, aranan bölge, sonuca uygulanan filtreler), ancak çağrı deseni aynıdır.

5.25.1. Temel çağrı

find_blobs bir eşik listesi alır ve bir nokta sonuç nesneleri listesi döndürür:

thresholds = [(30, 100, 15, 127, 15, 127)]  # LAB threshold for red
blobs = img.find_blobs(thresholds)

for b in blobs:
    img.draw_rectangle(b.rect, color=(255, 0, 0))
    img.draw_cross(b.cx, b.cy, color=(255, 0, 0))

Her eşik demeti, binary() metoduna geçirilen eşiklerle aynı biçime sahiptir – bir RGB565 görüntüsü için altı giriş (l_lo, l_hi, a_lo, a_hi, b_lo, b_hi) (sınırlar LAB cinsindendir), bir gri tonlama görüntüsü için iki giriş (lo, hi). Tek bir çağrıda en fazla 32 eşik sağlanabilir; bu da find_blobs() metodunu bu kadar esnek kılan şeydir: kırmızı, yeşil ve mavi işaretçiler eş zamanlı olarak izlenebilir, her biri döndürülen listeye kendi noktalarını katar ve her noktanın code özelliği hangi eşikle eşleştiğini belirtir.

Yukarıdaki draw_rectangle() ve draw_cross() çağrıları, yakalanan çerçeveyi IDE önizlemesi için işaretler. Nokta sonucu zaten b.rect (4’lü demet biçiminde sınırlayıcı kutu) ile b.cx / b.cy (tam sayı ağırlık merkezi) değerlerini taşır, dolayısıyla tespiti çerçeveye geri çizmek iki metot çağrısından ibarettir.

5.25.2. Sonucun içerdikleri

Her Blob, tespit edicinin bölge hakkında ölçtüğü her şeyi bir araya paketleyen bir öznitelik demetidir. Özellikler dört gruba ayrılır.

Sınırlayıcı kutu ve ağırlık merkezi grubu – x, y, w, h, rect, cx, cy, cxf, cyf – noktanın konumunu tanımlar. rect, çizim metotlarının beklediği (x, y, w, h) 4’lü demetidir; cx ve cy ağırlık merkezini tam sayı piksel koordinatlarında verir; cxf ve cyf ise ağırlık merkezini alt-piksel kayan nokta koordinatlarında verir; bu da bir üst kaynaklı kalibrasyonun kesirli konumları önemsediği durumlarda kullanışlıdır.

Biçim tanımlayıcılarıpixels, area, density, perimeter, roundness, elongation, compactness, rotation – noktanın neye benzediğini tanımlar. pixels, geçen piksellerin sayısıdır; area, eksene hizalı sınırlayıcı kutunun alanıdır (w * h); density ise bu ikisinin oranıdır ve katı bir dikdörtgen için 1.0‘a yaklaşır, ince bir çapraz çizgi için 0.0‘a doğru düşer. roundness ve compactness, noktanın ne kadar yuvarlak olduğunu farklı geometrik bakış açılarından puanlar (roundness ikinci dereceden momentlerden, compactness çevre-alan oranından); elongation, kolaylık için 1.0 - roundness değeridir. rotation, ana eksenin radyan cinsinden yönelimidir ve uzamış noktalarda en doğrudur, neredeyse yuvarlak olanlarda ise gürültülü hale gelir (belirsiz bir eksenin iyi tanımlanmış bir yönü yoktur).

Eşik ve birleştirme meta verilericode, count – hangi eşiğin eşleştiğini ve döndürülene kaç kaynak noktanın birleştirildiğini belirtir. code, eşleşen her eşik için bir biti ayarlanmış 32 bitlik bir bit eşlemidir (tek eşik code == 1 verir; birleştirilmiş çok renkli bir nokta birden fazla bite sahip olabilir); count, merge=True birden fazla tespiti bir araya getirmediği sürece 1‘dir.

Köşeler grubu – corners, min_corners – noktanın döndürülmüş geometrisini verir. corners, noktanın konturundan çekilen (x, y) uç noktalarının, sol üstten saat yönünde sıralanmış 4’lü demetidir; min_corners, noktayı çevreleyen en küçük alanlı döndürülmüş dikdörtgenin köşelerinin 4’lü demetidir. En küçük alanlı dikdörtgen sıkı uyumdur; eksene hizalı rect ise piksel ızgarasına hizalanmış gevşek uyumdur. Her ikisi de, bir alt aşamanın yönelimli bir kutuya mı yoksa düz bir kutuya mı ihtiyaç duyduğuna bağlı olarak kullanışlıdır.

Bir ikili eşik maskesine karşı gösterilen bir nokta tespiti. Sol panel, geçen piksellerden oluşan eğik bir oval maske gösterir. Sağ panel ise aynı maskeyi etrafına çizilmiş eksene hizalı sınırlayıcı kutu, ortada bir çarpı ile işaretlenmiş ağırlık merkezi, ovali gerçek açısında saran kesik çizgili en küçük alanlı döndürülmüş dikdörtgen ve ovalin uzun yönü boyunca uzanan, ağırlık merkezinden geçen ana eksen çizgisiyle işaretlenmiş olarak gösterir.

Bir nokta; eksene hizalı sınırlayıcı kutuyu (rect, x, y, w, h), ağırlık merkezini (cx, cy veya alt-piksel cxf, cyf), en küçük alanlı döndürülmüş dikdörtgeni (min_corners artı rotation) ve aşağıdaki modül düzeyindeki yardımcılar tarafından hesaplanan isteğe bağlı ana / yan eksen çizgilerini taşır.

5.25.4. Örtüşen noktaları birleştirme

merge=True, sınırlayıcı dikdörtgenleri örtüşen noktaları bir araya getirmek için sonuç listesini son işleme tabi tutar. Doğal kullanımı, kameranın rengini aynasal parlamalar, gölge çizgileri veya nesne üzerindeki eşleşmeyen aydınlatma nedeniyle birden fazla eşiklenmiş bölge olarak gördüğü bir hedefi tespit etmektir: tek bir kırmızı top, birlikte ele alındığında topun izini çizen üç ya da dört küçük kırmızı nokta olarak geri dönebilir. merge=True ile üç nokta tek bir büyük nokta haline gelir, rect birleşimi kapsar, code birleştirilen noktaların kodlarının bit düzeyinde OR işlemidir (böylece çok renkli bir birleştirme hangi renklerin katkıda bulunduğunu belirtir) ve count kaç kaynak noktanın birleştirildiğini bildirir.

margin, örtüşme testinden önce sınırlayıcı dikdörtgenleri büyütür veya küçültür. margin=2 ile sınırlayıcı dikdörtgenleri birbirinin 2 piksel yakınına gelen noktalar yine de birleşir; margin=-2 ile yalnızca sınırlayıcı dikdörtgenleri en az 2 piksel örtüşen noktalar birleşir. Doğal ayarlama: eşiğin bitişik parçalara böldüğü noktaları ele almak için pozitif kenar boşluğu; sıkıca gruplanmış ayrı nesneleri ayrı tutmak için negatif kenar boşluğu.

merge_cb, birleştirme gerçekleşmeden önce her aday çift üzerinde çalışır. Geri çağırma iki noktayı alır ve birleştirmeye izin vermek için True, engellemek için False döndürür. Bu, geometrik kuralın kaçırdığı birleştirmeleri çapraz denetlemek için doğru araçtır – örneğin, rotation açıları bir eşikten fazla uyuşmayan iki noktayı birleştirmeyi reddetmek ya da küçük olan yalnızca beneklenme ise küçük bir noktayı çok daha büyük bir noktayla birleştirmeyi reddetmek.

5.25.5. İzdüşüm histogramları

x_hist_bins_max ve y_hist_bins_max, her noktaya isteğe bağlı izdüşüm histogramları ekler. Bir izdüşüm histogramı, bir eksen boyunca geçen piksellerin sayısıdır: X ekseni histogramı, noktanın sınırlayıcı kutusu içinde sütun başına geçen pikselleri toplar ve Y ekseni histogramı satır başına toplar. Her ikisinin de varsayılanı sıfırdır – sıfır olmayan bir max sağlanmadıkça histogramlar hesaplanmaz, aksi takdirde her tespite iş yükü ekleyeceklerdir.

Hesaplandıklarında histogramlar, bir uygulamanın üzerinde daha fazla analiz yürütebileceği ucuz bir 1 boyutlu sinyal sağlar: noktanın içindeki dikey bir şeridin konumunu tespit etmek, iki renkli bir hedefin kırılma noktasını bulmak, uzun eksen boyunca kaç boşluk göründüğünü saymak. Bunlar, her Blob üzerinde x_hist_bins ve y_hist_bins özellikleri olarak doldurulur.

5.25.6. Ek geometrik yardımcılar

Bir noktayı alıp istenen ölçümü döndüren birkaç ek geometrik ölçü, modül düzeyindeki işlevler olarak bulunur:

  • image.get_solidity(), noktanın katılığını döndürür – pikseller, dışbükey örtünün alanına bölünür. Katı, dolu bir bölge 1.0‘a yakındır; içbükeyliklere sahip bir nokta (bir at nalı, parmakları açılmış bir el) bunun çok altına düşer.

  • image.get_convexity(), dışbükeyliği döndürür – dışbükey örtü çevresinin, noktanın çevresine bölümü. Mükemmel dışbükey bir nokta 1.0‘dır; pürüzlü veya çentikli noktalar daha düşüktür.

  • image.get_major_axis_line() ve image.get_minor_axis_line(), döndürülmüş en küçük alanlı dikdörtgenden türetilen, noktanın ana ve yan eksenleri boyunca Line nesneleri döndürür.

  • image.get_enclosing_circle(), noktayı çevreleyen bir Circle döndürür – bir alt aşama çizmek veya karşılaştırmak için bir daire istediğinde kullanışlıdır.

  • image.get_enclosed_ellipse(), noktanın en küçük alanlı dikdörtgenine yazılmış bir elips için (cx, cy, rx, ry, rotation) 5’li demetini döndürür. Değerler doğrudan draw_ellipse() metoduna beslenir.

5.25.7. Bir eşiği otomatik öğrenme

Bir nokta tespit edicisi, ancak çalıştırıldığı eşikler kadar iyidir ve bir hedef renk için doğru eşiği bulma işi başlı başına bir sorundur. İki yaygın desen bu işi azaltır.

Birincisi IDE’de etkileşimli seçimdir: bir çerçeve yakalayın, hedef rengin bir örneğinin etrafına bir dikdörtgen sürükleyin ve IDE’nin eşik düzenleyicisinin gördüğü LAB sınırlarını bildirmesine izin verin. Bu sınırlar betiğe find_blobs() eşikleri olarak düşer ve tespit edici hazırdır.

İkincisi programatik otomatik öğrenmedir: kamerada çalışan bir kalibrasyon rutini bir çerçeve yakalar, hedefin bulunduğu bilinen bir yamanın histogramını alır (roi= ile get_histogram()) ve yamanın değer aralığını histogramdan get_percentile() ile okur. 5. yüzdelik dilim her kanalın alt sınırını, 95. ise üst sınırını ayarlar ve her iki uçtaki başıboş aykırı pikselleri yok sayar. Bir RGB565 görüntüsünde tek bir yüzdelik dilim çağrısı üç LAB kanalının tümünü bir kerede bildirir, dolayısıyla iki çağrı find_blobs() metodunun beklediği altı sayıyı üretir:

h = img.get_histogram(roi=patch)
lo = h.get_percentile(0.05)
hi = h.get_percentile(0.95)
threshold = (lo.l_value, hi.l_value,
             lo.a_value, hi.a_value,
             lo.b_value, hi.b_value)