gpt4 book ai didi

python - OpenCV 分水岭 + otsu with distanceTransform

转载 作者:太空宇宙 更新时间:2023-11-03 22:21:44 24 4
gpt4 key购买 nike

我正在尝试使用 OpenCV 分水岭算法 ( https://docs.opencv.org/3.1.0/d3/db4/tutorial_py_watershed.html ),但稍作改动。文档中有这行代码:

ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)

如果可能的话,我需要用 Otsu 的阈值法替换这个阈值法。我使用的大部分代码都来自 OpenCV 分水岭文档:

img = np.load('file.npy')
kernel = np.ones((3,3), np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations = 2)
sure_background = cv2.dilate(opening, kernel, iterations = 50)
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_foreground = cv2.threshold(dist_transform, 0, dist_transform.max(), cv2.THRESH_BINARY + cv2.THRESH_OTSU)

最后一行导致错误:

/tmp/build/80754af9/opencv_1512687413662/work/modules/imgproc/src/thresh.cpp:1402: error: (-215) src.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) in function threshold

我知道在分水岭文档中,这一步没有 Otsu 的阈值,但我必须设置一个脚本以在非常多的图像上执行,对我来说很重要的是它不需要阈值为每个图像明确设置。

有没有办法使用 Otsu 的阈值在这个对象(cv2.distanceTransform 的结果)上运行这个方法(cv2.threshold)?


编辑

老实说,我没有在其他库中寻找类似的解决方案,但现在我在 scikit-image 库(http://scikit-image.org/docs/dev/auto_examples/segmentation/plot_watershed.html)中找到了分水岭算法。它似乎在使用上没有那么复杂,可能会满足我的需要。但我问的可能对我(或其他人)以后有用,所以如果有人有解决方案,请分享它:)


编辑 2

当我通过添加此行对值进行规范化时:

dist_transform = cv2.normalize(dist_transform, None, 255,0, cv2.NORM_MINMAX, cv2.CV_8UC1)

它成功了,但不幸的是,还有另一个问题。当我像这样运行 cv2.watershed 方法时:

ret, labels = cv2.connectedComponents(sure_foreground)
labels = labels + 1
labels[unknown == 255] = 0
labels = cv2.watershed(img, labels) # this line is wrong

我收到的错误消息是:

error: (-215) src.type() == (((0) & ((1 << 3) - 1)) + (((3)-1) << 3)) && dst.type() == (((4) & ((1 << 3) - 1)) + (((1)-1) << 3)) in function watershed

原因是我使用的图像是1 channel 数组,分水岭方法需要3 channel 数组(我在上面添加了加载图像)。有没有办法解决这个问题?数据类型正确(图像是 uint8,标签 - int32)。

最佳答案

您的问题在 documentation 中指定:

Currently, the Otsu’s method is implemented only for 8-bit images.

还有一个来自距离的变换:

dst – Output image with calculated distances. It is a 32-bit floating-point, single-channel image of the same size as src .

这意味着距离变换的输出与使用 Otsu 方法的阈值的输出不兼容......

可能的解决方案

您可以截断浮点值并将矩阵转换为 uint8 以便能够使用它。

np.uint8(dist_transform)

这可能会丢失一些数据,您必须小心负值和超过 255 的值...numpy 只会给您这样的值:

a = np.array([3.4, 2.7, 8.9, -1.2, 267])
np.uint8(a)
# result => array([ 3, 2, 8, 255, 11], dtype=uint8)

如您所见,您得到 -1.2 => 255 和 267 => 11 并且其他数字被截断...您可能需要考虑对数字进行四舍五入或将值标准化...。一切都取决于您的目标是什么以及你的距离变换看起来如何。

希望这对您有所帮助,并记得注意 src 和 dst 类型,这通常是 OpenCV 最常见的错误。

关于python - OpenCV 分水岭 + otsu with distanceTransform,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48382621/

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