我有一张像这样的图像,它只是黑白的:
我只想使用 获取带有边框的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)
Run Code Online (Sandbox Code Playgroud)
我得到的输出等于原始图像。我怎样才能只得到有边界的洪水区域?
编辑:我想从“竞技场”内的任何白点进行洪水填充,例如图像中的红点(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)
Run Code Online (Sandbox Code Playgroud)
我明白了:
然而,我觉得这是获取边界的错误方法,而且它们是不完整的。
我认为最简单、最快的方法就是用中灰色填充竞技场。然后只提取灰色像素并找到它们的边缘。看起来像这样,但请记住一半以上的行是注释和调试语句:-)
#!/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)
Run Code Online (Sandbox Code Playgroud)
以下是调试输出的 3 个步骤,显示了处理顺序:
result-1.png 看起来像这样:
result-2.png 看起来像这样:
result-3.png 看起来像这样:
顺便说一句,您不必编写任何 Python 代码来执行此操作,因为您只需在终端中使用 ImageMagick 即可执行此操作,大多数Linux 发行版中都包含 ImageMagick,并且适用于 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
Run Code Online (Sandbox Code Playgroud)