gpt4 book ai didi

python - 分水岭分割后提取对象

转载 作者:行者123 更新时间:2023-12-02 16:27:33 25 4
gpt4 key购买 nike

我需要在下面的图像中分割种子并将其裁剪。

/image/ndOkX.jpg

它们可能彼此非常接近,有时甚至重叠,因此我选择使用分水岭算法来完成此任务。

在绘制返回的标记的轮廓之后,我的结果在下图中,如您所见,我在定义适用于它的良好标记时遇到了问题。概述了各个种子,但是我不想有很多内在的线条。

/image/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()

    结果:
    enter image description here

    关于python - 分水岭分割后提取对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60479830/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com