填补图像 borders/contours 之间的空白
Filling gaps between borders/contours in images
我有两张图像想合并在一起,fill/remove 合并后边框之间的间隙。左边的图像是边缘,右边的图像是掩膜。 (请忽略右图的小补丁,不过能把它去掉就好了)
合并后的预期结果是
但这是目前取得的成绩
我尝试了 scikit-image api 的不同策略,包括:
ndi.binary_opening
、ndi.binary_closing
、morphology.{erosion, dilation, opening, closing}
但其中 none 似乎有效。
我认为这可能是一个策略的基础...
第 1 步:
从 "edge image" 开始。随机选择任何白色像素。使用该像素作为种子或起点用黑色进行洪水填充。这应该填充边缘的一侧。记住种子,并获得新的填充黑色区域的质心(可能还有区域)。将填充后的图像反转,得到图像另一部分的质心。
你现在知道了边缘两侧的质心 - 如下图红色标记:
第 2 步:
现在转到蒙版图像。也许使用 dilation/erosion 来填补任何小洞。然后在图像上 运行 "labelling" 以获得连续黑色斑点及其质心和区域的列表。 Select 面积最大的斑点。
您现在应该有最大斑点的质心,如下面绿色标记:
第 3 步:
现在选择两个红色点中与绿色点较近的一个,并使用相应的种子进行填充。
最好在步骤 1 中随机重复选择白色种子点,直到获得不同的质心,而不是进行反演。那是因为如果你只是反转并得到质心,你不知道一个好的种子像素。不确定质心是不是好种子。
看来你需要找到 mask 函数的质心 (CoM) 来确定填充哪一侧,然后使用 floodFill
到 edge 来自 CoM 的图像作为种子点。
您可以尝试这样的操作:
# Calculate the Center of Mass
com = np.zeros(2)
sum = np.zeros(2)
for x in range(0, nu_of_rows):
for y in range(0, num_of_cols):
com += image[x][y] * np.array([x,y])
sum += image[x][y]
com /= sum
# FloodFill a new image
h, w = mask_img.shape[:2]
new_image = mask_img.copy()
temp = np.zeros((h+2,w+2),np.uint8) # Needs to be 2 pixels wider/higher
cv2.FloodFill(new_image, temp, coi, 255, flags=cv2.FLOODFILL_MASK_ONLY)
如果 edge 和 mask 图像中的线条具有值 255
并且背景 0
.如果不是这种情况,请先使用以下命令反转您的两个图像:
inverted_img = cv2.bitwise_not(img)
注意:我没有用你的图片测试这个,而是用我的一张。所以你可能不得不在这里和那里改变一些东西。这是我的粗略示例工作:
我有两张图像想合并在一起,fill/remove 合并后边框之间的间隙。左边的图像是边缘,右边的图像是掩膜。 (请忽略右图的小补丁,不过能把它去掉就好了)
合并后的预期结果是
但这是目前取得的成绩
我尝试了 scikit-image api 的不同策略,包括:
ndi.binary_opening
、ndi.binary_closing
、morphology.{erosion, dilation, opening, closing}
但其中 none 似乎有效。
我认为这可能是一个策略的基础...
第 1 步:
从 "edge image" 开始。随机选择任何白色像素。使用该像素作为种子或起点用黑色进行洪水填充。这应该填充边缘的一侧。记住种子,并获得新的填充黑色区域的质心(可能还有区域)。将填充后的图像反转,得到图像另一部分的质心。
你现在知道了边缘两侧的质心 - 如下图红色标记:
第 2 步:
现在转到蒙版图像。也许使用 dilation/erosion 来填补任何小洞。然后在图像上 运行 "labelling" 以获得连续黑色斑点及其质心和区域的列表。 Select 面积最大的斑点。
您现在应该有最大斑点的质心,如下面绿色标记:
第 3 步:
现在选择两个红色点中与绿色点较近的一个,并使用相应的种子进行填充。
最好在步骤 1 中随机重复选择白色种子点,直到获得不同的质心,而不是进行反演。那是因为如果你只是反转并得到质心,你不知道一个好的种子像素。不确定质心是不是好种子。
看来你需要找到 mask 函数的质心 (CoM) 来确定填充哪一侧,然后使用 floodFill
到 edge 来自 CoM 的图像作为种子点。
您可以尝试这样的操作:
# Calculate the Center of Mass
com = np.zeros(2)
sum = np.zeros(2)
for x in range(0, nu_of_rows):
for y in range(0, num_of_cols):
com += image[x][y] * np.array([x,y])
sum += image[x][y]
com /= sum
# FloodFill a new image
h, w = mask_img.shape[:2]
new_image = mask_img.copy()
temp = np.zeros((h+2,w+2),np.uint8) # Needs to be 2 pixels wider/higher
cv2.FloodFill(new_image, temp, coi, 255, flags=cv2.FLOODFILL_MASK_ONLY)
如果 edge 和 mask 图像中的线条具有值 255
并且背景 0
.如果不是这种情况,请先使用以下命令反转您的两个图像:
inverted_img = cv2.bitwise_not(img)
注意:我没有用你的图片测试这个,而是用我的一张。所以你可能不得不在这里和那里改变一些东西。这是我的粗略示例工作: