Herkese merhabalar.
Aylardır duvarda duran yapışkan nottaki “MATLAB Trafik işareti tespit etme makalesi yaz” uyarısını dikkate alma zamana geldi. Bu yazımda bir proje için hazırlamış olduğum programı anlatmaya çalışacağım. Öncelikle şunu unutmamak gerekir ki herhangi bir problemi farklı yollardan çözmek mümkündür. Trafik işaretlerini tespit etmek için renk, şekil gibi ölçütler kullanılabilir.
Üzerinde çalıştığım projede toplam 15 adet görüntü ve bu görüntülerde de yaklaşık 32 tane trafik işareti vardı. Bazı analizlerden sonra bu görüntülerde klasik yöntemlerin aksine farklı bir yöntem ile sonuca ulaşabileceğimi fark ettim. Bunun ne olduğuna yazının ilerleyen safhalarında değineceğim. Yazmış olduğum bu programın çekeceğiniz herhangi bir trafik işareti içeren görüntüde çalışacağı garantisini veremiyorum ancak benim çalıştığım görüntülerde 0 (sıfır) hatalı sonuç ve 32 işaretin yaklaşık 29unu doğru bir şekilde tespit etti. Tespit edemediği 3 işaret ise çok ufak boyutlarda olduğu için tespit edilemedi.
Herhangi bir görüntü işleme programının başarısını “F Score” denen ölçüt ile ölçüyoruz. Bu skor hatalı tespitler ve eksik tespitleri işin içine katarak hesaplıyor. İşte formül:
F = 2 . (precision . recall) / (precision + recall)
precision: Doğru sonuç sayısının, programın döndürdüğü tüm sonuçların sayısına bölümü
recall: Programın döndürdüğü doğru sonuç sayısının, toplamda dönmesi gereken sonuç sayısına bölümü
Görüntüde nesne bulmak gibi çalışmalarda genelde yapılan işlemler şu şekildedir.
- Görüntü kalitesi arttırılır.
- Uygun filtreler uygulanır.
- Görüntü işleme algoritması çalıştırılır.
Yavaş yavaş yazmış olduğum programa geçelim. Programın çalışma mantığını anlatmakta fayda var. Analiz kısmından başlayalım.
Üzerinde çalışacağım görüntüleri analiz ettiğimde, benden tespit edilmesi beklenen trafik işaretlerinin HSV renk uzayına göre inceledim ve 3. parametre olan Value “parlaklık” değerinin resmin geri kalan kısımlarından farklı olduğunu, yani işaretleri ayırt ederken bu değeri kullanmanın işimi göreceğini fark ettim. Bu aşamadan sonra farklılığı belirgin hale getirerek, tespit edilmesi gereken işaretlerin her birinin daire oluşturduğunu ve bu dairenin içinde mutlaka boşluk veya boşluklar olduğunu gördüm. Bu şu demek oluyor. Eğer görüntüdeki nesnelerin içerisinde boşluk varsa bu trafik işaretidir. Sanırım biraz havada kaldı. Aşağıda resimlerle anlatmaya çalıştım. Bu kısımları kodlarla beraber incelerseniz sistem kafamızda oturacaktır. Şunu tekrar belirtmek isterim. Bu yöntem her görüntüde çalışmayacaktır. Bana sunulmuş 15 görüntüyü analiz edip böyle bir yöntemi uyguladım. Bunu seçmemdeki amaç kolay olması, çok hızlı olması ve programın sadece bu 15 görüntüde çalışacak olmasıdır. Performansa değinmek için söylüyorum, örneğin böyle bir proje için line-detection algoritması kullansaydık ve şekillere göre trafik işareti olup olmadığına karar verseydik çok daha uzun sürede sonuca ulaşabilirdik. Siz de elinizdeki projelere uygun yöntemler, ufak hileler üretip optimum sonuca ulaşabilirsiniz.
İşleyiş kısmına gelecek olursak:
Programı yapmış olduğu işlerin farklılığına göre 3 fonksiyona bölmeyi tercih ettim.
İlk fonksiyonumuz ana fonksiyon. Görüntüyü fonksiyona parametre olarak geçiyoruz ve ana fonksiyonumuz diğer iki fonksiyonu çağırıyor.
function [] = trafficSignDetector( input_img ) % Ana Fonksiyon oImg = imread(input_img); % Orjinal Resmi oku binImg = trafficSignToBinImg(oImg); % Orjinal resmi ikilik formata çevirip gerekli iyileştirmeleri yapan fonk. displayTrafficSign(binImg, oImg); % İkilik resimdeki verilere göre trafik işaretlerini bulup gösteren fonk. end
Görüntünün ikilik resme dönüştürülüp, üzerinde filtre uygulamaları, dilation ve erosion gibi morfolojik işlemler yapılıyor. Bu işlemleri uygularken parametre değerleriyle en iyi sonucu alana kadar oynamak gerekli olacaktır.
function [ BW ] = trafficSignToBinImg( trafikResmi ) hsvFormat= rgb2ntsc(trafikResmi); % RGB renk uzayından NTSC renk uzayına dönüşüm yapılıyor hsValue = hsvFormat(:,:,3); % HSV -> 3. parametre yani value (brighness veya parlaklık) kullanılıyor out = filter2(fspecial('average', 2), hsValue); % filtre kullanılarak kalite arttırılıyor BW = im2bw(10*out,0.2); % Görüntü siyah-beyaz hale getiriliyor ve beyazlıkların belirginliği arttırılıyor BW = bwareaopen(BW, 30); % Küçük objeler temizleniyor BW = imdilate(BW, strel('disk',4)); % Dilation morfolojik işlemi uygulanıyor BW = imdilate(BW,strel('disk',1)); % Dilation morfolojik işlemi uygulanıyor BW = imerode(BW, strel('diamond', 3)); % Erode morfolojik işlemi uygulanıyor BW = filter2(fspecial('average', 3), BW); % Kenarlıkları kalınlaştırıyoruz end
Görüntü işleme algoritmasının çalıştığı fonksiyonumuz.
function [] = displayTrafficSign( bin_img, original ) [num, L] = bwboundaries(bin_img, 4, 'noholes'); % Objelerin sınırlarını seçer stats = regionprops(L, 'basic'); % objelerin özelliklerini elde eder figure, imshow(original); % Orjinal resmi ekrana basar for k=1 : length(num) % Resimdeki tüm objeleri tarar coords = stats(k).BoundingBox; % Sınır koordinatlar x1 = coords(1); y1 = coords(2); x2 = x1 + coords(3); y2 = y1 + coords(4); xCoords = [x1 x2 x2 x1 x1]; yCoords = [y1 y1 y2 y2 y1]; x2 = floor(x2); y2 = floor(y2); eulerNumber = bweuler(bin_img(y1:y2, x1:x2)); % Objenin içinde boşluk var mı? if(eulerNumber<1) % Eğer objenin içinde boşluk veya boşluklar varsa bu bir trafik işaretidir, çerçeve içine al hold on plot(xCoords, yCoords, 'g-', 'LineWidth', 2); hold off end end end
Daha iyi anlaşılması bakımından adım adım resimli anlatıma geçelim.
2. HSV renk uzayının 3. parametresi kullanılarak görüntü ikilik formata dönüşüyor
3. Küçük objeler siliniyor ve katsayı kullanarak beyaz alanlar belirgin hale getiriliyor
6. Görüntüyü yumuşatmak için average filtresi kullanılıyor
7. Tüm objeler taranarak algoritmaya uygun objeler çerçeve içine alınıyor
Merak ettikleriniz için yorum bırakmaktan çekinmeyiniz.
Sevgi & Saygı.
Kaynaklar
1. www.mathworks.com/products/matlab/
2. https://en.wikipedia.org/wiki/RGB_color_model
3. https://en.wikipedia.org/wiki/HSL_and_HSV
4. https://en.wikipedia.org/wiki/Binary_image