OpenCV中基于距离变换图的Watershed算法报错求助
问题原因与修复方案
错误提示src.type() == CV_8UC3 && dst.type() == CV_32SC1明确指出两个核心问题:
- 输入的3通道图像必须是
uint8类型(8位无符号整数) - 标记图
markers必须是int32类型(32位有符号整数)
你的代码里,距离变换生成的dist是浮点型图像,转3通道后依然是浮点类型,不满足第一个要求;另外标记图的布尔值判断也存在潜在问题。
修复步骤
1. 修正距离变换图像的类型
距离变换输出的是01范围的浮点图,需要先缩放至0255并转换为uint8,再转3通道:
filled_img = filled_img.astype(np.uint8) dist = cv2.distanceTransform(filled_img, cv2.DIST_L2, 0) # 缩放并转换为uint8类型 dist = (dist / dist.max() * 255).astype(np.uint8) dist3d = cv2.cvtColor(dist, cv2.COLOR_GRAY2BGR)
2. 确保标记图类型与赋值正确
cv2.connectedComponents返回的标记图默认是int32,但建议显式确认;同时修正未知区域的赋值逻辑:
ret, markers = cv2.connectedComponents(sure_fg) markers = markers + 1 # 用像素值判断而非布尔值,避免潜在类型问题 markers[unknown == 255] = 0 # 显式转为int32,确保符合要求 markers = markers.astype(np.int32)
3. 修正分割线绘制代码
原代码是比较操作而非赋值,同时需要复制图像避免修改原图:
watershed_img = crop_img.copy() # 替换为赋值操作 watershed_img[watershed_markers == -1] = [255, 0, 0]
完整修复后的核心代码
# 处理距离变换图像 filled_img = filled_img.astype(np.uint8) dist = cv2.distanceTransform(filled_img, cv2.DIST_L2, 0) dist = (dist / dist.max() * 255).astype(np.uint8) dist3d = cv2.cvtColor(dist, cv2.COLOR_GRAY2BGR) # 生成并修正标记图 ret, markers = cv2.connectedComponents(sure_fg) markers = markers + 1 markers[unknown == 255] = 0 markers = markers.astype(np.int32) # 执行分水岭分割 watershed_markers = cv2.watershed(dist3d, markers) # 绘制分割结果 watershed_img = crop_img.copy() watershed_img[watershed_markers == -1] = [255, 0, 0] plt.figure(figsize=(20,20)) plt.imshow(watershed_img, 'jet') plt.show()
补充说明
你之前在原始彩色图上能成功执行分水岭,是因为原图本身就是uint8类型的3通道图像,天然满足OpenCV的输入要求;而距离变换后的图像你保留了浮点类型,才触发了类型不匹配的断言错误。
内容的提问来源于stack exchange,提问作者dvdrplus
相关产品推荐
相关产品推荐

