gpt4 book ai didi

python - 分水岭分割不包括单独的对象?

转载 作者:太空狗 更新时间:2023-10-30 00:52:50 25 4
gpt4 key购买 nike

问题

使用 this answer创建一个分割程序,它正在错误地计算对象。我注意到单独的对象被忽略或图像采集不佳。

我数了 123 个对象,程序返回 117,如下图所示。红色圈出的对象好像不见了:

Missing objects

使用来自 720p 网络摄像头的以下图像:

Picture with 123 objects

代码

import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import label
import urllib.request


# https://stackoverflow.com/a/14617359/7690982
def segment_on_dt(a, img):
border = cv2.dilate(img, None, iterations=5)
border = border - cv2.erode(border, None)

dt = cv2.distanceTransform(img, cv2.DIST_L2, 3)
plt.imshow(dt)
plt.show()
dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(np.uint8)
_, dt = cv2.threshold(dt, 140, 255, cv2.THRESH_BINARY)
lbl, ncc = label(dt)
lbl = lbl * (255 / (ncc + 1))
# Completing the markers now.
lbl[border == 255] = 255

lbl = lbl.astype(np.int32)
cv2.watershed(a, lbl)
print("[INFO] {} unique segments found".format(len(np.unique(lbl)) - 1))
lbl[lbl == -1] = 0
lbl = lbl.astype(np.uint8)
return 255 - lbl


# Open Image
resp = urllib.request.urlopen("/image/YUgob.jpg")
img = np.asarray(bytearray(resp.read()), dtype="uint8")
img = cv2.imdecode(img, cv2.IMREAD_COLOR)

## Yellow slicer
mask = cv2.inRange(img, (0, 0, 0), (55, 255, 255))
imask = mask > 0
slicer = np.zeros_like(img, np.uint8)
slicer[imask] = img[imask]

# Image Binarization
img_gray = cv2.cvtColor(slicer, cv2.COLOR_BGR2GRAY)
_, img_bin = cv2.threshold(img_gray, 140, 255,
cv2.THRESH_BINARY)

# Morphological Gradient
img_bin = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN,
np.ones((3, 3), dtype=int))

# Segmentation
result = segment_on_dt(img, img_bin)
plt.imshow(np.hstack([result, img_gray]), cmap='Set3')
plt.show()

# Final Picture
result[result != 255] = 0
result = cv2.dilate(result, None)
img[result == 255] = (0, 0, 255)
plt.imshow(result)
plt.show()

问题

如何计算丢失的元素?

最佳答案

回答您的主要问题,分水岭不会删除单个对象。分水岭在您的算法中运行良好。它接收预定义的标签并相应地执行分割。

问题是您为距离变换设置的阈值太高,它消除了单个对象的微弱信号,从而阻止了对象被标记并发送到分水岭算法。

enter image description here

距离变换信号较弱的原因是颜色分割阶段分割不当,难以设置单一的阈值来去除噪声和提取信号。

为了解决这个问题,我们需要进行适当的颜色分割,并在分割距离变换信号时使用自适应阈值而不是单一阈值。

这是我修改的代码。我通过 @user1269942 合并了颜色分割方法在代码中。额外的解释在代码中。

import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import label
import urllib.request


# https://stackoverflow.com/a/14617359/7690982


def segment_on_dt(a, img, img_gray):

# Added several elliptical structuring element for better morphology process
struct_big = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
struct_small = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))

# increase border size
border = cv2.dilate(img, struct_big, iterations=5)
border = border - cv2.erode(img, struct_small)




dt = cv2.distanceTransform(img, cv2.DIST_L2, 3)
dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(np.uint8)

# blur the signal lighty to remove noise
dt = cv2.GaussianBlur(dt,(7,7),-1)

# Adaptive threshold to extract local maxima of distance trasnform signal
dt = cv2.adaptiveThreshold(dt, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, -9)
#_ , dt = cv2.threshold(dt, 2, 255, cv2.THRESH_BINARY)


# Morphology operation to clean the thresholded signal
dt = cv2.erode(dt,struct_small,iterations = 1)
dt = cv2.dilate(dt,struct_big,iterations = 10)

plt.imshow(dt)
plt.show()

# Labeling
lbl, ncc = label(dt)
lbl = lbl * (255 / (ncc + 1))
# Completing the markers now.
lbl[border == 255] = 255

plt.imshow(lbl)
plt.show()

lbl = lbl.astype(np.int32)
cv2.watershed(a, lbl)
print("[INFO] {} unique segments found".format(len(np.unique(lbl)) - 1))
lbl[lbl == -1] = 0
lbl = lbl.astype(np.uint8)
return 255 - lbl

# Open Image
resp = urllib.request.urlopen("/image/YUgob.jpg")
img = np.asarray(bytearray(resp.read()), dtype="uint8")
img = cv2.imdecode(img, cv2.IMREAD_COLOR)


## Yellow slicer
# blur to remove noise
img = cv2.blur(img, (9,9))

# proper color segmentation
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, (0, 140, 160), (35, 255, 255))
#mask = cv2.inRange(img, (0, 0, 0), (55, 255, 255))

imask = mask > 0
slicer = np.zeros_like(img, np.uint8)
slicer[imask] = img[imask]



# Image Binarization
img_gray = cv2.cvtColor(slicer, cv2.COLOR_BGR2GRAY)

_, img_bin = cv2.threshold(img_gray, 140, 255,
cv2.THRESH_BINARY)


plt.imshow(img_bin)
plt.show()
# Morphological Gradient
# added
cv2.morphologyEx(img_bin, cv2.MORPH_OPEN,cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)),img_bin,(-1,-1),10)
cv2.morphologyEx(img_bin, cv2.MORPH_ERODE,cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)),img_bin,(-1,-1),3)

plt.imshow(img_bin)
plt.show()

# Segmentation
result = segment_on_dt(img, img_bin, img_gray)
plt.imshow(np.hstack([result, img_gray]), cmap='Set3')
plt.show()

# Final Picture
result[result != 255] = 0
result = cv2.dilate(result, None)
img[result == 255] = (0, 0, 255)
plt.imshow(result)
plt.show()

最终结果:找到 124 个独特的项目。发现了一个额外的项目,因为其中一个对象被分成了 2 个。通过适当的参数调整,您可能会得到您正在寻找的确切数字。但我建议买一个更好的相机。

enter image description here enter image description here

关于python - 分水岭分割不包括单独的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53379938/

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