Image Segmentation with Watershed Algorithm

จาก Morange Wiki

Image Segmentation with Watershed Algorithm

วัตถุประสงค์

  • บทนี้จะเรียนรู้เกี่ยวกับการทำ Marker-based ในรูปภาพ โดยใช้ watershed algorithm
  • เรียนรู้การใช้งานฟังก์ชั่น cv2.watershed()

ทฤษฎี

  • ในการทำรูปภาพในโหมดสีเทานั้น จะสามารถดูมุมมองได้จาก topographic surface ( มุมมองลักษณะภูมิประเทศ ) โดยที่ความเข้มสูงหมายถึงยอดของความสูงที่สุดและเนินที่นูนออกมา ในขณะที่ความเข้มต่ำหมายถึงจุดต่ำของหุบเขา ด้วยการเริ่มต้นกรอกทุกหุบเขาแยก (local minima) ด้วยสีที่แตกต่างกันของน้ำ ( labels ) ในขณะที่น้ำนั้นมีการเพิ่มขึ้นจนถึงยอดโดยการไล่ระดับสี (gradients) ในบริเวณใกล้เคียงน้ำจากหุบเขา ( hill ) ที่แตกต่างกันนั้นจะเห็นได้ชัดว่า สีจะมีความแตกต่างกันโดยจะเริ่มต้นที่จะผสานกัน เพื่อหลีกเลี่ยงการเพิ่มขึ้นของ barriers ในสถานที่ที่ผสานกันของน้ำ โดยจะสามารถทำงานต่อด้วยกสนเพิ่มขึ้นของน้ำและเพิ่ม barriers และใน bariers โดยจะช่วยให้เห็นการแบ่งส่วน โดยสิ่งนี้เรียกว่า "ปรัชญา" Philosophy
  • โดยสามารถเยี่ยมชมเว็บ CMM ได้เพื่อดูการข้อมูลเพิ่มเติม [| CMM Link]
  • ใน OpenCV นั้นจะช่วยให้สามารถทำ marker-based watershed algorithm ได้ด้วยการระบุซึ่งทุกจุดของ hill นั้นจะมีการรวม ( merged ) และทำให้ไม่สามารถตอบโต้ในรูปภาพได้โดยรับ labels ที่แตกต่างกันใน object

Code

  • ในต่อไปนี้จะทำตัวอย่างเกี่ยวกับวิธีการที่จะใช้ในการหา Distance Transform พร้อมกับการใช้ watershed เพื่อแบ่งแยกเป็นกลุ่มๆ โดยวัตถุจะสัมผัสกัน
  • ในการพิจารณาเหรียญด้านล่างนี้ จะติดกัน


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

img = cv2.imread('Coin512.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

cv2.imshow('image',thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()


มีข้อผิดพลาดในการสร้างรูปย่อ: ไฟล์สูญหาย
Input

มีข้อผิดพลาดในการสร้างรูปย่อ: ไฟล์สูญหาย
Output
  • โดยต่อไปนี้จะเป็นการลบนอดย์ที่อยู่ในวงกลมสีขาว โดยใช้ morphological opening โดยการลบภาพวัตถุพวกนั้น อาจจะใช้ morphological closing เข้ามาร่วมด้วย ยกตัวอย่าง


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

img = cv2.imread('Coin512.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

 # noise removal
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)

 # sure background area
sure_bg = cv2.dilate(opening,kernel,iterations=3)

# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)

# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)

cv2.imshow('image',unknown)
cv2.waitKey(0)
cv2.destroyAllWindows()

  • และในผลลัพธ์นั้นจะได้ภาพที่ผ่านฟังก์ชั่น thresholded image เรียบร้อยแล้ว โดยบางพื้นที่ของเหรียญนั้น จะเห้นได้ว่าติดต่อกัน โดยต่อไปจะนำมันออกจากกัน โดยบางกรณีนั้นจะสนใจการแบ่งส่วนเฉพาะด้านหน้า (foreground) เท่านั้น โดยจะไม่ได้สนใจส่วนที่ติดกัน ดังนั้น การเปลี่ยนไปใช้ Erosion ) ดังตัวอย่าง


มีข้อผิดพลาดในการสร้างรูปย่อ: ไฟล์สูญหาย
ภาพ Foreground

มีข้อผิดพลาดในการสร้างรูปย่อ: ไฟล์สูญหาย
ภาพ Background