如何在NumPy数组中为值为0的像素区域绘制轮廓
如何给图像中0值像素区域绘制轮廓
你的代码问题在于,你只是找到了所有0值像素的最小/最大行、列范围,然后把这个矩形区域内的所有像素改成了1,这自然只会得到一个包围整个0值区域的矩形,而不是每个0值区域的边缘轮廓。咱们来用两种方法解决这个问题:
方法一:用OpenCV(最简便的专业方法)
OpenCV有专门的轮廓检测API,能精准提取每个连通的0值区域的轮廓,代码示例如下:
import numpy as np import cv2 from PIL import Image import matplotlib.pyplot as plt # 读取图像并转为灰度图 input_image = Image.open(path_to_image).convert("L") input_image_array = np.asarray(input_image).astype(np.uint8) # 找轮廓:cv2.RETR_EXTERNAL只找最外层轮廓,cv2.CHAIN_APPROX_SIMPLE压缩轮廓点 contours, _ = cv2.findContours(input_image_array, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 创建一个和原图一样的空白画布,用来绘制轮廓 contour_image = np.zeros_like(input_image_array) # 绘制轮廓:颜色设为255(白色),线条宽度2 cv2.drawContours(contour_image, contours, -1, 255, 2) # 展示结果 plt.imshow(contour_image, cmap='gray') plt.show()
方法二:纯Numpy/Matplotlib实现(不用OpenCV)
如果不想依赖OpenCV,可以用形态学膨胀操作来提取轮廓:膨胀0值区域后,减去原0值区域,得到的就是边缘部分:
import numpy as np from PIL import Image import matplotlib.pyplot as plt from scipy.ndimage import binary_dilation # 读取图像并转为灰度数组 input_image = Image.open(path_to_image).convert("L") input_image_array = np.asarray(input_image).astype(np.uint8) # 创建0值区域的掩码 zero_mask = input_image_array == 0 # 定义膨胀的结构元素(3x3的正方形,用来扩展边缘) structuring_element = np.ones((3,3), dtype=bool) # 膨胀掩码 dilated_mask = binary_dilation(zero_mask, structure=structuring_element) # 轮廓 = 膨胀后的掩码 - 原掩码(得到边缘部分) contour_mask = dilated_mask ^ zero_mask # 将轮廓区域设为255(白色),其余保持0 result_image = np.where(contour_mask, 255, 0).astype(np.uint8) # 展示结果 plt.imshow(result_image, cmap='gray') plt.show()
这两种方法都能准确提取每个0值连通区域的轮廓,而不是一个大矩形。你可以根据自己的环境选择合适的方案~
内容的提问来源于stack exchange,提问作者izanthir
相关产品推荐
相关产品推荐

