python - 如何使用 Python OpenCV 在图像中获得泛滥区域及其边界?
问题描述
我有一张像这样的图像,它只有黑白:
我想只获得带有边框的图像的淹没区域cv2.floodfill
,就像这样(请原谅我的绘画技巧):
这是我当前的代码:
# Copy the image.
im_floodfill = cv2.resize(actual_map_image, (500, 500)).copy()
# Floodfill from point (X, Y)
cv2.floodFill(im_floodfill, None, (X, Y), (255, 255, 255))
# Display images.
cv2.imshow("Floodfilled Image", im_floodfill)
cv2.waitKey(0)
我得到的输出等于原始图像。我怎样才能只得到有边界的洪水区域?
编辑:我想从“竞技场”内的任何白点填充,比如图像中的红点(X,Y)。我希望只有竞技场内小圆圈的外边界和外墙的内边界。
EDIT2:我已经完成了一半:
# Resize for test purposes
actual_map_image = cv2.resize(actual_map_image, (1000, 1000))
actual_map_image = cv2.cvtColor(actual_map_image, cv2.COLOR_BGR2GRAY)
h, w = actual_map_image.shape[:2]
flood_mask = np.zeros((h+2, w+2), dtype=np.uint8)
connectivity = 8
flood_fill_flags = (connectivity | cv2.FLOODFILL_FIXED_RANGE | cv2.FLOODFILL_MASK_ONLY | 255 << 8)
# Copy the image.
im_floodfill = actual_map_image.copy()
# Floodfill from point inside arena, not inside a black dot
cv2.floodFill(im_floodfill, flood_mask, (h/2 + 20, w/2 + 20), 255, None, None, flood_fill_flags)
borders = []
for i in range(len(actual_map_image)):
borders.append([B-A for A,B in zip(actual_map_image[i], flood_mask[i])])
borders = np.asarray(borders)
borders = cv2.bitwise_not(borders)
# Display images.
cv2.imshow("Original Image", cv2.resize(actual_map_image, (500, 500)))
cv2.imshow("Floodfilled Image", cv2.resize(flood_mask, (500, 500)))
cv2.imshow("Borders", cv2.resize(borders, (500, 500)))
cv2.waitKey(0)
我明白了:
但是,我觉得这是获取边界的错误方式,而且它们是不完整的。
解决方案
我认为最简单,最快的方法是用中灰色填充竞技场。然后只提取灰色像素并找到它们的边缘。看起来像这样,但请记住,超过一半的行是注释和调试语句 :-)
#!/usr/bin/env python3
import cv2
# Load image as greyscale to use 1/3 of the memory and processing time
im = cv2.imread('arena.png', cv2.IMREAD_GRAYSCALE)
# Floodfill arena area with value 128, i.e. mid-grey
floodval = 128
cv2.floodFill(im, None, (150,370), floodval)
# DEBUG cv2.imwrite('result-1.png', im)
# Extract filled area alone
arena = ((im==floodval) * 255).astype(np.uint8)
# DEBUG cv2.imwrite('result-2.png', arena)
# Find edges and save
edges = cv2.Canny(arena,100,200)
# DEBUG cv2.imwrite('result-3.png',edges)
以下是调试输出的 3 个步骤,显示处理顺序:
result-1.png 看起来像这样:
result-2.png 看起来像这样:
result-3.png 看起来像这样:
顺便说一句,您不必编写任何 Python 代码来执行此操作,因为您可以使用 ImageMagick 在终端中执行此操作,ImageMagick包含在大多数 Linux 发行版中,可用于 macOS 和 Windows。这里使用的方法和我上面Python中使用的方法完全对应:
magick arena.png -colorspace gray \
-fill gray -draw "color 370,150 floodfill" \
-fill white +opaque gray -canny 0x1+10%+30% result.png
推荐阅读
- google-cloud-automl - 如何通过 AutoML Vision 中的验证测试
- asp.net-web-api - 回调信号中心服务器
- php - 将 MySQL 表 Moodle 导出到 Excel 文件
- php - Laravel 5.8:如何将两个争论传递给 Event & Listener
- c# - ArgumentOutOfRangeException:索引和长度必须引用字符串中的位置
- django-rest-framework - 为什么 DRF browsableapi 不显示创建序列化程序表单
- node.js - 在Node js中将csv转换为json
- c++ - 如何从 qtreeview 给模型两个可点击的图标
- python - Laravel:命令“python失败。退出代码:1(一般错误)'python'不被识别为内部或外部命令,可操作
- c++ - 在替换字符串中的单个字符时修改哈希值(c ++)