我正在尝试使用 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: 错误: (-215) src.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) 在函数阈值中
我知道在分水岭文档中,这一步中没有 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
我得到这个作为错误消息:
错误:(-215) src.type() == (((0) & ((1 << 3) - 1)) + (((3)-1) << 3)) && dst.type() == (((4) & ((1 << 3) - 1)) + (((1)-1) << 3)) 在函数分水岭
原因是我使用的图像是 1 通道数组,分水岭方法需要 3 通道数组(我在上面添加了加载图像)。有没有办法解决这个问题?数据类型正确(图像为 uint8,标签 - int32)。