scipy Python:确定像素是否被其他颜色的连续区域包围

14ifxucb  于 2023-03-18  发布在  Python
关注(0)|答案(1)|浏览(162)

我有一个PNG图像,我转换成一个只有1和0的Numpy数组。我想找到0的连续区域,并且在这个连续区域上的所有1都变成0。
我已经得到了具有以下内容的毗连区:

labels, num_features = label(temp)

但是我不知道如何确定一个像素是否被一个连续的区域包围。
请注意,我不能使用膨胀在我的情况下,只是填补白色,因为它损害了图像在其他一些地区。
下面是一个例子:0为紫色,1为白色:

这就是我想要的结果:

iq3niunx

iq3niunx1#

使用cv2.findContours,我们可以找到外部轮廓,然后使用cv2.drawContours用所需的颜色填充轮廓。
更有趣的部分是自动计算“填充颜色”(假设这是必需的)。
注:我们还可以假设同一图像中的不同轮廓可能具有不同的颜色。
假设我们事先知道颜色,使用以下阶段:

  • 将图像转换为灰度。
  • 查找轮廓(使用cv2.RETR_EXTERNAL忽略内部轮廓)。
  • 迭代等值线并在每个等值线上绘制一个填充的等值线。

代码示例:

import cv2
import numpy as np

img = cv2.imread('contiguous_zones.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # Convert to grayscale.
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)  # Apply automatic thresholding (use THRESH_OTSU) and invert polarity since background is white.

# Find contours (use cv2.RETR_EXTERNAL for ignoring the inner contours).
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Iterate contours
for c in contours:
    # Draw contour over the original image with the mean color.
    cv2.drawContours(img, [c], 0, (177, 35, 159), -1)

查找每个轮廓的颜色:
基于following answer,我们可以找到轮廓内的平均颜色。
有一个小的变化-我们必须忽略轮廓内的白色像素。
为了提高精度,我们还可以将掩模放大一点。
查找轮廓c颜色的示例代码:

mask = np.zeros((img.shape[0], img.shape[1]), np.uint8)
cv2.drawContours(mask, [c], 0, 255, -1)
mask = mask & thresh  # Remove inner part from the mask (black pixels in thresh).
mask = cv2.erode(mask, np.ones((5, 5), np.uint8))  # Erode the mask for improving accuracy (there are few white pixels from the outer contour).
mean_color = cv2.mean(img, mask=mask)  # Compute the mean color of the pixels inside the mask.
mean_color = np.round(mean_color[0:3]).astype(int)  # Take first 3 elements applies BGR - (the 4'th element is alpha) and convert to int.

完整代码示例:

import cv2
import numpy as np

img = cv2.imread('contiguous_zones.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # Convert to grayscale.
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)  # Apply automatic thresholding (use THRESH_OTSU) and invert polarity since background is white.

# Find contours (use cv2.RETR_EXTERNAL for ignoring the inner contours).
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Iterate contours
for c in contours:
    # Get the average color inside a contour
    # The mean color excludes the inner white pixels
    ############################################################################
    # https://stackoverflow.com/questions/54316588/get-the-average-color-inside-a-contour-with-open-cv
    mask = np.zeros((img.shape[0], img.shape[1]), np.uint8)
    cv2.drawContours(mask, [c], 0, 255, -1)
    mask = mask & thresh  # Remove inner part from the mask (black pixels in thresh).
    mask = cv2.erode(mask, np.ones((5, 5), np.uint8))  # Erode the mask for improving accuracy (there are few white pixels from the outer contour).
    #cv2.imshow('mask', mask)  # Show mask for testing
    #cv2.waitKey()
    mean_color = cv2.mean(img, mask=mask)  # Compute the mean color of the pixels inside the mask.
    mean_color = np.round(mean_color[0:3]).astype(int)  # Take first 3 elements applies BGR - (the 4'th element is alpha) and convert to int.
    ############################################################################

    # Draw contour over the original image with the mean color.
    cv2.drawContours(img, [c], 0, mean_color.tolist(), -1)

# Show results for testing:
cv2.imshow('thresh', thresh)
cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()

img(输出):

thresh

相关问题