Watershed Algorithm

Kategori: Computer Vision , 03 Şubat 2020 , JanFranco


Bir masa üzerinde 6 madeni para düşünelim. Bu paraların özelliği birbirlerine değiyor olmalarıdır. Önceki yazılarımızda öğrendiğimiz teknikleri uygulayarak paraları tespit etmeye çalışalım. Kütüphaneleri ve resmi alalım:


import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('../data/pennies.jpg')
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
plt.imshow(img)
plt.show()
>>

Watershed

Paralar üzerinde çok fazla detay olduğundan threshold yöntemini uyguladığımızda sorunlar çıkabilir. Bu sebeple blurlayalım:


blurred = cv2.medianBlur(img, 35)
plt.imshow(blurred)
plt.show()
>>

Watershed

Threshold için resmi griye çevirelim:


gray = cv2.cvtColor(blurred, cv2.COLOR_RGB2GRAY)
plt.imshow(gray, cmap='gray')
plt.show()
>>

Watershed

Threshold yöntemini uygulayalım:


_, thresh = cv2.threshold(gray, 160, 255, cv2.THRESH_BINARY_INV)
plt.imshow(thresh, cmap='gray')
plt.show()
>>

Watershed

Son olarak contour tespiti yapalım ve bulduğumuz contourları çizelim:


_, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
    if hierarchy[0][i][3] == -1:
        cv2.drawContours(img, contours, i, (0, 0, 255), 10)

plt.imshow(img)
plt.show()
>>

Watershed

Görüldüğü gibi paraları tespit edemedik. 6 para olmasına rağmen tek bir obje bulduk. Bunun sebebi paraların birbirine yapışık olması. İşte bu tarz problemlerde Watershed algoritmasını kullanabiliriz. Watershed algoritması, coğrafyada kullanılan arazi renklendirme uygulamasını baz alır. İsmi de oradan gelmektedir. Algoritmayı kullanmadan önce ilk olarak distanceTransform methodundan bahsedelim. distanceTransform methodunu aşağıdaki resim üzerinden anlatalım:

Watershed

Burada 7x7'lik bir binary resim mevcut. Resmin tam ortasına int(7/2) değeri atanır. Yani 3. Bu pikselden yukarı aşağı sağ sola veya çapraza gidilirse 3 değeri 1 düşere 2 olur. Yani kenalara olan uzaklığa göre pikselerin değeri değişmektedir. Bu method sayesinde paraları tespit edebileceğiz:


distTransform = cv2.distanceTransform(thresh, cv2.DIST_L2, 5)
plt.imshow(distTransform, cmap='gray')
plt.show()
>>

Watershed

Bu resmin thresholdunu alırsak:


_, fg = cv2.threshold(distTransform, 0.7 * distTransform.max(), 255, 0)
plt.imshow(fg, cmap='gray')
plt.show()
>>

Watershed

İlk threshold ile bu thresholdu birbirinden çıkaralım:


fg = np.uint8(fg)
unknown = cv2.subtract(thresh, fg)
plt.imshow(unknown, cmap='gray')
plt.show()
>>

Watershed

connectedComponents ile objeleri etiketleyelim:


_, markers = cv2.connectedComponents(fg)
markers = markers+1
markers[unknown == 255] = 0
plt.imshow(markers, cmap='gray')
plt.show()
>>

Watershed

Etiketlenmiş objeleri watershed algoritmasına gönderirsek, image segmentation tekniğini uygulayarak objeleri renklendirecek:


markers = cv2.watershed(img, markers)
plt.imshow(markers)
plt.show()
Resim üzerinde ilk teknikleri uygulayarak contourları çizmiştik. Temizlemek için resmi tekrar import edelim:


img = cv2.imread('../data/pennies.jpg')
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
Tekrar contourları bulalım:


_, contours, hierarchy = cv2.findContours(markers, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
    if hierarchy[0][i][3] == -1:
        cv2.drawContours(img, contours, i, (255, 0, 0), 10)

plt.imshow(img)
plt.show()
>>

Watershed

Watershed


Sonraki Yazı: Watershed with Custom Seeds
Yorumlar

Henüz bir yorum bulunmuyor.
Yorum bırakın