簡體   English   中英

分水嶺分割后提取對象

[英]Extracting objects after watershed segmentation

我需要分割下圖中的種子並裁剪它們。

https://i.stack.imgur.com/ndOkX.jpg

它們可能非常接近,有時會重疊,所以我選擇使用分水嶺算法來完成這項任務。

在繪制返回的標記的輪廓之后,我的結果如下圖所示,正如您所看到的,我在定義用於應用它的好標記時遇到了問題。 概述了單個種子,但有許多我不想要的內線。

https://i.stack.imgur.com/BtOfj.jpg

我將如何刪除它們或定義更好的標記?

我正在運行的代碼:

from skimage.feature import peak_local_max
from skimage.segmentation import watershed
import matplotlib.pyplot as plt
from scipy import ndimage
import cv2 as cv
import imutils
import numpy as np

img = cv.imread("image.jpg");
blur = cv.GaussianBlur(img,(7,7),0)


#color space change
mSource_Hsv = cv.cvtColor(blur,cv.COLOR_BGR2HSV);
mMask = cv.inRange(mSource_Hsv,np.array([0,0,0]),np.array([80,255,255]));
output = cv.bitwise_and(img, img, mask=mMask)

#grayscale
img_grey = cv.cvtColor(output, cv.COLOR_BGR2GRAY)

#thresholding
ret,th1 = cv.threshold(img_grey,0,255,cv.THRESH_BINARY + cv.THRESH_OTSU)

#dist transform
D = ndimage.distance_transform_edt(th1)

#markers
localMax = peak_local_max(D, indices=False, min_distance=20, labels=th1)
markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]

#apply watershed
labels = watershed(-D, markers, mask=th1)
print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1))

# loop over the unique labels

for label in np.unique(labels):
    if label == 0:
        continue

    # draw label on the mask
    mask = np.zeros(img_grey.shape, dtype="uint8")
    mask[labels == label] = 255

    # detect contours in the mask and grab the largest one
    cnts = cv.findContours(mask.copy(), cv.RETR_EXTERNAL,
        cv.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    c = max(cnts, key=cv.contourArea)

    cv.drawContours(img, cnts, -1, (0, 255, 0), 2)


cv.imshow("segmented",img)
cv.waitKey(0)

您可以合並應用以下條件的每兩個輪廓:

  • 合並輪廓的凸包面積接近兩個輪廓的面積之和。

以下解決方案使用一種“蠻力”方法,嘗試將每個輪廓與所有其他輪廓合並(效率不高)。

這是一個工作代碼示例(請閱讀評論):

from skimage.feature import peak_local_max
from skimage.segmentation import watershed
import matplotlib.pyplot as plt
from scipy import ndimage
import cv2 as cv
import imutils
import numpy as np

img = cv.imread("image.jpg");
blur = cv.GaussianBlur(img,(7,7),0)


#color space change
mSource_Hsv = cv.cvtColor(blur,cv.COLOR_BGR2HSV);
mMask = cv.inRange(mSource_Hsv,np.array([0,0,0]),np.array([80,255,255]));
output = cv.bitwise_and(img, img, mask=mMask)

#grayscale
img_grey = cv.cvtColor(output, cv.COLOR_BGR2GRAY)

#thresholding
ret,th1 = cv.threshold(img_grey,0,255,cv.THRESH_BINARY + cv.THRESH_OTSU)

#dist transform
D = ndimage.distance_transform_edt(th1)

#markers
localMax = peak_local_max(D, indices=False, min_distance=20, labels=th1)
markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]

#apply watershed
labels = watershed(-D, markers, mask=th1)
print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1))


contours = []

# loop over the unique labels, and append contours to all_cnts
for label in np.unique(labels):
    if label == 0:
        continue

    # draw label on the mask
    mask = np.zeros(img_grey.shape, dtype="uint8")
    mask[labels == label] = 255

    # detect contours in the mask and grab the largest one
    cnts = cv.findContours(mask.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    c = max(cnts, key=cv.contourArea)

    ## Ignore small contours
    #if c.shape[0] < 20:
    #    continue

    # Get convex hull of contour - it' going to help when merging contours
    hull = cv.convexHull(c)

    #cv.drawContours(img, c, -1, (0, 255, 0), 2)
    cv.drawContours(img, [hull], -1, (0, 255, 0), 2, 1)

    # Append hull to contours list
    contours.append(hull)


# Merge the contours that does not increase the convex hull by much.
# Note: The solution is kind of "brute force" solution, and can be better.
################################################################################
for i in range(len(contours)):
    c = contours[i]

    area = cv.contourArea(c)

    # Iterate all contours from i+1 to end of list
    for j in range(i+1, len(contours)):
        c2 = contours[j]

        area2 = cv.contourArea(c2)

        area_sum = area + area2

        # Merge contours together
        tmp = np.vstack((c, c2))
        merged_c = cv.convexHull(tmp)

        merged_area = cv.contourArea(merged_c)

        # Replace contours c and c2 by the convex hull of merged c and c2, if total area is increased by no more then 10%
        if merged_area < area_sum*1.1:
            # Replace contour with merged one.
            contours[i] = merged_c
            contours[j] = merged_c
            c = merged_c
            area = merged_area
################################################################################


# Draw new contours in red color
for c in contours:
    #Ignore small contours
    if cv.contourArea(c) > 100:
        cv.drawContours(img, [c], -1, (0, 0, 255), 2, 1)


cv.imshow("segmented",img)
cv.waitKey(0)
cv.destroyAllWindows()

結果:
在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM