基于Numpy/OpenCV实现黑白图像边缘白色像素保留的技术求助
问题描述
处理黑白图像,仅保留与黑色像素相邻的白色像素,其余白色像素转为黑色。已掌握循环列表实现的方法,但希望改用Numpy实现,尝试的代码要么导致图像全黑,要么无任何变化,附上尝试代码及处理前后图像,寻求Numpy或OpenCV解决方案。
尝试代码
from PIL import Image import numpy as np a = Image.open('a.png') a = a.convert('L') a_np = np.array(a) # 查看数组 print(a_np) # 输出示例: # array([[0, 0, 0, ..., 0, 0, 0], # [0, 0, 0, ..., 0, 0, 0], # ..., # [0, 0, 0, ..., 0, 0, 0]], dtype=uint8) mask = np.pad(a_np[1:-1,1:-1],1,mode='wrap') != 0 print(mask) # 输出示例:全False的数组 print(np.where(mask == True)) # 输出示例:(array([ 98, 98, ..., 981]), array([393, ..., 686])) a_np[mask] = 0 print(a_np) # 输出全0数组 print(np.where(a_np == 1)) # 输出空数组
处理前后图像
- 处理前图像:黑白图像,包含大面积白色区域及黑色轮廓/区域
- 处理后期望图像:仅保留与黑色像素相邻的白色边缘,其余白色区域转为黑色
解决方案
方法一:Numpy实现
核心思路:标记原始白色像素,通过移位操作检查每个白色像素的8邻域是否存在黑色像素,仅保留满足条件的白色像素。
from PIL import Image import numpy as np # 读取图像并转为灰度数组(0=黑,255=白) img = Image.open('a.png').convert('L') img_np = np.array(img) # 标记所有白色像素 white_pixels = img_np == 255 # 创建数组,标记每个像素的8邻域是否存在黑色像素 has_black_neighbor = np.zeros_like(img_np, dtype=bool) # 移位检查8个方向的邻域 has_black_neighbor[1:] |= img_np[:-1] == 0 # 上 has_black_neighbor[:-1] |= img_np[1:] == 0 # 下 has_black_neighbor[:,1:] |= img_np[:,:-1] == 0 # 左 has_black_neighbor[:,:-1] |= img_np[:,1:] == 0 # 右 has_black_neighbor[1:,1:] |= img_np[:-1,:-1] == 0 # 左上 has_black_neighbor[1:,:-1] |= img_np[:-1,1:] == 0 # 右上 has_black_neighbor[:-1,1:] |= img_np[1:,:-1] == 0 # 左下 has_black_neighbor[:-1,:-1] |= img_np[1:,1:] == 0 # 右下 # 保留符合条件的白色像素,其余设为黑色 result_np = np.where(white_pixels & has_black_neighbor, 255, 0).astype(np.uint8) # 保存结果 result_img = Image.fromarray(result_np) result_img.save('result_numpy.png')
方法二:OpenCV实现
利用形态学腐蚀操作,快速提取白色区域的边缘(即与黑色相邻的白色像素)。
import cv2 import numpy as np # 读取灰度图像 img = cv2.imread('a.png', cv2.IMREAD_GRAYSCALE) # 二值化,确保图像只有黑(0)白(255)两色 _, binary_img = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 创建3x3结构元素,用于腐蚀操作 kernel = np.ones((3,3), np.uint8) # 腐蚀白色区域,得到内部的白色部分 eroded = cv2.erode(binary_img, kernel, iterations=1) # 原始白色区域减去腐蚀后的区域,得到边缘(与黑色相邻的白色像素) result_cv = binary_img - eroded # 保存结果 cv2.imwrite('result_opencv.png', result_cv)
内容的提问来源于stack exchange,提问作者user18615293
相关产品推荐
相关产品推荐

